Files
XCEngine/editor/AGENTS.md

12 KiB
Raw Blame History

XCUI Editor Agent Guide

This file documents the current editor architecture for agents working under editor/. It describes the code that exists in this checkout, not a desired future shape.

If this file conflicts with the current code, editor/CMakeLists.txt, or the real directory tree, trust the code and update this file in the same change.

Build Shape

The important production targets are:

  • XCUIEditorLib: reusable XCEditor framework code from editor/src and editor/include/XCEditor, including the reusable window authority, synchronization planner, and presentation projection under XCEditor/Windowing.
  • XCUIEditorAppWindowing: app-internal static library for the current host contracts, content controllers, coordinators, frame transfer flow, and window manager.
  • XCUIEditorApp: concrete editor executable. Its output name is XCEngine.

Do not invent target boundaries that are not present in editor/CMakeLists.txt. Names such as XCUIEditorAppCore, XCUIEditorAppLib, and XCUIEditorHost are not current production library boundaries in this checkout.

There is now a narrow public editor/include/XCEditor/Windowing layer for the generic window authority model, synchronization plan/planner, and presentation projection. App-specific window orchestration remains under editor/app/Windowing, and the concrete Win32 host remains under editor/app/Platform/Win32.

Layering

Use these ownership boundaries when changing code:

  • editor/include/XCEditor and editor/src: reusable editor framework. Keep this layer independent from app state, Win32, D3D12 host code, and App::* types.
  • editor/include/XCEditor/Windowing and editor/src/Windowing: reusable window authority, validation, synchronization planning, commit, and presentation projection. Keep this layer generic and free of app content, host runtime, native platform, and rendering details.
  • editor/app/Composition, Commands, Features, Project, Scene, State, System, UtilityWindows: editor product semantics.
  • editor/app/Windowing/Content, Coordinator, Frame, Host: platform neutral app window orchestration.
  • editor/app/Platform/Win32: native window, message dispatch, input, lifecycle, chrome, and concrete host runtime.
  • editor/app/Rendering: editor rendering host and D3D12 integration.

The semantic dependency direction should remain:

XCEditor framework
  <- editor app semantics
  <- app windowing runtime
  <- Win32 host / rendering host

Startup Flow

The application starts through:

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

The primary workspace window is initialized through:

EditorContext::BuildWorkspaceController()
  -> EditorWindowSystem::BootstrapPrimaryWindow(...)
  -> EditorWindowManager::CreateWorkspaceWindow(...)
  -> EditorWindowContentFactory::CreateWorkspaceContentController(...)
  -> EditorWindowHostRuntime::CreateHostWindow(...)

Keep authoritative window bootstrap in EditorWindowSystem; do not move it back into the Win32 host.

Window Authority Model

EditorWindowSystem owns the authoritative UIEditorWindowWorkspaceSet through EditorWindowWorkspaceStore.

Normal per-frame workspace edits now use direct writes into that authoritative state:

EditorWorkspaceWindowContentController::UpdateAndAppend(...)
  -> EditorWindowSystem::TryBuildLiveWindowWorkspaceController(windowId, ...)
  -> UIEditorWorkspaceController::BindToState(...)
  -> workspace operations mutate the bound authoritative workspace/session

The old normal path is obsolete:

snapshot diff
  -> workspaceMutation frame request
  -> coordinator
  -> synchronization plan
  -> commit

Do not reintroduce workspaceMutation as the steady-state route for ordinary layout, tab, visibility, or active-panel edits inside an existing workspace window.

Cross-window create, update, close, and destroyed-window reconciliation still use the planner/coordinator flow:

target UIEditorWindowWorkspaceSet
  -> EditorWindowSystem::BuildPlanForWindowSet(...)
  -> EditorWindowWorkspaceCoordinator::ApplySynchronizationPlan(...)
  -> EditorWindowSystem::CommitSynchronizationPlan(...)

EditorWindowWorkspaceCoordinator::RefreshWindowPresentation(...) refreshes each workspace window projection from authoritative state. Presentation should follow authority; it should not become a second source of truth.

Frame Transfer Requests

EditorWindowFrameTransferRequests is only for host-side or cross-window side effects that cannot be represented as direct in-window workspace edits.

Current request fields are:

  • workspace.beginGlobalTabDrag
  • workspace.detachPanel
  • utility.openUtilityWindow

There is no workspace.workspaceMutation field in the current frame transfer contract. Treat any doc, comment, or test name that says otherwise as stale.

Window Categories

Workspace and utility windows share the native host path but use distinct content controllers.

  • Workspace windows use EditorWorkspaceWindowContentController.
  • Utility windows use EditorUtilityWindowContentController.
  • App windowing creates content through EditorWindowContentFactory.
  • The concrete host validates EditorWindowContentCapabilities when a native host window is created.

Utility windows are descriptor driven through EditorUtilityWindowDescriptor, EditorUtilityWindowRegistry, and CreateEditorUtilityWindowPanel(...). Register new utility windows there rather than hard-coding them in Win32 host logic.

Modification Rules

  • First decide whether the change belongs to XCEditor framework, app semantics, app windowing, Win32 host, or rendering host.
  • Keep public framework headers free of App::*, Win32, and D3D12 host types.
  • Do not add editor/app as an include directory for XCUIEditorLib. App-only services must cross into framework code through framework-owned interfaces and app-side adapters.
  • Do not compile ${XCUI_EDITOR_SHARED_SOURCES} directly into XCUIEditorApp; the executable should consume shared framework code through XCUIEditorLib.
  • Use editor/include/XCEditor/Windowing and editor/src/Windowing for generic window authority, synchronization, validation, and presentation projection.
  • Use editor/app/Windowing for app-specific window runtime semantics, content, frame transfer, host contracts, and coordinators.
  • Use editor/app/Platform/Win32 only for native host behavior and message integration.
  • Do not let editor/app/Windowing include Platform/Win32 or D3D12 concrete host headers.
  • Do not let Win32 host code create workspace or utility content directly. It should receive content through the app-windowing host contract.
  • Use direct authoritative workspace binding for ordinary in-window workspace mutations.
  • Use synchronization plans for operations that create, close, replace, or reconcile workspace windows.
  • Use frame transfer requests only for host-side or cross-window effects.

