# XCUI Editor Agent Guide 这份文档面向在 `editor/` 下工作的 coding agent / 开发者。它描述当前 editor 的真实工程边界、窗口架构和修改约束,不是产品说明。 如果本文和当前代码、`editor/CMakeLists.txt`、实际目录结构冲突,以当前 checkout 为准,并在本次工作里同步修正文档。 ## 1. 当前定位 `editor/` 是当前 editor 应用主线。 当前工程事实: - 构建目标是 `XCUIEditorApp`。 - 输出名是 `XCEngine`,构建产物为 `XCEngine.exe`。 - `editor/src` 是可复用的 XCEditor UI framework。 - `editor/include/XCEditor` 是 `editor/src` 的公开接口。 - `editor/app` 是具体 XCEngine editor 应用层。 - `editor/resources` 存放 editor 自有图标和 scene viewport shader。 虽然 `editor/CMakeLists.txt` 仍把这些代码编进一个可执行目标,但语义上已经分成 framework、app core、Win32 host 和 D3D12 host 四层。 ## 2. 分层边界 推荐按下面五层理解和修改: 1. `editor/src` / `editor/include/XCEditor` XCEditor UI framework。这里应保持通用,不依赖具体项目、场景、Win32 宿主或 D3D12 实现。 2. `editor/app/Composition`、`Features`、`Project`、`Scene`、`State`、`Commands` Editor app core。这里装配 panel、项目运行时、场景运行时、选择状态、命令路由和 shell frame。 3. `editor/app/Windowing` Editor host seam。这里放平台无关的窗口内容 contract、workspace/utility content assembly、frame orchestration 和 host-facing transfer request。 4. `editor/app/Platform/Win32` Win32 host。这里负责原生窗口、消息分发、窗口生命周期、输入收集、title bar / chrome 和 surface/presenter。 5. `editor/app/Rendering` Editor rendering host。这里负责 D3D12 UI 渲染、窗口 swapchain、viewport 离屏资源、editor 图标纹理和 scene viewport pass。 依赖方向尽量保持: ```text app/platform + app/rendering -> app/windowing -> app/core -> XCEditor framework -> engine UI primitives ``` 不要让 `editor/src` 反向依赖 `editor/app`。 ### 2.1 长期目标:把语义分层落成真实模块边界 当前 `editor/` 已经有语义上的四层划分,但还没有真正的编译/依赖边界。窗口相关代码最重要的长期目标,不是继续细拆 `Win32` 目录里的类,而是把下面这条关系变成代码和构建系统都能强制执行的事实: ```text XCEditor framework <- editor app core <- editor host seam / app/Windowing <- Win32 host + D3D12 host ``` 收敛要求: - `editor/app/Platform/Win32` 只负责 native window、message pump、input translation、chrome、lifecycle 和 surface/presenter 等宿主职责。 - workspace mutation、utility window routing、shell composition、window content assembly 这类产品语义应逐步收敛到平台无关层,而不是继续堆进 Win32 host。 - `editor/src` / `editor/include/XCEditor` 不允许反向依赖 `editor/app`;公开头文件不应暴露 `App::*` 类型。 - 最终要通过独立 CMake target 和受限 include dirs 落实,而不是只靠目录约定。 后续凡是修改窗口系统,优先朝“缩小 `Platform/Win32` 对 `Composition`、`Features`、`UtilityWindows`、`Rendering` 的直接依赖面”这个方向收敛。如果一个新需求只能通过继续把业务语义塞进 Win32 host 才能完成,应先停下来评估是否缺少平台无关的 host seam。 ## 3. 顶层启动流程 入口: ```text app/main.cpp -> RunXCUIEditorApp -> Application::Run ``` 核心对象关系: ```text Application -> EditorContext -> EditorWindowManager -> EditorWindow -> EditorWindowRuntimeController -> D3D12WindowRenderer -> D3D12UiRenderer -> D3D12WindowRenderLoop -> EditorWindowContentController -> EditorWorkspaceWindowContentController -> EditorUtilityWindowContentController ``` `EditorContext` 是全局共享应用状态。每个 workspace window 持有自己的 `UIEditorWorkspaceController` 和 `EditorShellRuntime`。utility window 不持有 workspace controller。 ## 4. 显式窗口架构 当前窗口系统已经显式区分两类窗口: - `EditorWindowCategory::Workspace` 主窗口和由 dock tab / panel 拖出的独立窗口。 - `EditorWindowCategory::Utility` 颜色选择器、Add Component 这类天然工具窗。 两类窗口共享同一个 native host: ```text EditorWindow -> EditorWindowRuntimeController -> D3D12WindowRenderLoop -> EditorWindowContentController ``` 差异放在 content controller 和 policy 上,而不是靠“有没有 workspace binding”隐式推断。 ### 4.1 Workspace Window workspace window 的内容控制器是 `EditorWorkspaceWindowContentController`,内部持有: - `UIEditorWorkspaceController` - `EditorShellRuntime` - `EditorWindowFrameOrchestrator` 这类窗口是完整 shell/workspace 容器。主窗口和 detached workspace window 都属于这一类。 ### 4.2 Utility Window utility window 的内容控制器是 `EditorUtilityWindowContentController`,内部持有: - `EditorUtilityWindowPanel` 当前 utility 窗口通过 registry/factory 创建,已实现显式 descriptor: - `EditorUtilityWindowDescriptor` - `EditorUtilityWindowReusePolicy` - `EditorWindowChromePolicy` - `EditorWindowNativeStylePolicy` 当前 `ColorPicker` 和 `AddComponent` 都是单例复用窗口。 ## 5. 窗口能力与策略 窗口内容能力由 `EditorWindowContentCapabilities` 描述。创建窗口时,host 会校验: - `Workspace` 分类必须对应具备 workspace capability 的 content controller。 - `Utility` 分类必须对应具备 utility capability 的 content controller。 这一步是硬校验,不再依赖后续 coordinator 通过空 binding 兜底。 窗口外观/宿主策略当前最少包括: - `EditorWindowChromePolicy` 当前用于控制 detached title bar tab strip、frame stats,以及 utility window 的 topmost pin 按钮/默认置顶策略。 - `EditorWindowNativeStylePolicy` 当前用于控制扩展窗口样式和是否复用 host 默认 style。 当前默认规则: - workspace window 允许 detached title bar tab strip。 - utility window 不允许 detached title bar tab strip。 - utility window 不显示 frame stats。 - utility window 顶栏显示 topmost pin 按钮,且默认置顶。 - utility window 使用 `WS_EX_TOOLWINDOW`。 ## 6. Workspace / Utility 协调器边界 ### 6.1 Workspace Coordinator `EditorWindowWorkspaceCoordinator` 只处理 `Workspace` 窗口: - 维护 window workspace set - 处理 detach panel - 处理 global tab drag - 处理 cross-window dock/drop - 更新 detached workspace title utility window 不参与: - workspace set - dock target hit test - cross-window drop target ### 6.2 Utility Coordinator `EditorUtilityWindowCoordinator` 只处理 utility window 请求: - 根据 `EditorUtilityWindowDescriptor` 创建工具窗 - 按 reuse policy 决定复用还是新建 - 对现有 utility window 做 focus / restore 不要把 utility window 塞进 workspace mutation 流程。 ## 7. Frame Request 结构 `EditorWindowFrameTransferRequests` 已拆成两个子域: ```text workspace: beginGlobalTabDrag detachPanel utility: openUtilityWindow ``` 规则: - `EditorWindowWorkspaceCoordinator` 只消费 `transferRequests.workspace` - `EditorUtilityWindowCoordinator` 只消费 `transferRequests.utility` - queued immediate frame 也按两个子域分别合并 不要再把 workspace 和 utility 的窗口请求混进同一个平铺字段集合。 ## 8. 每帧流程 当前每帧主路径: ```text Application::Run -> EditorWindowManager::RenderAllWindows -> EditorWindowRuntimeController::BeginFrame -> EditorWindowRuntimeController::UpdateAndAppend -> EditorWindowFrameOrchestrator::UpdateAndAppend -> EditorShellRuntime::Update -> EditorShellSessionCoordinator::PrepareShellDefinition -> EditorShellInteractionEngine::Update -> UpdateUIEditorShellInteraction -> ViewportHostService::RequestViewport -> EditorShellSessionCoordinator::FinalizeFrame -> EditorShellHostedPanelCoordinator::Update -> EditorShellRuntime::Append -> EditorWindowRuntimeController::RenderRequestedViewports -> EditorWindowRuntimeController::Present ``` 重要约束: - viewport 先在 shell layout 阶段通过 `RequestViewport()` 申明尺寸和纹理需求。 - 再在 `RenderRequestedViewports()` 阶段真正渲染。 - 不要打乱这两个阶段的顺序。 ## 9. 修改规范 - 先判断改动属于 framework、app core、windowing seam、Win32 host 还是 rendering host。 - 小改动优先贴近现有模式,不顺手做跨层重构。 - 新增通用 widget 放 `editor/src` / `editor/include/XCEditor`。 - 新增具体 editor 功能放 `editor/app/Features/`,再由 composition 装配。 - 新增 host-facing window content、frame request、content assembly 放 `editor/app/Windowing`。 - 新增 Win32 宿主行为放 `editor/app/Platform/Win32`,通过 seam/controller/policy 与 app core 通信。 - 新增 viewport 渲染资源或 pass 放 `editor/app/Rendering/Viewport` 或 `editor/resources/shaders/scene-viewport`。 - draw append 只负责绘制,不修改 editor runtime 或 scene/project state。 - D3D12 host、Win32 host、panel 之间避免双向强耦合。 ## 10. 当前架构债务 这轮重构完成后,仍有以下债务: - `editor/CMakeLists.txt` 还没有把 framework、app core、windowing seam、Win32 host、D3D12 host 拆成独立 target。 - `EditorContext` 仍然过重,混合了全局状态、service locator、command bridge、session sync 和状态输出。 - `EditorShellRuntime` 仍然过重,既持有 panel,又持有 viewport host、shell frame、draw composer 和 interaction coordinator。 - panel 仍缺少统一 feature 接口,`HierarchyPanel`、`ProjectPanel`、`InspectorPanel` 只是模式相似。 - `app/Windowing` 目前只是首刀 ownership 调整,workspace / utility window orchestration 仍主要停留在 Win32 coordinator。 这些债务后续要分步处理,不要一次性重写整个窗口系统。 ## 11. 验证基线 当前这轮窗口架构重构的验证状态: - 用户已完成 GUI 行为验证。 - `cmake --build build --config Debug --target XCUIEditorApp` 已通过。 - `build/editor/Debug/XCEngine.exe` 的 12 秒启动冒烟测试已通过,进程可正常响应关闭请求。 后续涉及窗口架构的改动,至少应维持这条验证基线。 ## 12. 推荐阅读入口 开始 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/Frame/EditorWindowFrameOrchestrator.*` - `editor/app/Platform/Win32/Windowing/EditorWindow.*` - `editor/app/Platform/Win32/Windowing/EditorWindowWorkspaceCoordinator.*` - `editor/app/Platform/Win32/Windowing/EditorUtilityWindowCoordinator.*` - `editor/app/UtilityWindows/EditorUtilityWindowRegistry.*` - `editor/include/XCEditor/Workspace/UIEditorWorkspaceController.h` - `editor/include/XCEditor/Shell/UIEditorShellInteraction.h`