Version: 2019.3
UIElements 开发者指南
布局引擎

视觉树

视觉树保存窗口中的所有视觉元素。它是由称为视觉元素的轻量级节点组成的对象图。

这些节点在 C# 堆上分配(手动进行分配或通过从 UXML 模板文件加载 UXML 资源的方式进行分配)。

每个节点都包含布局信息、其绘制和重绘选项以及节点如何响应事件。

VisualElement

VisualElement 是视觉树中所有节点的公共基类。VisualElement 基类包含样式、布局数据、本地变换、事件处理程序等的属性。

VisualElement 有若干子类,包括专门的控件,它们定义了其他行为和功能。VisualElement 可包含子元素。

不需要从 VisualElement 基类进行派生来使用 UIElements。可以通过样式表和事件回调来自定义 VisualElement 的外观和行为。

连接

视觉树的根对象称为面板。新元素在连接到面板之前将被忽略。可以向现有元素添加元素来将用户界面连接到面板。

为了验证 VisualElement 是否已连接到面板,可以测试此元素的 panel 属性。未连接视觉元素时,测试将返回 null

可在 UnityEditor.UIElements 命名空间中使用容器对象的 rootVisualElement 元素将新元素添加到树中。

绘制顺序

按以下顺序绘制视觉树中的元素:

  • 先绘制父项,再绘制子项
  • 根据同级名单绘制子项

更改绘制顺序的唯一方法是在父项中重新排序 VisualElement 对象。

位置、变换和坐标系

不同的坐标系定义如下:

  • 世界坐标系:坐标相对于面板空间。面板是视觉树中的最高层级元素。
  • 局部坐标系:坐标相对于元素本身。

布局系统会计算每个元素 VisualElement.layout 属性(Rect 类型)。

layout.position 表示为相对于其父项坐标空间的像素。虽然可以直接为 layout.position 赋值,但建议您使用样式表和布局系统来定位元素。

每个 VisualElement 也有一个 layout.transform 属性(ITransform 类型)可相对于父元素对元素进行定位。默认情况下,transform 是标识。

VisualElement.layout.positionVisualElement.layout.transform 属性用于定义如何在局部坐标系和父坐标系之间进行转换。

VisualElementExtensions 静态类提供了以下扩展方法在坐标系之间转换点和矩形:

  • WorldToLocalVector2RectPanel 空间转换为元素内的参照。
  • LocalToWorldVector2Rect 转换为 Panel 空间参照。
  • ChangeCoordinatesToVector2Rect 从一个元素的局部空间转换为另一个元素的局部空间。
视觉树层级视图
视觉树层级视图

例如,在上图中,树的排列如下:

  • Panel
    • 标签部分(称为 DockArea 并标记为“Coordinates”)
    • 蓝色 VisualElement 充当根(称为“rootVisualContainer”)
      • 红色 VisualElement 充当按钮的父级(“red container”,即红色容器)
        • Button

从面板的角度来看:

  • 无论参照如何,面板的原点都是 (0, 0)
  • 根的原点在世界空间中为 (0, 22)
  • 红色容器的原点在世界空间中为 (100, 122)。它的 position 属性(在 layout 属性中定义)设置为 (100, 100),因为它相对于它的父项:根容器。
  • 按钮的原点在世界空间中为 (100, 122)。它的 position 属性(在 layout 属性中定义)设置为 (0, 0),因为它相对于它的父项:红色容器。

元素的原点是其左上角。

使用 worldBound 属性,同时考虑 VisualElement 的祖先的变换和位置,可以检索该元素的窗口空间坐标。


  • 2018–11–02 页面已修订
UIElements 开发者指南
布局引擎