124 lines
18 KiB
Markdown
124 lines
18 KiB
Markdown
# 第六章 编辑器与引擎工作流设计与实现
|
||
|
||
上一章已经围绕渲染引擎运行时的核心模块展开分析,说明了底层图形抽象、资源管理、场景组织、渲染主链以及脚本系统的实现方式。在此基础上,本章进一步转向引擎的可视化工作界面与工程工作流部分,重点说明当前项目中的编辑器如何围绕场景编辑、资源浏览、参数调整、运行验证和脚本支撑等需求组织起来。对于本课题而言,编辑器是连接资源系统、场景系统、渲染系统和脚本系统的直接工作入口,也是展示整个系统工程完成度的重要部分。
|
||
|
||
## 6.1 编辑器在引擎中的定位
|
||
|
||
### 6.1.1 编辑器作为引擎工作界面
|
||
|
||
当前项目中的编辑器由 `Application`、`EditorLayer`、`EditorWorkspace` 以及各类面板共同构成,其初始化过程直接建立在现有引擎能力之上。编辑器启动时,系统首先完成窗口渲染器初始化,随后初始化 `ResourceManager` 并设置项目根目录,在此基础上创建 `EditorContext`、初始化脚本运行时、建立 ImGui 后端桥接,并由 `ViewportHostService` 接管编辑器视口所需的离屏渲染资源。完成这些准备后,`EditorLayer` 被挂接到应用层级系统中,编辑器界面才开始进入逐帧更新与绘制阶段。
|
||
|
||
从这一结构可以看出,编辑器直接复用引擎已有的资源系统、渲染链路、场景数据和脚本运行时能力。编辑器中的界面显示、视口输出和运行模式切换都以统一的上下文对象为中心展开,这使得编辑器天然具备“所见即当前引擎状态”的特点,也保证了论文中对编辑器功能的讨论能够真实反映项目的工程实现情况。
|
||
|
||
### 6.1.2 编辑器承担的核心任务
|
||
|
||
结合当前代码结构,编辑器主要承担以下几类任务。其一是场景编辑任务,包括场景层级浏览、对象选择、重命名、父子层级调整以及组件参数检查。其二是资源管理任务,包括 `Assets` 目录浏览、文件夹导航、资源创建、重命名、删除、移动以及导入状态反馈。其三是渲染验证任务,即通过 `Scene` 与 `Game` 两类视口把引擎渲染结果以不同用途展示出来,其中前者面向编辑过程,后者面向运行结果。其四是脚本与调试支撑任务,包括脚本程序集重建、脚本运行时重载、日志查看、错误定位以及运行模式控制。
|
||
|
||
为了支撑这些任务,编辑器内部通过 `EditorContext` 对事件总线、选择管理器、场景管理器、项目管理器、撤销管理器和视口宿主服务进行统一组织。这样一来,不同面板虽然在界面上彼此独立,但在数据层和事件层是相互联通的。例如层级面板中的对象选择会同步到 Inspector 面板,Project 面板中的资源选择会切换 Inspector 的检查对象,Game 视口中的输入帧又会通过事件总线进入运行时输入系统。这种组织方式使编辑器能够围绕统一编辑上下文协同工作,形成结构完整的界面系统。
|
||
|
||
### 6.1.3 编辑器与运行时的协同关系
|
||
|
||
`EditorWorkspace` 是编辑器运行阶段的核心组织者。在工作区附加阶段,系统会依次注册 `MenuBar`、`HierarchyPanel`、`SceneViewPanel`、`GameViewPanel`、`InspectorPanel`、`ConsolePanel` 和 `ProjectPanel` 等主要面板,同时创建 `DockLayoutController`,加载启动场景,并挂接 `PlaySessionController`。在逐帧更新阶段,工作区负责驱动异步资源加载更新、运行模式更新以及各面板自身的刷新;在界面绘制阶段,再由菜单栏、停靠布局和各面板共同完成整套编辑器界面的输出。
|
||
|
||
其中较为关键的一点,是编辑器不仅负责“编辑”,还负责把编辑状态与运行状态组织成闭环。`PlaySessionController` 在进入播放模式前会保存当前编辑态场景快照,停止播放时再恢复快照,从而把运行时验证和编辑态维护分离开来。这样既能保证 `Game` 视口中脚本逻辑、输入和运行时场景更新能够被真实执行,又能在停止运行后回到稳定的编辑状态。这一协同机制使编辑器成为引擎工作流的核心组成部分。
|
||
|
||
## 6.2 编辑器界面总体布局设计
|
||
|
||
### 6.2.1 主要界面面板组成
|
||
|
||
从当前实现来看,编辑器界面主要由顶部菜单栏与运行控制区、左侧层级面板、中部双视口区域、右侧属性检查面板以及底部控制台和项目资源面板构成。各部分职责划分明确:`MenuBar` 负责主菜单与运行模式控制,`HierarchyPanel` 用于展示当前场景对象树,`SceneViewPanel` 和 `GameViewPanel` 分别承担编辑视图与运行视图显示任务,`InspectorPanel` 负责组件和资源属性编辑,`ProjectPanel` 负责项目目录与资源浏览,`ConsolePanel` 则承担日志查看与调试辅助功能。
|
||
|
||
这种布局与当前项目已经具备的功能模块一一对应。由于本项目已经具备场景系统、组件系统、材质系统、脚本系统和基础运行模式切换能力,因此编辑器界面也自然围绕这些能力组织。用户在编辑器中完成的操作路径,基本可以概括为“在 `Project` 中选择资源,在 `Hierarchy` 中定位对象,在 `Inspector` 中调整参数,在 `Scene` 中观察编辑结果,在 `Game` 中验证运行结果,并通过 `Console` 反馈调试信息”。
|
||
|
||
### 6.2.2 停靠布局与空间组织方式
|
||
|
||
编辑器界面的整体停靠布局由 `DockLayoutController` 统一管理。当前默认布局中,左侧区域停靠 `Hierarchy`,中部区域停靠 `Scene` 与 `Game` 两个标签页,右侧区域停靠 `Inspector`,底部区域停靠 `Console` 与 `Project`。这一布局与当前工程任务之间具有较强的一致性:对象结构查看放在左侧,核心视口放在中央,参数编辑放在右侧,资源与调试信息放在底部,符合渲染引擎编辑器的基本操作习惯,也便于在论文中按照“对象编辑 - 视口验证 - 资源管理 - 调试反馈”的路径说明工作流。
|
||
|
||
在界面上方,`MenuBar` 除了主菜单外,还单独绘制了运行工具条。该工具条提供播放、暂停和单步执行三个核心按钮,并直接与当前运行模式状态联动。这样一来,场景编辑、运行控制和视口验证被组织在同一工作界面中,用户无需在不同程序之间切换即可完成从编辑到验证的全过程。
|
||
|
||
此处建议插入图 6-1“编辑器整体界面截图”,重点展示顶部菜单与运行控制区、左侧 `Hierarchy`、中部 `Scene/Game` 双视口、右侧 `Inspector`、底部 `Console/Project` 的整体布局关系。
|
||
|
||
### 6.2.3 面板之间的联动关系
|
||
|
||
编辑器界面的价值不仅在于布局清晰,更在于各面板之间形成了稳定的数据联动。`HierarchyPanel` 中的选择结果会同步到选择管理器,随后 `InspectorPanel` 根据当前选中对象展示组件信息;`ProjectPanel` 中选中的材质资源则会切换 Inspector 的检查对象类型,使其进入材质资源编辑模式;`SceneViewPanel` 中通过拾取选中的对象同样会反馈到层级面板和 Inspector;而 `ConsolePanel` 中的日志信息又能够反向服务于当前脚本和运行调试。
|
||
|
||
因此,界面布局设计本质上也是工作流设计。通过统一的编辑上下文,各面板既保持了职责分工,又避免了信息孤立,使编辑器能够围绕当前引擎形成完整的操作闭环。
|
||
|
||
## 6.3 Scene 与 Game 视口实现
|
||
|
||
### 6.3.1 视口离屏渲染接入方式
|
||
|
||
当前编辑器中的视口通过离屏渲染方式接入。`ViewportPanelContent` 在绘制 `Scene` 或 `Game` 面板时,会向 `IViewportHostService` 发起 `RequestViewport` 请求,请求中包含视口类型和当前窗口可用尺寸。`ViewportHostService` 接收到请求后,会根据目标尺寸检查或创建对应的离屏颜色缓冲、深度缓冲以及相关资源视图,并在后续渲染阶段返回可供 ImGui 显示的纹理句柄。
|
||
|
||
这种设计带来的直接好处是,编辑器视口与主窗口交换链输出相互分离。视口可以根据面板尺寸独立变化,也可以附加对象 ID 缓冲、叠加层和调试通道,而不必改变主窗口渲染流程。对于需要同时存在编辑视图和运行视图的渲染引擎而言,这种离屏接入方式具有较好的工程适配性。
|
||
|
||
### 6.3.2 Scene 视口的组织方式
|
||
|
||
`Scene` 视口服务于编辑过程,因此它采用独立于运行时场景相机的编辑器相机。`ViewportHostService` 内部维护了专用的 `SceneViewCameraState`,其中包含编辑器相机对象、相机组件和相机控制器。用户在 `SceneViewPanel` 中进行观察、缩放、平移、环绕和聚焦操作时,面板会构造 `SceneViewportInput` 并提交给 `ViewportHostService`,由后者更新场景视口相机状态。
|
||
|
||
在渲染阶段,`Scene` 视口会先围绕当前编辑器相机生成渲染请求,再结合对象选择结果和叠加信息构造额外的编辑器渲染计划。当前实现中,`Scene` 视口已经支持对象 ID 读回拾取、选中轮廓高亮、网格显示、变换 Gizmo、方向指示器以及编辑器叠加层缓存等能力。这说明 `Scene` 视口是一个建立在引擎渲染链路之上的可交互编辑视图。
|
||
|
||
### 6.3.3 Game 视口的组织方式
|
||
|
||
与 `Scene` 视口不同,`Game` 视口主要用于展示运行时场景输出结果。它不使用独立的编辑器相机,而是直接依赖当前场景中的可用相机,由 `SceneRenderer` 使用正常的运行时渲染流程完成输出。若场景中不存在可用相机,则 `Game` 视口会明确给出无法渲染的状态反馈。由此可见,`Game` 视口本质上是运行时渲染结果在编辑器中的嵌入显示窗口。
|
||
|
||
`GameViewPanel` 在显示画面的同时,还会把当前帧的键盘、鼠标位置、按键状态和滚轮状态整理为 `GameViewInputFrameEvent` 并发布到事件总线中。随后 `PlaySessionController` 在播放模式下接收该事件,并将其转换为 `InputManager` 可识别的输入数据。因此,`Game` 视口不仅承担画面展示功能,还承担了编辑器到运行时输入桥接的作用。
|
||
|
||
此处建议插入图 6-2“Scene 视口与 Game 视口对照截图”,用于展示二者在观察目的、交互方式和输出内容上的差异。
|
||
|
||
### 6.3.4 视口与渲染主链的关系
|
||
|
||
无论是 `Scene` 视口还是 `Game` 视口,当前项目都没有为其单独实现一套完全不同的渲染器。两类视口都通过 `ViewportHostService` 接入现有的 `SceneRenderer` 和渲染请求生成流程,只是在相机来源、附加渲染通道和输入处理方式上有所区别。这样做的意义在于,编辑器视口所展示的结果与引擎实际渲染能力保持一致,既减少了重复实现,也使视口验证具有更高的可信度。
|
||
|
||
## 6.4 编辑器交互与调试辅助能力
|
||
|
||
### 6.4.1 对象选择与场景编辑交互
|
||
|
||
在场景编辑过程中,对象选择是最基础也是最频繁的交互。当前项目同时提供了层级树选择和视口直接拾取两种方式。前者由 `HierarchyPanel` 完成,用户可以在对象树中展开、选中、重命名对象,并通过拖放改变父子层级关系;后者则由 `Scene` 视口中的对象 ID 拾取流程完成,系统通过离屏对象 ID 纹理读回鼠标位置对应的实体编号,再同步到选择管理器。
|
||
|
||
对象选中之后,相关状态会立即反馈到其他面板。`InspectorPanel` 会切换到对应对象的组件检查界面,`Scene` 视口会刷新轮廓高亮和 Gizmo,层级面板也会保持当前选中状态。这种以统一选择状态为中心的交互方式,使用户既可以从结构树编辑场景,也可以直接在视口中完成对象定位与操作。
|
||
|
||
### 6.4.2 变换 Gizmo 与辅助显示
|
||
|
||
为了提高场景编辑效率,`Scene` 视口实现了较为完整的变换交互辅助能力。当前代码中已经包含平移、旋转、缩放三类 Gizmo,以及用于协调三者状态的 `SceneViewportTransformGizmoCoordinator`。用户可在视口中直接拖动控制柄修改对象变换,并在交互过程中结合撤销管理器记录编辑操作。这使编辑器具备了较为明确的几何编辑能力,而不只是参数填写工具。
|
||
|
||
除变换 Gizmo 外,视口中还实现了场景网格、选中轮廓、方向指示器和 HUD 叠加层等辅助显示内容。网格用于增强空间尺度感,选中轮廓用于强化对象定位,方向指示器用于辅助相机朝向理解,HUD 则用于补充编辑状态显示。这些辅助内容虽然不直接参与运行时渲染结果,但对于编辑器的可用性和调试效率具有重要作用。
|
||
|
||
此处建议插入图 6-3“Scene 视口交互界面截图”,重点展示对象选中轮廓、场景网格和变换 Gizmo 的叠加效果。
|
||
|
||
### 6.4.3 导航控制与交互状态管理
|
||
|
||
`SceneViewPanel` 还围绕编辑视口建立了较完整的导航状态管理机制。当前支持的交互包括观察、平移、环绕、聚焦选中对象以及基于键鼠组合的视角移动。面板内部会根据鼠标按键状态、快捷键状态、工具模式和当前是否存在激活中的 Gizmo 来判断当前交互应解释为视口导航还是对象编辑,并进一步决定是否由 ImGui 捕获鼠标或键盘输入。
|
||
|
||
这种交互状态管理对于编辑器而言十分关键。如果缺少这一层协调,视口观察、对象拖拽、快捷键切换和界面点击很容易相互冲突。当前项目通过专门的交互解析与导航状态更新流程,把不同输入意图区分开来,使 `Scene` 视口能够在复杂编辑状态下保持稳定响应。
|
||
|
||
## 6.5 资源与脚本工作流支撑
|
||
|
||
### 6.5.1 项目资源浏览与导入状态反馈
|
||
|
||
`ProjectPanel` 是当前编辑器中承担工程资源工作流的主要界面。该面板左侧以树状结构展示项目文件夹,右侧以资源网格方式显示当前目录内容,并提供面包屑导航、搜索、右键上下文菜单、拖放移动、重命名以及新建文件夹和材质资源等功能。对于图像资源,面板还可以直接显示缩略图预览,从而提高资源识别效率。
|
||
|
||
除了资源浏览本身,`ProjectPanel` 还会显示资源导入状态和场景加载状态。其工具栏可以读取 `ResourceManager::GetProjectAssetImportStatus()` 返回的导入快照,并把当前导入操作、耗时和成功与否展示出来;同时也会读取 `SceneManager` 维护的场景加载进度信息,用于反馈当前场景是否仍有异步资源尚未完成。这使资源管理不再停留在文件浏览层面,而是能够反映资源进入运行时之前的真实处理状态。
|
||
|
||
### 6.5.2 场景文档与运行模式工作流
|
||
|
||
编辑器中的场景工作流主要由 `SceneManager` 和 `PlaySessionController` 共同完成。`SceneManager` 负责场景创建、对象创建与删除、对象复制与粘贴、层级移动、场景加载与保存,以及场景脏标记维护;同时还支持场景快照捕获与恢复。对于编辑工作而言,这意味着场景既是可视化内容容器,也是可以被保存、恢复和回滚的文档对象。
|
||
|
||
在运行模式切换方面,`PlaySessionController` 提供了播放、停止、暂停、恢复和单步执行等控制能力,并通过事件总线与顶部运行工具条联动。进入播放模式前,控制器会保存当前编辑场景快照并清空撤销历史,然后启动运行时循环;停止播放时,再恢复编辑态快照并回到普通编辑模式。这一机制把“编辑场景”和“验证运行结果”衔接在一起,是当前编辑器工作流中最能体现工程闭环的一部分。
|
||
|
||
### 6.5.3 脚本程序集与调试支撑
|
||
|
||
当前项目已经具备基于 C# 的脚本系统,因此编辑器也必须承担脚本工作流支撑任务。`Application` 在初始化编辑器时会尝试从 `Library/ScriptAssemblies` 目录加载 `XCEngine.ScriptCore.dll`、`GameScripts.dll` 和相关运行时程序集;如果程序集不存在,编辑器会明确记录状态信息并禁用脚本类发现。与此同时,编辑器还提供了脚本程序集重建与脚本运行时重载能力,使脚本修改后能够重新进入编辑器工作流。
|
||
|
||
在对象检查层面,`InspectorPanel` 通过 `ComponentEditorRegistry` 为 `Transform`、`Camera`、`Light`、`MeshFilter`、`MeshRenderer` 和 `ScriptComponent` 等组件注册了对应的编辑器,从而使对象属性面板不仅能显示组件数据,还能承担组件参数编辑和脚本组件检查的任务。对于材质资源,Inspector 还支持单独的材质资源检查与保存流程,这进一步体现了编辑器对资源系统的深入接入。
|
||
|
||
在调试支撑方面,`ConsolePanel` 提供了日志级别筛选、折叠显示、搜索、清空、错误暂停、详情查看和源位置打开等功能。控制台不仅能够查看普通日志,还能够在播放模式中配合错误暂停机制辅助脚本调试。这样一来,脚本编译、运行验证和错误定位便能够在同一个编辑器环境中完成。
|
||
|
||
此处建议插入图 6-4“Project、Inspector 与 Console 联动截图”,用于展示资源浏览、属性编辑与日志调试在同一工作流中的组织方式。
|
||
|
||
## 6.6 本章小结
|
||
|
||
本章围绕当前项目中的编辑器与工作流实现进行了分析。可以看到,编辑器是建立在渲染引擎运行时、资源系统、场景系统和脚本系统之上的统一工作界面。在结构上,系统通过 `Application`、`EditorContext`、`EditorWorkspace` 和各类面板完成了编辑器的整体组织;在界面上,形成了菜单栏、双视口、层级面板、属性面板、项目资源面板和控制台共同构成的工作布局;在功能上,又通过对象拾取、Gizmo 交互、离屏视口、播放控制、资源导入反馈、脚本重载和日志调试等能力,把编辑、验证与调试串联成完整流程。
|
||
|
||
对于本课题后续的体积渲染扩展而言,编辑器部分的意义在于提供了稳定的验证和展示平台。无论后续体积渲染模块以何种方式接入现有渲染主链,都可以借助当前编辑器的视口、资源工作流和调试能力完成参数调整、效果观察和结果记录。因此,编辑器与工作流部分不仅体现了当前渲染引擎的工程完整性,也为后续高级渲染模块的并入提供了必要支撑。
|