当前位置: 首页 > 工具软件 > Urho3D > 使用案例 >

Urho3D用户界面

申屠健
2023-12-01

Urho3D基于矩形元素实现了一个简单的分层用户界面系统。提供的元素包括:

  • BorderImage:具有可选边框的纹理图像
  • Button按钮:按钮
  • CheckBox复选框:可以打开/关闭的按钮
  • Cursor光标:鼠标光标
  • DropDownList:将项目的垂直列表(可选可滚动)显示为弹出窗口
  • LineEdit:单行文本编辑器
  • ListView:显示可滚动的垂直项目列表
  • 菜单Menu:可显示弹出元素的按钮
  • ScrollBar:带有后退和前进按钮的滑块
  • ScrollView:子元素的可滚动视图
  • 滑块Slider:水平或垂直滑块
  • 精灵Sprite:支持亚像素定位、缩放和旋转的纹理图像。
  • 文本Text:可以是多行的静态文本
  • 工具提示ToolTip:当光标悬停在其父元素上时自动显示的弹出窗口。
  • UIElement:其他元素的容器,本身不呈现任何内容
  • View3D:渲染三维视口的窗口
  • 窗口:可移动和可调整大小的窗口

    可以使用函数GetRoot()从UI子系统查询根UI元素。它是一个与应用程序窗口一样大的空画布(UIElement),可以向其中添加其他元素。

   使用AddChild()和RemoveChild()函数,元素与场景节点类似地相互添加。每个UI元素都有一个用于存储自定义数据的用户变量VariantMap,以及添加用于标识的标记的可能性:请参阅AddTag()、RemoveTag(),SetTags()和GetChildrenWithTag()。

    要使元素对鼠标输入做出反应,必须使用SetCursor()定义鼠标光标元素,或者必须将操作系统鼠标光标设置为从输入子系统可见。

UI纹理

BorderImage和从中派生的元素指定纹理和其中用于渲染的绝对像素矩形;请参见SetTexture()和SetImageRect()。纹理由元素的颜色调制。为了实现更通用的缩放,可以通过指定每个边框的宽度将元素划分为9个子四边形或面片,请参见SetBorder()。设置零边框(默认设置)会将元素绘制为一个四边形。

绝对像素矩形与“渲染器”(Renderer)的纹理质量设置交互不良,该设置通过跳过最顶层的mipmap来减少纹理大小。UI纹理通常也不需要生成mipmap,因为它们通常以1:1的比例显示在屏幕上。因此,最好使用以下附带的UI纹理设置XML文件来禁用质量降低和mipmaps:

<texture>
    <mipmap enable="false" />
    <quality low="0" />
</texture>

UI布局和样式定义文件

用户界面元素派生自Serializable,因此可以使用其属性将其序列化为XML或从XML序列化。UI定义文件有两种使用情况:要么只定义UI元素样式(例如,按钮的每个状态的图像矩形,或者文本使用的字体),然后留下实际位置和尺寸供以后填写,要么完全定义UI元素布局。编辑器和调试控制台使用的默认元素样式定义位于文件bin/Data/UI/DefaultStyle.xml中。

UI中的函数LoadLayout()将获取一个XML文件并实例化其中定义的元素。要成为有效的XML,应该有一个根级UI元素。可以指定可选样式的XML文件;其思想是首先从该文件中读取元素的样式,然后从实际布局XML文件中填充其余部分。这样布局文件可以相对简单,因为大多数数据已经定义。

   请注意,样式不能轻易递归地应用于随后加载的元素。因此,请记住在加载时已经指定了样式文件,或者将默认样式文件分配给UI根元素,然后将由所有加载的布局拾取。这之所以有效,是因为UI子系统通过从目标父UI元素开始沿父链向上搜索样式文件。当找到样式文件或到达根元素时,搜索立即停止。还要注意,Urho3D不限制应用程序中同时使用的样式文件的数量。如果应用程序需要,可以在UI父层次结构中设置不同的样式文件。

   查看元素的C++代码以了解所有支持的属性,并查看bin/Data/UI目录中编辑器的用户界面布局以获取示例。您还可以使用编辑器应用程序创建UI布局。序列化格式类似于场景XML序列化,有三个重要区别:

   1)要实例化的元素类型和用于实例化的样式可以单独设置。例如,下面的元素定义告诉实例化一个Button元素,它应该使用样式XML文件中定义的样式“CloseButton”。

