Files
XCEngine/editor/AGENTS.md

13 KiB
Raw Blame History

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:

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

XCUIEditorAppLibXCUIEditorAppCoreXCUIEditorHost 不是当前 editor/CMakeLists.txt 里真实定义的生产 target它们只在部分测试脚本或清理逻辑里作为条件名称出现。不要把这些名字当成当前已经存在的模块边界。

2. 当前分层

推荐按下面五层理解和修改,但要记住这主要是目录和语义边界,不是已经被 CMake 强制落实的编译边界:

  1. editor/src / editor/include/XCEditor XCEditor framework。这里应保持通用不依赖具体 editor app、Win32 宿主或 D3D12 实现。

  2. editor/app/CompositionCommandsFeaturesProjectSceneStateSupportSystemUtilityWindows 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。

依赖方向尽量保持为:

XCEditor framework
  <- app semantics
  <- app/windowing
  <- Platform/Win32
  <- app/Rendering

现实约束:

  • 当前只有 XCUIEditorLib 是真实独立 target。
  • 其余层级只是目录和 ownership 约定。
  • 修改时仍要主动控制 include 方向,避免把“语义上应该分层”写回成硬耦合。

3. 顶层启动流程

入口:

app/main.cpp
  -> RunXCUIEditorApp
  -> Application::Run

当前启动主线:

Application
  -> EditorContext
  -> Win32SystemInteractionHost
  -> EditorWindowSystem
  -> EditorWindowManager
      -> EditorWindowHostRuntime
      -> EditorWindowWorkspaceCoordinator
      -> EditorUtilityWindowCoordinator
      -> EditorWindowLifecycleCoordinator

primary workspace window 的 bootstrap 顺序是:

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 现在持有显式 EditorWorkspaceWindowProjectionhost 常规同步 / presentation 路径优先消费 projection refresh而不是整体替换 live controller。
  • EditorWindow::TryGetWorkspaceController() 仍保留给局部交互 / 过渡路径使用,但它不再是常规 host 同步主接口。
  • 每个 workspace window 依然持有自己的一份 live UIEditorWorkspaceController

因此:

  • 不要把当前架构写成“projection-only content controller 已完成”。

5. 窗口类别与内容控制器

当前窗口系统显式区分两类窗口:

  • EditorWindowCategory::Workspace
  • EditorWindowCategory::Utility

两类窗口共享同一个 native host

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 当前按两个子域组织:

workspace:
  workspaceMutation
  beginGlobalTabDrag
  detachPanel

utility:
  openUtilityWindow

当前事实:

  • workspaceMutation 已经是 frame 内 workspace 变化的显式回传入口。
  • openUtilityWindow 来自 EditorContext::RequestOpenUtilityWindow(...),由 EditorWindowFrameOrchestrator 消费 request state 后写入 frame transfer request。
  • queued immediate frame 也按这两个子域分别合并。

steady-state frame 主路径是:

Application::Run
  -> EditorWindowManager::RenderAllWindows
      -> EditorWindowHostRuntime::RenderAllWindows
          -> EditorWindowFrameDriver::DriveFrame
              -> EditorWindowRuntimeController::UpdateAndAppend
                  -> EditorWindowContentController::UpdateAndAppend
          -> EditorWindowWorkspaceCoordinator::RefreshWindowPresentation
          -> EditorWindowWorkspaceCoordinator::HandleWindowFrameTransferRequests
          -> EditorUtilityWindowCoordinator::HandleWindowFrameTransferRequests

另外,WM_PAINTWM_SIZEWM_DPICHANGEDWM_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 先补 EditorUtilityWindowKindEditorUtilityWindowDescriptorCreateEditorUtilityWindowPanel(...),不要直接在 Win32 coordinator 里硬编码窗口类型。
  • 新增跨窗口语义时,优先增加显式 frame request 或 app/windowing plan builder不要回退到 Win32 host 直接读写 authority。
  • 修改窗口同步逻辑时,区分“当前代码事实”和“长期目标”。当前还存在 live mutable projection不要按尚未落地的终态直接删接口。
  • 不要让 editor/include/XCEditor/** 暴露 App::* 类型。
  • draw append 只负责绘制,不顺手修改 scene / project / authority 状态。

8. 当前架构债务

当前仍然存在的主要债务:

  • XCUIEditorLibapp 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