Current Architecture Debt

The highest-value windowing boundary has been hardened: XCUIEditorLib now owns the reusable window authority, synchronization planner, workspace store, and presentation projection under XCEditor/Windowing. XCUIEditorAppWindowing owns the app-internal content controller factory, coordinators, frame transfer flow, host contracts, and manager. The Win32 host is the concrete native adapter and creates native host windows from content supplied by app windowing.

The framework/app compile boundary is also enforced. XCUIEditorLib does not receive editor/app includes, and XCUIEditorApp does not directly compile the shared framework sources. When framework UI code needs app-provided data such as loaded icons, expose a framework-owned interface and adapt it in app composition code.

The main remaining debt is promotion discipline around the app runtime surface. XCUIEditorAppWindowing is still app-internal and may depend on app semantics such as EditorContext, EditorShellRuntime, utility window descriptors, and product-specific content. Do not promote host interfaces, frame transfer, or content controllers to XCEditor until they are generic enough to expose.

Validation

Default editor validation is only the app build plus the 12-second smoke run:

cmake --build build --config Debug --target editor_ui_smoke_targets
build\tests\UI\Editor\smoke\Debug\editor_ui_smoke_runner.exe build\editor\Debug\XCEngine.exe

Do not run editor_windowing_phase1_tests, editor_ui_tests, or broader test targets by default. Run them only when the user explicitly asks for them or a separate targeted change makes them necessary.

The runner sets XCUIEDITOR_SMOKE_TEST_DURATION_SECONDS=12, waits for the editor to launch, lets the app auto-exit, and treats a clean editor exit as success.

Start with these files for editor/windowing work:

  • editor/CMakeLists.txt
  • editor/app/Bootstrap/Application.*
  • editor/app/Composition/EditorContext.*
  • editor/app/Composition/EditorShellRuntime.*
  • editor/include/XCEditor/Workspace/UIEditorWorkspaceController.h
  • editor/src/Workspace/UIEditorWorkspaceController.cpp
  • editor/include/XCEditor/Windowing/System/EditorWindowSystem.h
  • editor/include/XCEditor/Windowing/System/EditorWindowSynchronizationPlan.h
  • editor/include/XCEditor/Windowing/System/EditorWindowSynchronizationPlanner.h
  • editor/include/XCEditor/Windowing/Presentation/EditorWorkspaceWindowProjection.h
  • editor/include/XCEditor/Windowing/Presentation/EditorWindowPresentationPolicy.h
  • editor/src/Windowing/System/EditorWindowSystem.cpp
  • editor/src/Windowing/System/EditorWindowWorkspaceStore.*
  • editor/src/Windowing/System/EditorWindowSynchronizationPlanner.cpp
  • editor/src/Windowing/Presentation/EditorWindowPresentationPolicy.cpp
  • editor/app/Windowing/Host/EditorWindowHostInterfaces.h
  • editor/app/Windowing/Content/EditorWindowContentController.h
  • editor/app/Windowing/Content/EditorWindowContentFactory.*
  • editor/app/Windowing/Content/EditorWorkspaceWindowContentController.*
  • editor/app/Windowing/Frame/EditorWindowFrameOrchestrator.*
  • editor/app/Windowing/Frame/EditorWindowTransferRequests.h
  • editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.*
  • editor/app/Windowing/Coordinator/EditorUtilityWindowCoordinator.*
  • editor/app/Windowing/EditorWindowManager.*
  • editor/app/Platform/Win32/Windowing/EditorWindow.*
  • editor/app/Platform/Win32/Windowing/EditorWindowHostRuntime.*
  • editor/app/Platform/Win32/Windowing/EditorWindowMessageDispatcher.*
  • tests/UI/Editor/smoke/CMakeLists.txt

前面几刀

  • 最近一刀封死 framework -> app 的反向依赖:UIEditorShellCompose 不再认识 App::BuiltInIcons,改由 UIEditorShellIconResolver 抽象取图标, app 在 EditorShellDrawComposer 里用 adapter 连接 BuiltInIcons
  • 同一刀收紧构建边界:XCUIEditorLib 不再拥有 editor/app include XCUIEditorApp 不再直接编译 ${XCUI_EDITOR_SHARED_SOURCES},也不再把 editor/src 加进 includeapp 通过 XCUIEditorLib 消费 framework。
  • 前一刀把窗口权威核心切到 frameworkEditorWindowSystem、同步计划/规划器、 workspace store 和 presentation projection 位于 editor/include/XCEditor/Windowingeditor/src/Windowing
  • editor/app/Windowing 保留 app-specific 的 content controllers、coordinators、 frame transfer、host contracts 和 EditorWindowManagerWin32 host 仍只做 native adapter。
  • 未提升到 XCEditor 的内容包括 EditorContextEditorShellRuntime、utility descriptors/panels、host interfaces、content controllers、coordinators、 frame transfer 和 Win32/D3D12 host。
  • 默认验证也收口:只构建 XCUIEditorApp 相关 smoke 目标并跑 12 秒 smoke 需要专项覆盖时再单独运行 windowing/unit targets。