Files
XCEngine/editor/AGENTS.md

318 lines
13 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.
# XCUI Editor Agent Guide
## Build Shape
The editor is a two-layer system.
- `XCUIEditorLib` is the reusable framework library.
- `XCUIEditorApp` is the concrete editor application executable.
- The build shape of `editor/` is `XCUIEditorLib <- XCUIEditorApp`.
- `editor/src/**` and `editor/include/XCEditor/**` belong to the framework layer.
- `editor/app/**` belongs to the app layer and is compiled directly into `XCUIEditorApp`.
- `app/Windowing`, `app/Platform/Win32`, `app/Rendering`, `app/Composition`, and similar directories are internal partitions inside the app layer.
- Types for multi-window editor authority, Win32 hosting, utility windows, and editor-only rendering stay in `editor/app/**`.
- `editor/include/XCEditor/**` exposes framework-level APIs only.
Architecture shorthand for this repo:
```text
XCUIEditorLib
<- XCUIEditorApp
```
When describing the current architecture, refer to `windowing`, `platform`, `rendering`, and `host` as app-internal partitions unless the build graph itself changes.
这份文档面向在 `editor/` 下工作的 coding agent / 开发者。它描述当前 editor 的真实工程边界、窗口架构和修改约束,不是产品说明。
如果本文和当前代码、`editor/CMakeLists.txt`、实际目录结构冲突,以当前 checkout 为准,并在本次工作里同步修正文档。
## 1. 当前定位
`editor/` 是当前 editor 应用主线。
当前工程事实:
- 可复用 UI framework 的真实构建目标是 `XCUIEditorLib`
- editor 应用的真实可执行目标是 `XCUIEditorApp`
- `XCUIEditorApp` 的输出名是 `XCEngine`,产物为 `XCEngine.exe`
- `editor/src` + `editor/include/XCEditor` 是 XCEditor framework。
- `editor/app` 是具体 XCEngine editor 应用层。
- `editor/resources` 存放 editor 自有图标和 scene viewport shader。
当前 `editor/CMakeLists.txt` 并没有把 app core、windowing seam、Win32 host、rendering host 拆成独立生产 target。除了 `XCUIEditorLib` 之外,其余 app / windowing / platform / rendering 代码仍直接编进 `XCUIEditorApp`
`XCUIEditorAppLib``XCUIEditorAppCore``XCUIEditorHost` 不是当前 `editor/CMakeLists.txt` 里真实定义的生产 target它们只在部分测试脚本或清理逻辑里作为条件名称出现。不要把这些名字当成当前已经存在的模块边界。
## 2. 当前分层
推荐按下面五层理解和修改,但要记住这主要是目录和语义边界,不是已经被 CMake 强制落实的编译边界:
1. `editor/src` / `editor/include/XCEditor`
XCEditor framework。这里应保持通用不依赖具体 editor app、Win32 宿主或 D3D12 实现。
2. `editor/app/Composition``Commands``Features``Project``Scene``State``Support``System``UtilityWindows`
editor 应用语义层。这里放 panel 组合、项目/场景运行时、选择状态、命令桥接、utility window 描述和 app 侧服务。
3. `editor/app/Windowing`
平台无关的窗口主线。这里放 content controller contract、frame transfer request、workspace synchronization planner / presentation policy / authoritative window set。
4. `editor/app/Platform/Win32`
Win32 host。这里负责 native window、消息分发、生命周期、输入翻译、窗口 chrome、host runtime 和 coordinator。
5. `editor/app/Rendering`
editor 渲染宿主。这里负责 D3D12 UI 渲染、窗口 render loop、swapchain、viewport 资源和 scene viewport pass。
依赖方向尽量保持为:
```text
XCEditor framework
<- app semantics
<- app/windowing
<- Platform/Win32
<- app/Rendering
```
现实约束:
- 当前只有 `XCUIEditorLib` 是真实独立 target。
- 其余层级只是目录和 ownership 约定。
- 修改时仍要主动控制 include 方向,避免把“语义上应该分层”写回成硬耦合。
## 3. 顶层启动流程
入口:
```text
app/main.cpp
-> RunXCUIEditorApp
-> Application::Run
```
当前启动主线:
```text
Application
-> EditorContext
-> Win32SystemInteractionHost
-> EditorWindowSystem
-> EditorWindowManager
-> EditorWindowHostRuntime
-> EditorWindowWorkspaceCoordinator
-> EditorUtilityWindowCoordinator
-> EditorWindowLifecycleCoordinator
```
primary workspace window 的 bootstrap 顺序是:
```text
EditorContext::BuildWorkspaceController()
-> EditorWindowSystem::BootstrapPrimaryWindow(...)
-> EditorWindowManager::CreateWorkspaceWindow(...)
```
不要把 primary window authority 初始化放回 Win32 host。当前 authoritative bootstrap 已经在 `EditorWindowSystem`
## 4. 当前窗口系统事实
### 4.1 Authority / Planner / Host Execution
当前多窗口 workspace 主线里,几个核心对象的职责是:
- `EditorWindowSystem`
- 持有 authoritative `UIEditorWindowWorkspaceSet`
- 通过 `EditorWindowWorkspaceStore` 做 validation / commit
- 构建 synchronization plan
- 处理显式 `workspaceMutation` request
- 处理 destroyed window reconciliation
- `EditorWindowWorkspaceCoordinator`
- 采集 host snapshot
- 调用 `EditorWindowSystem` 生成 plan
- 执行 host-side create / update / close
- 处理 global tab drag、detach、cross-window dock/drop
- 处理 window presentation refresh
- 在 native destroy 时回到 `EditorWindowSystem` 做 reconcile
重要事实:
- `EditorWindowWorkspaceCoordinator` 已不再直接写 authority store。
- 但它仍然很厚,仍同时承担 host 执行、presentation refresh、drag/detach 流程和部分回滚时序。
- 当前不要把它描述成“纯粹的薄 host adapter”。
### 4.2 Live Workspace Projection 还没有完全去状态化
`EditorWorkspaceWindowContentController` 当前内部仍持有:
- `UIEditorWorkspaceController`
- `EditorShellRuntime`
- `EditorWindowFrameOrchestrator`
这意味着当前 workspace window 仍然有一个 live mutable controller。它已经不是 authority但也还不是完全只读 projection。
当前真实行为是:
- `EditorWorkspaceWindowContentController::UpdateAndAppend(...)` 会在 layout snapshot 发生变化时发出显式 `workspaceMutation` request。
- `EditorWorkspaceWindowContentController` 现在持有显式 `EditorWorkspaceWindowProjection`host 常规同步 / presentation 路径优先消费 projection refresh而不是整体替换 live controller。
- `EditorWindow::TryGetWorkspaceController()` 仍保留给局部交互 / 过渡路径使用,但它不再是常规 host 同步主接口。
- 每个 workspace window 依然持有自己的一份 live `UIEditorWorkspaceController`
因此:
- 不要把当前架构写成“projection-only content controller 已完成”。
## 5. 窗口类别与内容控制器
当前窗口系统显式区分两类窗口:
- `EditorWindowCategory::Workspace`
- `EditorWindowCategory::Utility`
两类窗口共享同一个 native host
```text
EditorWindow
-> EditorWindowRuntimeController
-> D3D12WindowRenderLoop
-> EditorWindowContentController
```
### 5.1 Workspace Window
workspace window 的内容控制器是 `EditorWorkspaceWindowContentController`
它是完整 shell/workspace 容器,用于:
- 主窗口
- detached workspace window
### 5.2 Utility Window
utility window 的内容控制器是 `EditorUtilityWindowContentController`,内部承载 `EditorUtilityWindowPanel`
当前 registry / factory 主线是显式 descriptor 驱动:
- `EditorUtilityWindowDescriptor`
- `EditorUtilityWindowReusePolicy`
- `EditorWindowChromePolicy`
- `EditorWindowNativeStylePolicy`
当前已注册的 utility window
- `ColorPicker`
- `AddComponent`
两者当前都使用 `SingleInstance` 复用策略。
### 5.3 Capability 校验
窗口内容能力由 `EditorWindowContentCapabilities` 描述,`EditorWindowHostRuntime::CreateEditorWindow(...)` 在创建时做硬校验:
- `Workspace` 分类要求 `capabilities.workspace == true`
- `Utility` 分类要求 `capabilities.utilityPanel == true`
不要依赖“后续 coordinator 看到空 binding 再兜底”这种旧思路。
## 6. Frame Request 与每帧主线
`EditorWindowFrameTransferRequests` 当前按两个子域组织:
```text
workspace:
workspaceMutation
beginGlobalTabDrag
detachPanel
utility:
openUtilityWindow
```
当前事实:
- `workspaceMutation` 已经是 frame 内 workspace 变化的显式回传入口。
- `openUtilityWindow` 来自 `EditorContext::RequestOpenUtilityWindow(...)`,由 `EditorWindowFrameOrchestrator` 消费 request state 后写入 frame transfer request。
- queued immediate frame 也按这两个子域分别合并。
steady-state frame 主路径是:
```text
Application::Run
-> EditorWindowManager::RenderAllWindows
-> EditorWindowHostRuntime::RenderAllWindows
-> EditorWindowFrameDriver::DriveFrame
-> EditorWindowRuntimeController::UpdateAndAppend
-> EditorWindowContentController::UpdateAndAppend
-> EditorWindowWorkspaceCoordinator::RefreshWindowPresentation
-> EditorWindowWorkspaceCoordinator::HandleWindowFrameTransferRequests
-> EditorUtilityWindowCoordinator::HandleWindowFrameTransferRequests
```
另外,`WM_PAINT``WM_SIZE``WM_DPICHANGED``WM_EXITSIZEMOVE` 等消息也会触发 immediate frame并在 message dispatcher 中 flush queued transfer requests。
## 7. 修改规范
- 先判断改动属于 framework、app semantics、windowing、Win32 host 还是 rendering host。
- 小改动优先贴近现有模式,不顺手做跨层重构。
- 新增通用 widget 放 `editor/src` / `editor/include/XCEditor`
- 新增具体 editor 功能放 `editor/app/Features/<FeatureName>`,再由 composition 装配。
- 新增 utility window 先补 `EditorUtilityWindowKind``EditorUtilityWindowDescriptor``CreateEditorUtilityWindowPanel(...)`,不要直接在 Win32 coordinator 里硬编码窗口类型。
- 新增跨窗口语义时,优先增加显式 frame request 或 app/windowing plan builder不要回退到 Win32 host 直接读写 authority。
- 修改窗口同步逻辑时,区分“当前代码事实”和“长期目标”。当前还存在 live mutable projection不要按尚未落地的终态直接删接口。
- 不要让 `editor/include/XCEditor/**` 暴露 `App::*` 类型。
- draw append 只负责绘制,不顺手修改 scene / project / authority 状态。
## 8. 当前架构债务
当前仍然存在的主要债务:
-`XCUIEditorLib`app core、windowing、Win32 host、rendering host 还没有真实拆成独立 target。
- `EditorContext` 仍然很重,混合了 shell asset、项目/场景运行时、selection、command focus、utility window request 和状态输出。
- `EditorShellRuntime` 仍然很重,既负责 shell compose / interaction也负责 hosted panel、viewport request 和 draw append。
- `EditorWorkspaceWindowContentController` 仍持有 live mutable `UIEditorWorkspaceController`,只是 host 常规同步 / presentation 已经切到 projection refreshprojection 和 authority 的边界仍未完全硬化。
- `EditorWindowWorkspaceCoordinator` 仍然过厚,还没有收缩成纯粹的 host executor + native event bridge。
- `EditorWindow::TryGetWorkspaceController()` 仍存在于交互 / 过渡路径,说明 live projection 去状态化还没完成;但常规同步路径已经不再依赖 `ReplaceWorkspaceController()`
这些都是当前事实,不要在新的规范文档或代码注释里把它们写成“已经解决”。
## 9. 验证入口
当前 editor 相关验证入口统一在 `tests/UI/Editor`
- `editor_ui_tests`
framework 和基础 UI 单元测试。
- `editor_windowing_phase1_tests`
当前窗口 authority / planner / reconcile 规则的 focused unit tests。
- `xcui_editor_app_smoke`
editor 启动烟测。
- `tests/UI/Editor/manual_validation`
复杂交互人工验证场景。
条件事实:
- `editor_app_feature_tests` 只会在 `XCUIEditorAppLib` 等可选 target 真实存在时创建。
- 不要把它当成当前 checkout 一定存在的测试目标。
涉及窗口系统的改动,优先保持:
- `XCUIEditorApp` 可构建
- `editor_windowing_phase1_tests` 不回退
- `xcui_editor_app_smoke` 不回退
## 10. 推荐阅读入口
开始 editor 相关任务时,优先阅读:
- `editor/CMakeLists.txt`
- `editor/app/Bootstrap/Application.*`
- `editor/app/Composition/EditorContext.*`
- `editor/app/Composition/EditorShellRuntime.*`
- `editor/app/Windowing/Content/EditorWindowContentController.h`
- `editor/app/Windowing/Content/EditorWorkspaceWindowContentController.*`
- `editor/app/Windowing/Frame/EditorWindowFrameOrchestrator.*`
- `editor/app/Windowing/System/EditorWindowSystem.*`
- `editor/app/Platform/Win32/Windowing/EditorWindow.*`
- `editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.*`
- `editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.*`
- `editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.*`
- `editor/app/UtilityWindows/EditorUtilityWindowRegistry.*`
- `tests/UI/Editor/unit/CMakeLists.txt`
- `tests/UI/Editor/smoke/CMakeLists.txt`