docs: sync editor viewport host docs
This commit is contained in:
@@ -6,51 +6,226 @@
|
||||
|
||||
**源文件**: `editor/src/Application.h`
|
||||
|
||||
**描述**: 编辑器应用主入口,负责窗口渲染器、ImGui 后端、LayerStack 和 `EditorContext` 的初始化、渲染与关闭。
|
||||
**描述**: 编辑器进程的组合根,负责主窗口渲染宿主、`EditorContext`、脚本运行时、ImGui 会话与视口宿主服务的启动、逐帧驱动和关闭。
|
||||
|
||||
## 概述
|
||||
|
||||
`Application` 是当前编辑器应用真正的壳层对象。
|
||||
`Application` 不是“又一个编辑器功能模块”,而是当前 Editor 可执行程序最外层的壳。
|
||||
|
||||
它负责把几类本来分散的系统拼成一个可运行编辑器:
|
||||
它把一批必须按顺序初始化、按反向顺序关闭的系统串起来:
|
||||
|
||||
- Win32 宿主窗口句柄
|
||||
- [Platform::D3D12WindowRenderer](../Platform/D3D12WindowRenderer/D3D12WindowRenderer.md)
|
||||
- [UI::ImGuiSession](../UI/ImGuiSession/ImGuiSession.md)
|
||||
- ImGui 平台/渲染后端桥
|
||||
- `LayerStack`
|
||||
- [Core::EditorContext](../Core/EditorContext/EditorContext.md)
|
||||
- [Layers::EditorLayer](../Layers/EditorLayer/EditorLayer.md)
|
||||
- Win32 窗口句柄与窗口标题。
|
||||
- [D3D12WindowRenderer](../Platform/D3D12WindowRenderer/D3D12WindowRenderer.md)。
|
||||
- [EditorContext](../Core/EditorContext/EditorContext.md) 与其内部的 manager / event bus。
|
||||
- [ImGuiBackendBridge](../UI/ImGuiBackendBridge/ImGuiBackendBridge.md) 与 [ImGuiSession](../UI/ImGuiSession/ImGuiSession.md)。
|
||||
- [ViewportHostService](../Viewport/ViewportHostService/ViewportHostService.md)。
|
||||
- `LayerStack` 与 [EditorLayer](../Layers/EditorLayer/EditorLayer.md)。
|
||||
- 全局资源系统和脚本运行时桥接。
|
||||
|
||||
## 当前实现说明
|
||||
如果把商业编辑器类比成“宿主壳 + 工具层 + 领域服务”,`Application` 对应的就是宿主壳。它自己不直接实现 Inspector、Hierarchy、Project Browser 或 Scene View 的业务规则,但它决定这些系统能否以正确顺序运行起来。
|
||||
|
||||
- 采用单例入口 `Get()`。
|
||||
- `Initialize(HWND)` 会安装崩溃过滤器、配置日志、初始化窗口渲染器、创建编辑器上下文、初始化 ImGui,并挂接 `EditorLayer`。
|
||||
- `Shutdown()` 会按反向顺序关闭 layer、ImGui 和窗口渲染器。
|
||||
- `Render()` 当前只是执行一帧编辑器 UI 渲染。
|
||||
- `OnResize()` 会把尺寸变化转发给窗口渲染器。
|
||||
## 前置知识
|
||||
|
||||
## 关键公开接口
|
||||
理解这个类型,先抓住两点:
|
||||
|
||||
| 方法 | 作用 |
|
||||
- 编辑器真正的业务状态主要在 [EditorContext](../Core/EditorContext/EditorContext.md) 内,而不在 `Application` 自身。
|
||||
- `Application` 的核心职责是“编排顺序”而不是“承载全部逻辑”。
|
||||
|
||||
这也是商业级工具常见的分层方式。宿主层负责窗口、GPU 设备、UI 帧和生命周期;面板、命令和 manager 负责编辑器行为。这样项目切换、脚本热重载、布局恢复和视口渲染才不会互相缠死。
|
||||
|
||||
## 公开成员
|
||||
|
||||
| 成员 | 说明 |
|
||||
|------|------|
|
||||
| `Get()` | 获取全局应用单例。 |
|
||||
| `Initialize(HWND)` | 初始化编辑器应用。 |
|
||||
| `Shutdown()` | 关闭编辑器应用。 |
|
||||
| `Render()` | 绘制一帧编辑器。 |
|
||||
| `OnResize(int, int)` | 处理窗口尺寸变化。 |
|
||||
| `GetWindowHandle()` | 获取当前窗口句柄。 |
|
||||
| `GetEditorContext()` | 获取当前编辑器上下文。 |
|
||||
| `Get()` | 返回进程级单例。 |
|
||||
| [Initialize(HWND)](Initialize.md) | 初始化窗口渲染、上下文、脚本运行时、ImGui 和编辑器 layer。 |
|
||||
| [Shutdown()](Shutdown.md) | 按反向顺序释放所有宿主级资源。 |
|
||||
| [Render()](Render.md) | 推进一帧 editor update + render。 |
|
||||
| [OnResize(int, int)](OnResize-And-SaveProjectState.md) | 将窗口尺寸变化转发给主窗口渲染器。 |
|
||||
| [SwitchProject(const std::string&)](SwitchProject.md) | 切换项目根目录、资源根、脚本运行时与布局会话。 |
|
||||
| [`ReloadScriptingRuntime()`](ReloadScriptingRuntime.md) | 重新从当前项目的 `Library/ScriptAssemblies` 装载脚本运行时。 |
|
||||
| [`RebuildScriptingAssemblies()`](RebuildScriptingAssemblies.md) | 先卸载当前脚本 runtime 释放程序集锁,再触发项目脚本程序集重建,并在成功后重载运行时。 |
|
||||
| [`CanReimportProjectAsset(const std::string&)`](CanReimportProjectAsset.md) | 判断某个项目路径当前是否支持显式重导。 |
|
||||
| [`ReimportProjectAsset(const std::string&)`](ReimportProjectAsset.md) | 强制重导单个 project asset,并刷新项目资产索引。 |
|
||||
| [`ReimportAllProjectAssets()`](ReimportAllProjectAssets.md) | 重建整个项目 `Library` 资产缓存。 |
|
||||
| [`ClearProjectLibrary()`](ClearProjectLibrary.md) | 清空当前项目 `Library` 缓存目录与对应索引。 |
|
||||
| [`GetProjectLibraryRoot()`](GetProjectLibraryRoot.md) | 返回当前项目 `Library` 根目录。 |
|
||||
| [SaveProjectState()](OnResize-And-SaveProjectState.md) | 保存当前 ImGui 会话状态。 |
|
||||
| `GetMainRenderContext()` | 暴露主窗口 render context。 |
|
||||
| `GetMainRHIDevice()` / `GetMainSwapChain()` | 暴露主窗口 RHI 设备与交换链。 |
|
||||
| `GetViewportHostService()` | 暴露 Scene / Game 等视口宿主服务。 |
|
||||
| `GetEditorContext()` | 访问当前 editor context。 |
|
||||
| [`GetScriptRuntimeStatus()`](GetScriptRuntimeStatus.md) | 返回当前脚本运行时状态快照。 |
|
||||
| `IsRenderReady()` | 判断渲染宿主是否已完成初始化。 |
|
||||
| `GetWindowHandle()` | 返回主窗口句柄。 |
|
||||
|
||||
## 当前实现边界
|
||||
## 启动链路
|
||||
|
||||
- 目前窗口渲染路径绑定到 D3D12 窗口渲染器,不是抽象后端。
|
||||
- `InitializeEditorContext()` 当前默认把项目路径设为可执行目录。
|
||||
- `Render()` 当前只走 ImGui 帧,不承载独立游戏循环或模拟步进逻辑。
|
||||
按 `Application.cpp` 当前实现,[Initialize(HWND)](Initialize.md) 的真实顺序是:
|
||||
|
||||
1. 安装崩溃异常过滤器,并把 `stderr` 重定向到可执行目录日志。
|
||||
2. 解析编辑器项目根目录,并尝试切换当前工作目录。
|
||||
3. 初始化主窗口渲染器。
|
||||
4. 初始化全局 [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md),并把资源根设置到项目目录。
|
||||
5. 创建 [EditorContext](../Core/EditorContext/EditorContext.md) 并记录项目路径。
|
||||
6. 在 `EventBus` 上订阅 `EditorExitRequestedEvent`,把“请求退出”转换成 `WM_CLOSE`。
|
||||
7. 初始化脚本运行时。
|
||||
8. 初始化 ImGui 会话、DX12 后端、内置图标和 `ViewportHostService`。
|
||||
9. 创建并挂接 [EditorLayer](../Layers/EditorLayer/EditorLayer.md)。
|
||||
10. 标记 `m_renderReady = true`。
|
||||
|
||||
这个顺序很重要。比如:
|
||||
|
||||
- `EditorContext` 必须先存在,ImGui 初始化时才能把 project path 和 viewport host service 注入进去。
|
||||
- `ViewportHostService` 依赖 ImGui backend 和 RHI device,不能早于窗口渲染器。
|
||||
- `EditorLayer` 依赖已经就绪的 context、ImGui 和视口服务,必须放在最后挂接。
|
||||
|
||||
## 每帧执行链路
|
||||
|
||||
[`Render()`](Render.md) 当前不是单纯“画一帧 UI”,而是 Editor 主循环的最外层入口:
|
||||
|
||||
1. 计算 `deltaTime`。
|
||||
2. 调用 `m_layerStack.onUpdate(deltaTime)`。
|
||||
3. 进入 `RenderEditorFrame()`。
|
||||
|
||||
`RenderEditorFrame()` 的链路则是:
|
||||
|
||||
1. `m_windowRenderer.BeginFrame()`。
|
||||
2. `m_imguiBackend.BeginFrame()`。
|
||||
3. `m_viewportHostService.BeginFrame()`。
|
||||
4. `m_layerStack.onImGuiRender()`。
|
||||
5. `UpdateWindowTitle()`。
|
||||
6. `ImGui::Render()`。
|
||||
7. 调用 `m_windowRenderer.Render(...)`,并在 render callback 中执行 `m_viewportHostService.RenderRequestedViewports(...)`。
|
||||
|
||||
这条链路体现了当前 editor 的核心分工:
|
||||
|
||||
- `Application` 负责帧边界。
|
||||
- `LayerStack` 负责工具 UI 的组织。
|
||||
- `ViewportHostService` 负责真正的视口渲染请求。
|
||||
|
||||
所以典型的数据流是:
|
||||
|
||||
`Application::Render()` -> 面板与 layer 采集输入 / 生成视口请求 -> `ViewportHostService` 渲染 -> 主窗口提交。
|
||||
|
||||
## 项目切换与脚本运行时
|
||||
|
||||
`Application` 还是当前 editor 中“项目切换”和“脚本运行时热更新”的宿主层入口。
|
||||
|
||||
### 脚本运行时初始化
|
||||
|
||||
`InitializeScriptingRuntime(projectPath)` 会把程序集目录固定到:
|
||||
|
||||
- `<Project>/Library/ScriptAssemblies/XCEngine.ScriptCore.dll`
|
||||
- `<Project>/Library/ScriptAssemblies/GameScripts.dll`
|
||||
- `<Project>/Library/ScriptAssemblies/mscorlib.dll`
|
||||
|
||||
在启用 `XCENGINE_ENABLE_MONO_SCRIPTING` 的构建里:
|
||||
|
||||
- 缺少任一程序集时,不会崩溃,而是把 [ScriptEngine](../../Scripting/ScriptEngine/ScriptEngine.md) 运行时清空,并写入状态消息。
|
||||
- 只有 `MonoScriptRuntime::Initialize()` 成功后,才会把 runtime 注册到 [ScriptEngine](../../Scripting/ScriptEngine/ScriptEngine.md)。
|
||||
|
||||
这意味着当前 editor 对脚本程序集采用的是“软失败”策略。项目还没编译 managed 程序集时,Inspector 和脚本类发现会退化,但编辑器主体仍可启动。
|
||||
|
||||
### 项目切换
|
||||
|
||||
[`SwitchProject(projectPath)`](SwitchProject.md) 当前会同步完成:
|
||||
|
||||
- 切换 `ImGuiSession` 所属项目路径。
|
||||
- 更新 `EditorContext` 项目路径。
|
||||
- 更新工作目录。
|
||||
- 更新 [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md) 的资源根。
|
||||
- 重新初始化脚本运行时。
|
||||
- 刷新窗口标题。
|
||||
- 当目标项目没有已保存布局时,发布 `DockLayoutResetRequestedEvent`。
|
||||
|
||||
这和 Unity / Unreal 这类工具的思路是一致的:项目切换不是只换一个路径字符串,而是一次宿主级上下文切换。
|
||||
|
||||
### 脚本程序集重建
|
||||
|
||||
`RebuildScriptingAssemblies()` 会先关闭当前脚本 runtime 以释放 `GameScripts.dll` 这类项目本地程序集的文件锁,再调用 editor 侧脚本程序集构建器。构建成功后,才继续走 `ReloadScriptingRuntime()`;如果构建或重载失败,editor 会留下失败状态消息,但不会继续保留旧 runtime。
|
||||
|
||||
如果需要分别看重载、重建和状态读取的返回值语义,可以继续阅读:
|
||||
|
||||
- [ReloadScriptingRuntime](ReloadScriptingRuntime.md)
|
||||
- [RebuildScriptingAssemblies](RebuildScriptingAssemblies.md)
|
||||
- [GetScriptRuntimeStatus](GetScriptRuntimeStatus.md)
|
||||
|
||||
## 项目资产重导与 Library 管理
|
||||
|
||||
`Application` 现在还暴露了一组 editor 宿主级项目资产缓存入口,统一转发到全局 [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md)。
|
||||
|
||||
这几项接口的定位不是运行时按需加载,而是让菜单、命令路由和项目面板能通过宿主层执行显式缓存维护:
|
||||
|
||||
- [`CanReimportProjectAsset(assetPath)`](CanReimportProjectAsset.md)
|
||||
判断给定路径当前是否可走重导链路。
|
||||
- [`ReimportProjectAsset(assetPath)`](ReimportProjectAsset.md)
|
||||
强制重导单个 asset,并刷新项目资产索引。
|
||||
- [`ReimportAllProjectAssets()`](ReimportAllProjectAssets.md)
|
||||
清空已加载资源后重建整个项目 `Library` 缓存。
|
||||
- [`ClearProjectLibrary()`](ClearProjectLibrary.md)
|
||||
清空 `Library` 缓存,但不立即重建所有 artifact。
|
||||
- [`GetProjectLibraryRoot()`](GetProjectLibraryRoot.md)
|
||||
返回当前项目缓存目录路径。
|
||||
|
||||
这组能力被放在 `Application` 而不是某个单独 panel 里,是因为它们都依赖当前项目根、全局资源系统和 editor 宿主生命周期。
|
||||
|
||||
## 关闭链路与所有权
|
||||
|
||||
[`Shutdown()`](Shutdown.md) 采用严格的反向释放顺序:
|
||||
|
||||
1. 停止渲染。
|
||||
2. Detach `EditorLayer`。
|
||||
3. 从 `EditorContext` 移除 viewport host service 引用。
|
||||
4. 关闭 `ViewportHostService`。
|
||||
5. 释放内置图标、ImGui backend、ImGui session。
|
||||
6. 关闭脚本运行时并从 [ScriptEngine](../../Scripting/ScriptEngine/ScriptEngine.md) 卸下 runtime。
|
||||
7. 销毁 `EditorContext`。
|
||||
8. 关闭 [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md)。
|
||||
9. 关闭主窗口渲染器。
|
||||
|
||||
当前所有权关系大致是:
|
||||
|
||||
- `Application` 持有 `EditorContext`、`ViewportHostService`、ImGui backend/session 和窗口渲染器。
|
||||
- `LayerStack` 拥有 `EditorLayer` 的生命周期。
|
||||
- [ScriptEngine](../../Scripting/ScriptEngine/ScriptEngine.md) 本身是全局单例,但 runtime 实例的所有权由 `Application` 持有。
|
||||
|
||||
## 设计说明
|
||||
|
||||
当前实现有几个很重要的设计取向:
|
||||
|
||||
- 把顺序敏感的宿主初始化集中到 `Application`,避免散落在各个 panel / manager 中。
|
||||
- 通过 `EventBus` 把退出请求、布局重置这类“宿主动作”做成事件,而不是让菜单栏直接调用 Win32 API。
|
||||
- 把脚本运行时热重载放在宿主层,而不是 Inspector 或 `ScriptEngine` 内部硬编码,便于项目切换和重新编译。
|
||||
|
||||
这类设计的好处是明显的:
|
||||
|
||||
- 项目切换不需要重启 editor。
|
||||
- 视口渲染与 ImGui 会话有稳定的帧边界。
|
||||
- 脚本运行时缺失时,editor 仍可继续工作。
|
||||
|
||||
## 当前限制
|
||||
|
||||
- 当前主窗口宿主固定绑定 [D3D12WindowRenderer](../Platform/D3D12WindowRenderer/D3D12WindowRenderer.md) 和 Win32,不是多后端宿主抽象。
|
||||
- 整个类型按单窗口、单 swap chain 设计,没有多 editor window 管理。
|
||||
- 脚本运行时是否可用受编译宏和程序集产物双重限制。
|
||||
- 所有入口都应视为主线程 API;当前没有显式跨线程调度。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Editor 模块](../Editor.md)
|
||||
- [EditorContext](../Core/EditorContext/EditorContext.md)
|
||||
- [EventBus](../Core/EventBus/EventBus.md)
|
||||
- [EditorEvents](../Core/EditorEvents/EditorEvents.md)
|
||||
- [EditorLayer](../Layers/EditorLayer/EditorLayer.md)
|
||||
- [Win32EditorHost](../Platform/Win32EditorHost/Win32EditorHost.md)
|
||||
- [ViewportHostService](../Viewport/ViewportHostService/ViewportHostService.md)
|
||||
- [ImGuiBackendBridge](../UI/ImGuiBackendBridge/ImGuiBackendBridge.md)
|
||||
- [ImGuiSession](../UI/ImGuiSession/ImGuiSession.md)
|
||||
- [ReloadScriptingRuntime](ReloadScriptingRuntime.md)
|
||||
- [RebuildScriptingAssemblies](RebuildScriptingAssemblies.md)
|
||||
- [GetScriptRuntimeStatus](GetScriptRuntimeStatus.md)
|
||||
- [CanReimportProjectAsset](CanReimportProjectAsset.md)
|
||||
- [ReimportProjectAsset](ReimportProjectAsset.md)
|
||||
- [ReimportAllProjectAssets](ReimportAllProjectAssets.md)
|
||||
- [ClearProjectLibrary](ClearProjectLibrary.md)
|
||||
- [GetProjectLibraryRoot](GetProjectLibraryRoot.md)
|
||||
- [ScriptEngine](../../Scripting/ScriptEngine/ScriptEngine.md)
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Application::CanReimportProjectAsset
|
||||
|
||||
判断给定项目路径当前是否支持显式重导。
|
||||
|
||||
```cpp
|
||||
bool CanReimportProjectAsset(const std::string& assetPath) const;
|
||||
```
|
||||
|
||||
## 当前行为
|
||||
|
||||
- `assetPath` 为空时直接返回 `false`
|
||||
- 否则转发到:
|
||||
|
||||
```cpp
|
||||
::XCEngine::Resources::ResourceManager::Get().CanReimportProjectAsset(assetPath.c_str())
|
||||
```
|
||||
|
||||
## 返回值语义
|
||||
|
||||
当前返回 `true` 的前提是:
|
||||
|
||||
- Editor 已绑定有效项目根目录
|
||||
- 传入路径非空
|
||||
- 底层 `ResourceManager / AssetImportService` 能识别该路径对应的可导入资源类型
|
||||
|
||||
因此它更像“是否可以发起重导”的前置检查,而不是是否一定会导入成功的承诺。
|
||||
|
||||
## 当前用途
|
||||
|
||||
这个方法适合给菜单命令、项目浏览器右键菜单或批处理工具做启用态判断,避免对目录、未知 importer 或空路径直接发起重导。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [ReimportProjectAsset](ReimportProjectAsset.md)
|
||||
- [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md)
|
||||
40
docs/api/XCEngine/Editor/Application/ClearProjectLibrary.md
Normal file
40
docs/api/XCEngine/Editor/Application/ClearProjectLibrary.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Application::ClearProjectLibrary
|
||||
|
||||
清空当前项目 `Library` 缓存目录及其索引状态。
|
||||
|
||||
```cpp
|
||||
bool ClearProjectLibrary();
|
||||
```
|
||||
|
||||
## 当前行为
|
||||
|
||||
当前实现会:
|
||||
|
||||
1. 取全局 `ResourceManager`
|
||||
2. 调用 `resourceManager.Initialize()`
|
||||
3. 转发到 `resourceManager.ClearProjectLibraryCache()`
|
||||
|
||||
## 当前语义
|
||||
|
||||
和 [ReimportAllProjectAssets](ReimportAllProjectAssets.md) 不同,这个方法当前只负责“清空缓存”,不负责立即重建所有 artifact。
|
||||
|
||||
底层会:
|
||||
|
||||
- `UnloadAll()` 清空当前资源对象
|
||||
- 调用 `AssetImportService::ClearLibraryCache()`
|
||||
- 刷新 `ProjectAssetIndex`
|
||||
|
||||
因此调用后,后续首次加载或显式重导会重新生成需要的 artifact。
|
||||
|
||||
## 适用场景
|
||||
|
||||
- 诊断某个缓存目录是否已损坏
|
||||
- 在全量重导前先做一次干净清库
|
||||
- 需要确认 `Library` 中不存在旧 artifact 残留
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [ReimportAllProjectAssets](ReimportAllProjectAssets.md)
|
||||
- [GetProjectLibraryRoot](GetProjectLibraryRoot.md)
|
||||
- [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md)
|
||||
@@ -0,0 +1,35 @@
|
||||
# Application::GetProjectLibraryRoot
|
||||
|
||||
返回当前项目 `Library` 缓存目录路径。
|
||||
|
||||
```cpp
|
||||
std::string GetProjectLibraryRoot() const;
|
||||
```
|
||||
|
||||
## 当前行为
|
||||
|
||||
当前实现直接返回:
|
||||
|
||||
```cpp
|
||||
::XCEngine::Resources::ResourceManager::Get().GetProjectLibraryRoot().CStr()
|
||||
```
|
||||
|
||||
## 返回值语义
|
||||
|
||||
- 返回值是 `std::string` 按值拷贝,不是内部缓冲区引用
|
||||
- 如果当前项目根尚未建立或资源系统尚未绑定有效缓存目录,通常会得到空字符串
|
||||
|
||||
## 当前用途
|
||||
|
||||
这个方法主要适合:
|
||||
|
||||
- editor 诊断面板显示当前 `Library` 目录
|
||||
- 执行清库 / 全量重导前后做路径确认
|
||||
- 测试或工具层输出当前缓存根位置
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [ClearProjectLibrary](ClearProjectLibrary.md)
|
||||
- [ReimportAllProjectAssets](ReimportAllProjectAssets.md)
|
||||
- [ResourceManager::GetProjectLibraryRoot](../../Core/Asset/ResourceManager/GetProjectLibraryRoot.md)
|
||||
49
docs/api/XCEngine/Editor/Application/Initialize.md
Normal file
49
docs/api/XCEngine/Editor/Application/Initialize.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Application::Initialize
|
||||
|
||||
**命名空间**: `XCEngine::Editor`
|
||||
|
||||
**类型**: `method`
|
||||
|
||||
**源文件**: `editor/src/Application.h`
|
||||
|
||||
## 签名
|
||||
|
||||
```cpp
|
||||
bool Initialize(HWND hwnd);
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
完成当前 Editor 宿主壳的启动编排,包括日志、项目根解析、窗口渲染宿主、资源系统、`EditorContext`、脚本运行时、ImGui 和 `EditorLayer` 挂接。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 启动早期会先执行:
|
||||
- `InstallCrashExceptionFilter()`
|
||||
- `RedirectStderrToExecutableLog()`
|
||||
- `ConfigureEditorLogging(exeDir)`
|
||||
- 然后解析当前编辑器项目根目录,并尝试切换工作目录到该路径。
|
||||
- 之后缓存主窗口句柄 `m_hwnd`,并调用 `InitializeWindowRenderer(hwnd)`。
|
||||
- 窗口渲染宿主成功后,会初始化全局 `ResourceManager` 并把资源根设置到项目根目录。
|
||||
- 接着按顺序初始化:
|
||||
- `EditorContext`
|
||||
- 脚本运行时
|
||||
- ImGui session / backend / 内置图标 / `ViewportHostService`
|
||||
- `EditorLayer`
|
||||
- 最后清空上一帧时间戳状态并把 `m_renderReady` 设为 `true`。
|
||||
|
||||
## 失败路径
|
||||
|
||||
- 任一关键步骤失败时,当前会直接返回 `false`。
|
||||
- `InitializeWindowRenderer(...)` 失败时还会弹出 Win32 `MessageBoxW` 错误框。
|
||||
|
||||
## 当前实现边界
|
||||
|
||||
- 当前启动路径默认只面向单窗口 Win32 + D3D12 宿主。
|
||||
- 项目根目录由宿主启动时自动解析,不要求外部先传入项目路径。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [Shutdown](Shutdown.md)
|
||||
- [SwitchProject](SwitchProject.md)
|
||||
@@ -0,0 +1,51 @@
|
||||
# Application::OnResize / SaveProjectState
|
||||
|
||||
**命名空间**: `XCEngine::Editor`
|
||||
|
||||
**类型**: `methods`
|
||||
|
||||
**源文件**: `editor/src/Application.h`
|
||||
|
||||
## 签名
|
||||
|
||||
```cpp
|
||||
void OnResize(int width, int height);
|
||||
void SaveProjectState();
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
分别处理宿主窗口尺寸变化,以及把当前 ImGui 会话状态持久化到当前项目。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
### `OnResize(width, height)`
|
||||
|
||||
- 当前只是直接转发到:
|
||||
|
||||
```cpp
|
||||
m_windowRenderer.Resize(width, height);
|
||||
```
|
||||
|
||||
- 也就是说,窗口尺寸变化目前由主窗口 renderer 自己处理 back buffer 重建。
|
||||
|
||||
### `SaveProjectState()`
|
||||
|
||||
- 当前只是调用:
|
||||
|
||||
```cpp
|
||||
m_imguiSession.SaveSettings();
|
||||
```
|
||||
|
||||
- 它负责把当前项目相关的 ImGui/dock 布局状态写回会话存储。
|
||||
|
||||
## 设计含义
|
||||
|
||||
- 这两个方法当前都是 thin forwarding API。
|
||||
- 它们存在的价值主要是把宿主层对外暴露的职责收口在 `Application` 上,而不是让外部直接碰内部子系统。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [Render](Render.md)
|
||||
- [SwitchProject](SwitchProject.md)
|
||||
@@ -0,0 +1,40 @@
|
||||
# Application::ReimportAllProjectAssets
|
||||
|
||||
重建当前项目全部资产的 `Library` 缓存。
|
||||
|
||||
```cpp
|
||||
bool ReimportAllProjectAssets();
|
||||
```
|
||||
|
||||
## 当前行为
|
||||
|
||||
当前实现会:
|
||||
|
||||
1. 取全局 `ResourceManager`
|
||||
2. 调用 `resourceManager.Initialize()`
|
||||
3. 转发到 `resourceManager.RebuildProjectAssetCache()`
|
||||
|
||||
## 当前语义
|
||||
|
||||
这不是逐个路径循环调用 [ReimportProjectAsset](ReimportProjectAsset.md),而是更重的一次整库重建。底层会:
|
||||
|
||||
- 清空已加载运行时资源
|
||||
- 让 `AssetImportService` 重建项目 `Library` 缓存
|
||||
- 刷新 `ProjectAssetIndex`
|
||||
|
||||
因此它更适合:
|
||||
|
||||
- 批量修复缓存
|
||||
- 强制全量重导
|
||||
- 处理 importer 升级后的缓存重建
|
||||
|
||||
## 返回值语义
|
||||
|
||||
返回值直接反映底层 `ResourceManager::RebuildProjectAssetCache()` 是否成功。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [ReimportProjectAsset](ReimportProjectAsset.md)
|
||||
- [ClearProjectLibrary](ClearProjectLibrary.md)
|
||||
- [ResourceManager::RebuildProjectAssetCache](../../Core/Asset/ResourceManager/RebuildProjectAssetCache.md)
|
||||
42
docs/api/XCEngine/Editor/Application/ReimportProjectAsset.md
Normal file
42
docs/api/XCEngine/Editor/Application/ReimportProjectAsset.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Application::ReimportProjectAsset
|
||||
|
||||
强制重导单个 project asset,并刷新当前项目的资产索引状态。
|
||||
|
||||
```cpp
|
||||
bool ReimportProjectAsset(const std::string& assetPath);
|
||||
```
|
||||
|
||||
## 当前行为
|
||||
|
||||
- `assetPath` 为空时直接返回 `false`
|
||||
- 否则先取全局 `ResourceManager`
|
||||
- 调用 `resourceManager.Initialize()`
|
||||
- 最后转发到:
|
||||
|
||||
```cpp
|
||||
resourceManager.ReimportProjectAsset(assetPath.c_str())
|
||||
```
|
||||
|
||||
## 底层影响
|
||||
|
||||
`Application` 本身只是宿主层薄包装,真正的重导逻辑在 `ResourceManager` 内部完成。按当前实现,底层会:
|
||||
|
||||
1. `UnloadAll()` 清空已加载资源对象
|
||||
2. 调用 `AssetImportService::ReimportAsset(...)` 强制重建单个资产的 artifact
|
||||
3. 刷新 `ProjectAssetIndex`
|
||||
4. 若能解析出有效 `AssetGUID + relativePath`,则更新 GUID 到路径的记忆映射
|
||||
|
||||
因此这不是“只重写磁盘文件”的静默操作,而是会影响 editor 当前资源查找状态的一次显式缓存维护。
|
||||
|
||||
## 返回值语义
|
||||
|
||||
- 重导链路成功完成时返回 `true`
|
||||
- 路径为空、项目根无效、importer 无法处理该路径或底层导入失败时返回 `false`
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [CanReimportProjectAsset](CanReimportProjectAsset.md)
|
||||
- [ReimportAllProjectAssets](ReimportAllProjectAssets.md)
|
||||
- [AssetDatabase::ReimportAsset](../../Core/Asset/AssetDatabase/ReimportAsset.md)
|
||||
- [ResourceManager](../../Core/Asset/ResourceManager/ResourceManager.md)
|
||||
57
docs/api/XCEngine/Editor/Application/Render.md
Normal file
57
docs/api/XCEngine/Editor/Application/Render.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Application::Render
|
||||
|
||||
**命名空间**: `XCEngine::Editor`
|
||||
|
||||
**类型**: `method`
|
||||
|
||||
**源文件**: `editor/src/Application.h`
|
||||
|
||||
## 签名
|
||||
|
||||
```cpp
|
||||
void Render();
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
推进一帧 Editor update + render,是当前宿主壳对外最重要的逐帧入口。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 当 `m_renderReady == false` 时直接返回。
|
||||
- 否则会用 `std::chrono::steady_clock` 计算当前帧 `deltaTime`。
|
||||
- 第一帧不会生成有效 `deltaTime`,而是把它保持在 `0.0f`。
|
||||
- 随后按顺序执行:
|
||||
- `m_layerStack.onUpdate(deltaTime)`
|
||||
- `RenderEditorFrame()`
|
||||
|
||||
## `RenderEditorFrame()` 当前真实流程
|
||||
|
||||
`Render()` 的核心渲染逻辑当前落在内部 helper `RenderEditorFrame()` 中:
|
||||
|
||||
1. `m_windowRenderer.BeginFrame()`
|
||||
2. `m_imguiBackend.BeginFrame()`
|
||||
3. `m_viewportHostService.BeginFrame()`
|
||||
4. `m_layerStack.onImGuiRender()`
|
||||
5. `UpdateWindowTitle()`
|
||||
6. `ImGui::Render()`
|
||||
7. `m_windowRenderer.Render(...)`
|
||||
|
||||
在最后一步里,当前还会通过 `beforeUiRender` 回调执行:
|
||||
|
||||
```cpp
|
||||
m_viewportHostService.RenderRequestedViewports(*m_editorContext, renderContext);
|
||||
```
|
||||
|
||||
因此 Scene / Game 视口内容会先于主窗口 ImGui draw data 提交。
|
||||
|
||||
## 设计含义
|
||||
|
||||
- `Application::Render()` 当前负责的是“帧边界 + 调度顺序”,而不是面板业务本身。
|
||||
- `LayerStack` 采集 UI 和视口请求,`ViewportHostService` 真正渲染被请求的视口。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [OnResize / SaveProjectState](OnResize-And-SaveProjectState.md)
|
||||
45
docs/api/XCEngine/Editor/Application/Shutdown.md
Normal file
45
docs/api/XCEngine/Editor/Application/Shutdown.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Application::Shutdown
|
||||
|
||||
**命名空间**: `XCEngine::Editor`
|
||||
|
||||
**类型**: `method`
|
||||
|
||||
**源文件**: `editor/src/Application.h`
|
||||
|
||||
## 签名
|
||||
|
||||
```cpp
|
||||
void Shutdown();
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
按反向顺序释放当前 Editor 宿主壳持有的主要资源与子系统。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 会先把:
|
||||
- `m_renderReady = false`
|
||||
- `m_hasLastFrameTime = false`
|
||||
- 然后依次执行:
|
||||
- `DetachEditorLayer()`
|
||||
- 若存在 `EditorContext`,先把其 `ViewportHostService` 指针清空
|
||||
- `m_viewportHostService.Shutdown()`
|
||||
- `UI::ShutdownBuiltInIcons()`
|
||||
- `m_imguiBackend.Shutdown()`
|
||||
- `m_imguiSession.Shutdown()`
|
||||
- `ShutdownScriptingRuntime()`
|
||||
- `ShutdownEditorContext()`
|
||||
- 若资源系统曾初始化,则关闭 `ResourceManager`
|
||||
- `m_windowRenderer.Shutdown()`
|
||||
|
||||
## 设计含义
|
||||
|
||||
- 当前 shutdown 顺序明显按依赖关系反向释放。
|
||||
- 特别是先断开 `EditorContext -> ViewportHostService` 引用,再销毁视口宿主,避免悬空服务指针。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [Render](Render.md)
|
||||
54
docs/api/XCEngine/Editor/Application/SwitchProject.md
Normal file
54
docs/api/XCEngine/Editor/Application/SwitchProject.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Application::SwitchProject
|
||||
|
||||
**命名空间**: `XCEngine::Editor`
|
||||
|
||||
**类型**: `method`
|
||||
|
||||
**源文件**: `editor/src/Application.h`
|
||||
|
||||
## 签名
|
||||
|
||||
```cpp
|
||||
bool SwitchProject(const std::string& projectPath);
|
||||
```
|
||||
|
||||
## 作用
|
||||
|
||||
切换当前 Editor 宿主壳所绑定的项目根目录,并同步刷新布局会话、工作目录、资源根、脚本运行时和窗口标题。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
- 当前没有 `EditorContext` 或传入路径为空时直接返回 `false`。
|
||||
- 首先调用:
|
||||
|
||||
```cpp
|
||||
const bool hasSavedDockLayout = m_imguiSession.SetProjectPath(projectPath);
|
||||
```
|
||||
|
||||
- 然后把 `EditorContext` 中的项目路径更新为新路径。
|
||||
- 接着尝试切换进程工作目录到该项目根,并输出日志。
|
||||
- 随后执行:
|
||||
- `ResourceManager::Get().SetResourceRoot(projectPath.c_str())`
|
||||
- `InitializeScriptingRuntime(projectPath)`
|
||||
- 最后清空 `m_lastWindowTitle` 并重新调用 `UpdateWindowTitle()`。
|
||||
- 若目标项目没有保存过 dock 布局,会通过 `EventBus` 发布 `DockLayoutResetRequestedEvent`。
|
||||
|
||||
## 返回值
|
||||
|
||||
- `true`: 成功完成这次宿主级项目切换。
|
||||
- `false`: 缺少 `EditorContext` 或传入路径为空。
|
||||
|
||||
## 设计含义
|
||||
|
||||
- 当前项目切换不是单纯改一条路径字符串,而是一次宿主级上下文切换。
|
||||
- 它同时影响:
|
||||
- ImGui 布局会话
|
||||
- 资源根
|
||||
- 脚本运行时
|
||||
- 窗口标题
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Application](Application.md)
|
||||
- [Initialize](Initialize.md)
|
||||
- [ReloadScriptingRuntime](ReloadScriptingRuntime.md)
|
||||
Reference in New Issue
Block a user