<element type="Button" style="CloseButton" />

  2) 内部子元素,例如ScrollView的滚动条,需要这样标记,以避免将它们实例化为重复项。这是通过将属性internal=“true”添加到XML元素来完成的,这在布局和样式XML文件中都是必需的。此外,必须按照元素作为父元素的子元素添加的顺序列出这些元素(如果有疑问,请参阅元素的C++构造函数代码。可以在中间省略元素。)例如:

<element type="ScrollView" />
    <element type="ScrollBar" internal="true" />
        ...customize the horizontal scroll bar attributes here...
    </element>
    <element type="ScrollBar" internal="true" />
        ...customize the vertical scroll bar attributes here...
    </element>
</element>

3)Menu和DropDownList显示的popup元素不是实际的子元素。在XML序列化中,它仍然作为子元素存储,但标记为popup=“true”属性。

以编程方式定义UI布局

      与从定义文件加载UI元素层次结构不同,在代码中创建元素同样有效(尽管对于更大的层次结构来说很麻烦),几个Urho3D示例演示了这一点。

     在这种操作模式下,即使父元素(或UI根)分配了默认样式文件,当元素添加或创建到层次结构时,样式也不会自动应用。这是因为将样式应用于元素意味着只设置一些属性,并且可能会“破坏性”,即覆盖已设置的值。对于每个创建的元素,您需要手动调用SetStyle()来指定应该应用的样式名,或者调用SetStyleAuto()来使用元素的类型名作为样式名,例如Button元素的样式“Button”。为了实现这一点,每个UI元素都应该有一个直接或通过其父元素有效分配的样式文件。用户犯的一个常见错误是构造子元素,并尝试在父元素的构造函数中对其进行样式设置,但忘记了首先在构造函数中显式分配样式文件。

子元素布局

    默认情况下,UI元素以“自由”布局模式运行,其中子元素的位置可以相对于父元素的任何角落指定,但不会自动定位或调整大小。

    要创建自动调整的子布局,可以将布局模式切换为“水平”或“垂直”。现在,子元素将根据添加顺序从左到右或从上到下定位。考虑到它们的最小和最大大小,最好调整它们的大小以适应父元素,但如果不这样做,则会调整父元素的大小。

     还可以为布局指定左、上、右和下边框宽度以及元素之间的间距。不直接支持网格布局,但可以在垂直布局中手动创建水平布局,反之亦然。

     使用函数SetLayout()或SetLayoutMode()控制布局。

子元素锚定

    允许自动调整UI层次结构的与布局分离的机制是使用锚定。首先使用SetEnableAnchor()在子元素中启用锚定,然后可以使用SetMinAnchor()和SetMaxAnchor()设置与父元素大小(范围0-1)相关的左上角和右下角。通过调用SetMinOffset()和SetMaxOffset()。最后请注意,通过调用SetPivot(),子元素的枢轴也可以在相对于其大小的0-1范围内表示,而不是仅设置水平/垂直对齐。

字体

   Urho3D同时支持FreeType(.ttf、.otf)和位图字体。

    对于FreeType字体,可以调整字形的位置。请参见SetAbsoluteGlyphOffset()为所有点大小设置固定像素偏移,或参见SetScaledGlyphOffset()设置将在应用之前与点大小相乘的浮点偏移。偏移信息也可以存储在字体文件旁边的附带XML文件中,该文件的格式如下:   

<font>
    <absoluteoffset x="xInt" y="yInt" />
    <scaledoffset x="xFloat" y="yFloat" />
</font>

