Files
XCEngine/editor/AGENTS.md

142 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# XCEditor Agent Guide
本文面向以后在 `editor/` 下工作的 coding agent / 开发者。若本文与代码、`CMakeLists.txt` 或测试目标冲突,以代码为准,并在同一次改动中更新本文。
## 长期目标
- `editor/` 是当前 XCUI 编辑器主线,不是旧 `mvs/editor``new_editor` 入口。长期方向是把可复用 UI shell 与产品编辑器装配继续分离清楚。
- `XCUIEditor` 保持为平台无关、后端无关的静态库。公共头在 `include/XCEditor/**`,实现主要在 `src/**`;不要放入 Win32、D3D12、DXGI、产品面板状态或工程 runtime 事实。
- `XCEditorCore` 承担产品编辑器核心。代码主要在 `app/Core``app/Composition``app/Features``app/Services``app/Windowing`,并通过 `XCEditorCoreRendering` 对象库接入 `app/Rendering`;它不直接拥有 Win32 消息循环。
- `XCEditor` 是可选 Win32 + D3D12 应用壳。代码在 `app/Bootstrap``app/Host/Win32``app/Host/D3D12`负责窗口、DPI、消息分发、swapchain、UI 纹理和截图。
- 产品装配应以 `app/Core/Product/EditorProductManifest.*` 为单一事实源。正式 panel 集、action route、runtime owner、viewport renderer owner 先在 manifest 中声明,再派生 shell / menu / command / runtime / viewport 注册。
- UI widget / shell / workspace 代码优先保持 model/state/request/frame/result 风格。新增行为要能被 `tests/UI/Editor/unit` 以纯状态方式测试。
- scene/project 的用户操作应通过 runtime 或 command route 进入,不要在 draw/append 阶段直接改 scene 或文件系统。scene feature / panel 层不得直接 `SetPosition()``SetRotation()``SetLocalScale()``CreateComponent()` 或类似写入 engine object graph交互预览也必须回到 `EditorSceneRuntime`,再由 backend/adapter 执行。
- engine 全局 runtime 访问权统一收口到 `app/Core/Engine/EditorEngineServices.h` 合约和 `app/Services/Engine/EngineEditorServices.*` 生产实现。`SceneManager::Get()``ResourceManager::Get()``RenderObjectIdRegistry::Get()` 这类入口只能在该生产 adapter 内出现。
- scene 事实所有权走 `app/Core/Scene/EditorSceneBackend.h` 合约。`EditorSceneRuntime` 只消费显式 backend`EngineEditorSceneBackend` 必须吃显式注入的 engine manager / resource manager不要在 scene runtime、panel、composition 或 viewport pass 中重新触碰 engine 全局单例。读模型优先经由 runtime/backend 快照派生,例如 hierarchy 使用 `EditorSceneHierarchySnapshot`,不要让面板从 `Scene*` 现场重建业务模型。
- scene 渲染私有逻辑不要塞进 panel 或 shell。新增渲染能力时先判断它属于 engine `Rendering/RHI`、editor viewport pass bundle还是 UI overlay。
- 运行时路径以 `app/Core/Environment/EditorRuntimePaths.h` 为显式契约。workspace、executable、resource、project、capture 根路径由 bootstrap 一次性解析并向下传递;不要在下游重新从 repo root、当前工作目录或文档文件推导运行环境。
- 资源路径、图标、shader、截图输出都应走明确服务或 host 接口。不要硬编码从当前工作目录猜路径;手动验证截图不得写回 source tree。
## 当前情况
- `editor/AGENTS.md` 只是协作说明,不是运行时定位标记。`Application::ResolveRuntimePaths()` 当前用稳定工程标记(根 `CMakeLists.txt``editor/resources``project`)定位开发 workspace并填充 `EditorRuntimePaths`
- 顶层 `CMakeLists.txt` 默认启用 `XCENGINE_BUILD_XCUI_EDITOR_CORE``XCENGINE_BUILD_XCUI_EDITOR_APP`。构建 core/app 时必须启用 `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT`
- `XCEditor` 目标输出名是 `XCEngine.exe`Debug 产物位于 `build/editor/Debug/XCEngine.exe`
- 当前应用没有命令行项目选择流程;默认项目根由 `EditorRuntimePaths.projectRoot` 提供,开发 workspace 下通常是 `<workspaceRoot>/project`。不要沿用旧文档里的 `--project <path>` 说法。
- 当前面板 ID 为 `hierarchy``scene``game``inspector``console``project`,由 `EditorProductManifest.*` 声明并驱动注册。
- 当前 `game` panel 是 viewport shell但 renderer owner 是 placeholder不是正式 Game runtime。它会显示 `Game view runtime is not implemented`,不要假设 Game view 已完整实现。
- 当前 command 事实:`file.exit` 已绑定退出;`edit.*` 通过 active route 分发到 hierarchy/project/scene/inspector`assets.*` 通过 project route 分发;多数 `file.*``run.*``scripts.*``help.about` 仍只是菜单/命令 surface未拥有完整 host owner。
- `EditorContext` 是产品级状态聚合点:`EditorSession`、project runtime、scene runtime、selection、command focus、utility window request、shortcut manager 和 host command bridge 都在这里串接;初始化只接收 `EditorRuntimePaths`,不再自行拼接 repo/project/resource 路径。
- `UIEditorWorkspaceController` 管单窗口 workspace model/session`EditorWindowSystem` 管多窗口 workspace set。跨窗口 detach、close、update 必须经过 synchronization plan。
- `EditorWorkspacePanelRuntimeSet` 托管产品面板生命周期。新增 panel 时先改 `EditorProductManifest.*`,再按需要调整 `BuildEditorWorkspaceModel()` 的默认布局和测试;不要再手工在 registry / menu / runtime set / viewport host 多处分别补定义。
- `EditorSelectionService` 是 hierarchy/project/inspector/scene viewport 之间的选择同步核心。不要在单个 panel 内维护另一套长期选择真相。
- `EditorProjectRuntime` 包装 `ProjectBrowserModel`,负责 project tree/grid、选择、文件操作、scene asset open request。文件系统改动后要刷新并 revalidate selection。
- `ProjectPanel` 只消费由 `EditorContext` / `EditorPanelServices` 提供的 `EditorProjectRuntime`,不再拥有或初始化自己的 project runtime。测试也应显式创建 `EditorProjectRuntime` 并通过 `SetProjectRuntime()` 注入,不要把 `projectRoot` 传给 panel。
- `EditorEngineServices` 是 editor 接入 engine 全局 runtime 的唯一生产 adapter。`Application` 创建它并向 `EditorContext`、window shell runtime、viewport runtime 传递;下游只消费显式服务。
- `EditorSceneBackend` 是 scene document/backend 的显式边界;`EngineEditorSceneBackend``EditorEngineServices` 创建,并通过显式 `SceneManager&` / `ResourceManager&` 接入真实 engine runtime。`EditorSceneRuntime` 负责 startup scene 编排、editor scene camera、hierarchy selection、component list、transform edit history 和 scene tool state但不直接访问 engine 单例。
- scene object graph 写入必须停在 `EditorSceneBackend` 生产 adapter 内。`EditorSceneRuntime` 可以编排 undo/redo、selection stamp、inspector revision 和 tool state但组件移除、component mutation、Transform inspector 写入、gizmo 预览/撤销写入都应通过 backend command 执行,不要在 runtime / feature / panel 层直接 `RemoveComponent()``SetPosition()``SetRotation()``SetScale()``SetLocal*()`
- `EditorSceneRuntime::BuildHierarchySnapshot()` 是 hierarchy 面板的 scene 读入口;`HierarchyModel` 从该快照构建 UI tree。不要重新把 hierarchy 绑定回 `Scene*`
- transform gizmo support 只负责几何计算和 hit/drag 状态;预览写入通过 `SceneGizmoUndoBridge` 调回 `EditorSceneRuntime::ApplyTransformTool*Preview()`。不要在 `SceneViewportTransformGizmoSupport.*` 里直接写 `GameObject` transform。
当前目录地图:
- `include/XCEditor/Foundation`:命令注册/分发、快捷键、主题、文本测量接口、runtime trace。
- `include/XCEditor/Fields`bool、number、text、enum、asset、object、color、vector、property grid 等编辑字段的绘制模型与交互。
- `include/XCEditor/Collections`list/tree/tab/scroll/inline rename/drag-drop 等集合控件。
- `include/XCEditor/Docking``include/XCEditor/Workspace`dock host、workspace tree、layout persistence、splitter correction、panel detach/transfer。
- `include/XCEditor/Shell`menu/toolbar/status/workspace 的 shell 组合与交互入口。
- `include/XCEditor/Viewport`viewport slot/shell/input bridge。这里是通用 UI viewport 容器,不是 scene renderer。
- `include/XCEditor/Windowing`:多窗口 workspace 状态、同步计划和 presentation policy。
- `src/**`:对应公共头的实现。保持偏纯函数/状态机风格。
- `app/Core`:产品级 contracts、session、command focus、selection、panel services、engine services、scene/project/viewport/windowing 接口。
- `app/Core/Scene`scene backend 合约和 editor scene runtime 可消费的公共 scene 标识工具。
- `app/Core/Environment`运行时路径契约。bootstrap 负责解析 `EditorRuntimePaths`core/composition/features/rendering 只消费显式路径。
- `app/Core/Product`:产品 manifest。这里定义正式 panel 集、route 归属、runtime owner 和 viewport renderer owner。
- `app/Composition`:装配编辑器 shell。`EditorContext` 拥有 session、project runtime、scene runtime、selection、command bridge`EditorShellRuntime` 驱动 shell interaction、hosted panels 和 viewport runtime。
- `app/Features`:产品面板与场景视图工具。
- `app/Services`:产品 runtime 的生产服务实现。engine 全局 runtime 接入集中在 `app/Services/Engine/EngineEditorServices.*`scene backend 由该 adapter 生产project runtime 集中在 `app/Services/Project`
- `app/Rendering`:编辑器 viewport、icon、object-id picking、grid/outline/helper pass 相关服务。渲染执行仍走 engine `Rendering + RHI`
- `app/Host`宿主接口实现。Win32/D3D12 细节只能待在这里或 rendering host 实现里。
- `app/Windowing`窗口实例、内容控制器、生命周期协调器、workspace 多窗口同步、截图和 frame orchestration。
- `resources/Icons``resources/shaders/scene-viewport`:内置图标和 scene viewport shader。资源路径由 app/rendering 层解析。
当前启动和帧流程:
```text
wWinMain
-> RunXCEditor
-> Application::Initialize / Run
-> Application::ResolveRuntimePaths
-> EditorContext::Initialize
-> BuildEditorApplicationShellAsset
-> EditorWindowSystem::BootstrapPrimaryWindow
-> EditorWindowManager::CreateWorkspaceWindow
-> EditorWindowRuntimeController
-> EditorWorkspaceWindowContentController
-> EditorShellRuntime::Update / Append / RenderRequestedViewports
```
- `Application::Run()` pump Win32 message更新 `ResourceManager::UpdateAsyncLoads()`,然后让 `EditorWindowManager::RenderAllWindows()` 驱动所有窗口。
- `EditorWindowRuntimeController::BeginFrame()` 从 D3D12 runtime 取 `RenderContext`content controller 先更新 shell 与 hosted panels再 present UI draw data。
- `EditorShellInteractionEngine::Update()``BeginFrame()` 清空 viewport 请求,再运行 `UpdateUIEditorShellInteraction()`,最后把每个 viewport shell 的尺寸提交给 `EditorViewportRuntimeServices::RequestViewport()`
- `EditorShellRuntime::RenderRequestedViewports()` 在 UI shell 更新后调用 viewport runtime把 scene viewport 渲染进离屏纹理,再由 shell frame 展示。
当前 Scene Viewport 分层:
- `src/Viewport``include/XCEditor/Viewport`viewport slot/shell/input bridge只处理 UI 容器和输入桥。
- `app/Features/Scene/SceneViewportController.*`:场景视图产品交互,处理 Q/W/E/R 工具切换、F 聚焦、鼠标导航、scene icon picking、transform gizmo。
- `app/Core/Scene/EditorSceneBackend.h`scene backend contract、startup scene result 和 game object item id helpers。
- `app/Services/Scene/EditorSceneRuntime.*`scene selection、editor camera、transform undo/redo、component mutation 和 scene render request 的事实来源;它必须通过注入的 `EditorSceneBackend` 访问真实 scene。
- `app/Services/Engine/EngineEditorServices.*`:当前唯一允许直接接入 engine `SceneManager` / `ResourceManager` / `RenderObjectIdRegistry` 的生产 adapter。
- `app/Rendering/Viewport/ViewportHostService.*`:离屏 viewport 资源管理和 renderer 注册。
- `app/Rendering/Viewport/SceneViewportRenderService.*`:调用 engine `SceneRenderer`,插入 grid、selection outline、selected helpers、object-id 等 editor pass。
- object-id picking 依赖有效 object-id surface 和 frame serial修改时要覆盖 `test_viewport_object_id_picker.cpp` 及相关 viewport render plan 测试。
当前构建和验证入口:
```powershell
cmake --build build --config Debug --target XCUIEditor
cmake --build build --config Debug --target XCEditorCore
cmake --build build --config Debug --target XCEditor
cmake --build build --config Debug --target editor_ui_tests
cmake --build build --config Debug --target editor_app_core_tests
cmake --build build --config Debug --target editor_app_feature_tests
cmake --build build --config Debug --target editor_windowing_phase1_tests
cmake --build build --config Debug --target editor_ui_smoke_targets
cmake --build build --config Debug --target editor_ui_manual_validation_scenarios
```
```powershell
ctest --test-dir build -C Debug -R "editor|xceditor" --output-on-failure
```
- `XCUIEditor` widget/shell/workspace 改动:跑 `editor_ui_tests``editor_windowing_phase1_tests`
- `app/Core`、project/scene/session/command 改动:跑 `editor_app_core_tests`
- scene viewport、project panel、window input routing 改动:跑 `editor_app_feature_tests`
- Win32/D3D12 host 或启动流程改动:跑 `editor_ui_smoke_targets`,必要时跑 `xceditor_smoke`
- 手动 UI 场景:跑 `editor_ui_manual_validation_scenarios`
有用环境变量:
- `XCUIEDITOR_SMOKE_TEST=1`:启用应用自退出 smoke 模式。
- `XCUIEDITOR_SMOKE_TEST_FRAME_LIMIT=<n>`smoke 模式帧数上限。
- `XCUIEDITOR_SMOKE_TEST_DURATION_SECONDS=<n>`smoke 模式持续时间。
- `XCUI_AUTO_CAPTURE_ON_STARTUP=1`:启动后自动截图。
## 过去执行
- 已把 editor 产品装配的 panel 声明收敛到 `app/Core/Product/EditorProductManifest.*`,并让 panel registry、View > Panels 菜单、panel 激活命令、action route、workspace runtime set 和 viewport renderer 注册从 manifest 派生。
- 已把 `game` panel 明确标成 placeholder viewport而不是隐式共享 scene renderer 或假装 Game runtime 已完成。
- 已新增 manifest validation 测试,确保产品 manifest 能声明 panel runtime owner 和 viewport renderer owner并覆盖 `game` placeholder 的预期状态。
- 已更新根 `AGENT.md` 和本文件,去掉旧 `--project` 说法,记录当前 XCUI editor、`XCEditorCore` 分层和 product manifest 规则。
- 已移除 `ProjectPanel` 自持 `EditorProjectRuntime` 的 fallback 路径project runtime 事实源现在只来自 `EditorContext`,面板测试改为显式 runtime 注入。
- 已把 scene 的 engine 全局访问收敛到 `EngineEditorSceneBackend`,让 `EditorSceneRuntime` 通过 `EditorSceneBackend` 合约初始化、打开 scene 和执行 hierarchy mutation新增 backend contract 单测覆盖无 backend 失败和 fake backend 注入。
- 已新增 `EditorEngineServices` 边界,把 `SceneManager::Get()``ResourceManager::Get()``RenderObjectIdRegistry::Get()``Application``EditorContext` 和 viewport shader/object-id 路径收口到 `app/Services/Engine/EngineEditorServices.*``EditorContext` 现在通过显式 engine service 创建 scene backend并会在 scene runtime 初始化失败时返回失败。
- 已把 hierarchy 面板的 scene 读取改为 `EditorSceneHierarchySnapshot` 快照路径,`HierarchyModel` 不再由 panel 直接拿 `Scene*` 构建;已把 inspector 添加组件动作收口到 `EditorSceneBackend::AddComponent()`,让 `ComponentFactoryRegistry::Get()` 留在 engine adapter 内。
- 已把 scene transform gizmo 的拖拽预览写入从 feature support 层移到 `EditorSceneRuntime`support 层不再直接 `SetPosition()` / `SetRotation()` / `SetLocalScale()`
- 已把 `EditorSceneRuntime` 内的组件移除、Transform inspector 写入、component mutation、transform snapshot restore 和 gizmo preview 写入继续收口到 `EditorSceneBackend` command真实 engine object graph 写入现在由 `EngineEditorSceneBackend` 执行runtime 只负责状态编排和 revision/undo 维护。
- 本次改动验证过:
- `cmake --build build --config Debug --target XCEditor`
- `cmake --build build --config Debug --target editor_app_core_tests`
- `cmake --build build --config Debug --target editor_app_feature_tests`