Gizmo
Gizmo 是编辑器中用于世界内可视化和操作的层。它们在场景视图上绘制线条、方框、球体和标签,显示内置组件的运行情况(摄像机视锥、灯光形状、碰撞体边界),并为您提供一个交互式变换 Gizmo,以便直接在视口中移动、旋转和缩放对象。
导航场景视图
视口拥有自己的自由观察摄像机,独立于游戏的摄像机。按住鼠标右键环顾四周;按住时:
- WASD 移动,Q/E 下降和上升,Shift 加速。
- 鼠标滚轮随时向前/向后推进。
- F 将摄像机对准当前选中对象。
工具栏中的摄像机 ▾ 菜单调整导航手感——移动速度、观察灵敏度和缩放速度(当滚轮推进感觉过于急促时很方便)。您的设置会通过编辑器设置存储在不同会话之间保留。
选择对象
在场景视图中单击对象以选中它——网格通过针对网格实际边界的射线投射进行拾取,而灯光/摄像机/空对象通过单击其图标进行拾取。单击空白区域取消选择。(您也可以像以前一样从场景树中进行选择。)
变换 Gizmo
选中对象后,在场景视图中其原点处会出现一个彩色手柄。该手柄在屏幕上以恒定大小跟随摄像机。
| 模式 | 快捷键 | 手柄 | 拖拽效果 |
|---|---|---|---|
| 移动 | W |
三个轴箭头(X 红色,Y 绿色,Z 蓝色) | 沿该轴滑动对象 |
| 旋转 | E |
三个轴圆环 | 绕该轴旋转对象 |
| 缩放 | R |
三个带立方体末端的轴线 | 沿该轴缩放对象 |
悬停轴以高亮显示,然后拖拽进行操作。每次拖拽都是一个独立的撤销步骤(Ctrl+Z)。模式按钮位于场景视图工具栏中。
吸附
在工具栏中切换吸附,以将拖拽约束为固定增量——移动为 0.5 单位,旋转为 15°,缩放为 0.25。吸附会对您所做的变化进行取整,因此您可以将数值调整到整齐的网格上。
组件 Gizmo
内置组件会绘制自己的可视化器,可通过工具栏中的Gizmo ▾ 菜单进行过滤:
- 摄像机——视锥轮廓加摄像机图标。仅当该摄像机被选中时才绘制视锥。
- 灯光——方向光显示太阳圆盘和平行光线;点光源在其范围内显示线框球体;聚光灯显示线框锥体。仅对选中的灯光绘制形状,因此充满灯光的场景保持清晰可读;每盏灯光始终显示一个按其颜色着色的灯泡图标。
- 碰撞体——碰撞体边界周围的线框方框。
- 图标——灯光/摄像机(以及自定义类型)的广告牌图标。
- 选中轮廓——选中对象网格周围的橙色方框,紧贴网格的实际边界。非物质节点(灯光、摄像机、空对象)没有空间范围,因此没有轮廓——其图标和变换手柄取而代之标记选中状态。
- 网格——XZ 平面上的地面网格,中心轴线更亮。
每种类型可以独立切换,因此您可以在保持所需视觉元素的同时整理视口。
Gizmo API
Gizmo 记录到纯数据命令缓冲区(engine.Gizmos)中——无需 GPU 或 GUI 依赖——因此任何组件(包括您自己的脚本)都可以记录它们。每个形状都分解为彩色线段。
const engine = @import("engine");
fn draw(giz: *engine.Gizmos, center: engine.Vector3) void {
giz.setColor(.green);
giz.wireSphere(center, 0.5);
giz.setColor(.yellow);
giz.arrow(center, center.add(.{ .x = 0, .y = 2, .z = 0 }));
giz.setColor(engine.Gizmos.Color.rgb(0.2, 0.6, 1.0));
giz.box(center, .{ .x = 1, .y = 1, .z = 1 });
giz.label(center, "spawn point");
}
可用的图元:line、lineW、ribbon、ray、polyline、arrow、tube、box、wireCube(矩阵方向)、circle、wireSphere、wireCone、frustum 和 label。setColor、setLineWidth 和 setMatrix 应用于其后记录的所有内容;setMatrix 允许您在对象的局部空间中绘制。
线条宽度
线条具有屏幕空间的像素宽度,由每个顶点携带——渲染器将每个线段扩展为面向摄像机的四边形,因此无论摄像机距离多远,线条都能保持相同的宽度。使用 setLineWidth 设置统一宽度,或按端点变化:
giz.setLineWidth(3); // 此后所有内容为 3px
giz.arrow(a, b); // 粗大易读的箭头
// 逐渐变细至消失的彗尾轨迹——每个点有宽度。
const pts = [_]engine.Vector3{ head, mid, tail };
const widths = [_]f32{ 8, 4, 0 };
giz.ribbon(&pts, &widths);
lineW(a, b, wa, wb) 绘制从 wa 逐渐变细到 wb 的单个线段;ribbon(points, widths) 将这些线段链接成可变宽度的带状。变换 Gizmo 的移动/缩放手柄使用 setLineWidth,使它们看起来(和抓取时)像实心条而不是 1px 的线。
自定义组件 Gizmo、图标和图层
扩展通过编辑器 Gizmo 系统针对组件类型名称注册——绘制器(记录线条/标签)、广告牌图标和/或可见性图层(Unity 风格):
GizmoSystem.registerGizmo("WaypointPath", drawWaypoints);
GizmoSystem.registerIcon("WaypointPath", dvui.entypo.flag);
GizmoSystem.setLayer("WaypointPath", "Navigation");
fn drawWaypoints(giz: *engine.Gizmos, node: *const engine.SceneNode, comp: *const engine.Component) void {
_ = comp;
giz.setColor(.cyan);
giz.wireSphere(node.transform.position, 0.25);
}
自定义 Gizmo 和图标与内置组件一起遵循自定义/图标可见性切换。
备注
- Gizmo 仅在编辑器视口中渲染,绝不会在发布的游戏中渲染。
- 世界 Gizmo 会针对场景进行深度测试;变换手柄始终绘制在最上层,以便保持可抓取状态。
- 旋转手柄绕世界轴旋转;对于已旋转的对象,结果将应用于相应的欧拉角。