UI类具有各种字体呈现的全局配置选项。默认设置类似于Windows风格的渲染,字符清晰,但间距不均匀。对于macOS风格的渲染(具有精确的间距但轮廓略模糊),请调用UI::SetFontHintLevel(FONT_HINT_LEVEL_NONE)。使用排版示例来探索这些选项,并找到适合您游戏的最佳配置。

     默认情况下,轮廓字体将被提示(与像素边界对齐),如果可能,使用字体的嵌入提示。调用SetForceAutoHint()以使用FreeType的标准自动提示,而不是每个字体的嵌入提示。

   要调整提示,请调用SetFontHintLevel()。如果级别设置为FONT_HINT_level_LIGHT,字体将垂直对齐像素网格,而不是水平对齐。在FONT_HINT_LEVEL_NONE处,提示被完全禁用。

     提示级别LIGHT和NONE允许亚像素字形定位,这大大提高了间距,尤其是在小字体大小时。默认情况下,亚像素定位仅用于12点以下的尺寸;在较大的尺寸下,每个字形都是像素对齐的。调用SetFontSubfixelThreshold更改此阈值。  

    当纹理没有像素对齐时,双线性纹理过滤会使它们看起来模糊。因此,亚像素字体纹理被过采样(水平拉伸)以减少这种模糊性,代价是额外的内存使用。默认情况下,亚像素字体使用2倍过采样。调用SetFontOversampling以更改此设置。

    亚像素定位仅水平操作。文本始终垂直像素对齐。

精灵

    精灵是一种特殊的UI元素,允许子像素(浮动)定位和缩放以及旋转,而其他元素使用整数定位来实现像素完美显示。精灵可以用来实现旋转HUD元素,例如小地图或速度计指针。

    由于自由的可转换性,无法使用GetElementAt()可靠地查询精灵。此外,由于其他元素不支持缩放和旋转,因此只有其他子画面才应该成为子画面的父对象。

光标形状

     Urho3D支持从图像定义的自定义光标形状。

     该形状可以是CursorShape枚举中的OS默认值,UI子系统会自动切换到该枚举和从该枚举中切换,但可以使用Cursor::SetShape(CursorShape)手动切换到。

     或者,可以使用字符串格式的名称来定义它们,以标识它,只能使用Cursor::SetShape(const String&)手动切换到或切换到该名称。

    有许多保留名称用于操作系统默认值:

  • Normal
  • IBeam
  • Cross
  • ResizeVertical
  • ResizeDiagonalTopRight
  • ResizeHorizontal
  • ResizeDiagonalTopLeft
  • ResizeAll
  • AcceptDrop
  • RejectDrop
  • Busy
  • BusyArrow

光标形状可以用多种不同的方式定义:

XML:

<element type="Cursor">
    <attribute name="Shapes">
        <variant type="VariantVector" >
            <variant type="String" value="Normal" />
            <variant type="ResourceRef" value="Image;Textures/UI.png" />
            <variant type="IntRect" value="0 0 12 24" />
            <variant type="IntVector2" value="0 0" />
        </variant>
        <variant type="VariantVector" >
            <variant type="String" value="Custom" />
            <variant type="ResourceRef" value="Image;Textures/UI.png" />
            <variant type="IntRect" value="12 0 12 36" />
            <variant type="IntVector2" value="0 0" />
        </variant>
    </atrribute>
</element>

C++:

UI* ui = GetSubsystem<UI>();
ResourceCache* rc = GetSubsystem<ResourceCache>();
 
Cursor* cursor = new Cursor(context_);
Image* image = rc->GetResource<Image>("Textures/UI.png");
if (image)
{
    cursor->DefineShape(CS_NORMAL, image, IntRect(0, 0, 12, 24), IntVector2(0, 0));
    cursor->DefineShape("Custom", image, IntRect(12, 0, 12, 36), IntVector2(0, 0));
}
 
ui->SetCursor(cursor);

Angelcode:

Cursor@ cursor = new Cursor();
Image@ image = cache.GetResource("Image", "Textures/UI.png");
if (image !is null)
{
    cursor.DefineShape(CS_NORMAL, image, IntRect(0, 0, 12, 24), IntVector2(0, 0));
    cursor.DefineShape("Custom", image, IntRect(12, 0, 12, 36), IntVector2(0, 0));
}
 
ui.SetCursor(cursor);

缩放比例

默认情况下,UI是像素完美的:根元素的大小等于应用程序窗口的大小。

可以使用函数SetScale()、SetWidth()和SetHeight()更改像素比例。

 类似资料: