530 lines
31 KiB
Markdown
530 lines
31 KiB
Markdown
# XCUI Editor Agent Guide
|
|
|
|
This file is a working map for agents changing `editor/`. It is not a
|
|
substitute for reading the code. If this guide conflicts with the current
|
|
implementation, trust the implementation and update this guide in the same
|
|
change.
|
|
|
|
## Build Shape
|
|
|
|
- The root `CMakeLists.txt` always adds `editor/` before `tests/`.
|
|
- `editor/CMakeLists.txt` always builds `XCUIEditor`, a static library made
|
|
from `editor/include/XCEditor/**` plus `editor/src/**`.
|
|
- `XCUIEditor` outputs `XCUIEditor.lib` and is the reusable, platform-neutral
|
|
editor UI layer. It links
|
|
against `XCEngine` and is covered mainly by `tests/UI/Editor/unit`.
|
|
- The production editor target shape is fixed at three targets:
|
|
`XCUIEditor`, the reusable editor UI library; `XCEditorCore`, the editor
|
|
product-core library; and `XCEditor`, the thin product executable.
|
|
- `XCEditorCore` outputs `XCEditorCore.lib` and owns product editor logic that
|
|
should be buildable without the concrete Win32/D3D12 executable host:
|
|
composition, commands, state, project and scene services, feature panels,
|
|
utility-window descriptors, viewport services, and editor window core.
|
|
- `XCEditorCore` is controlled by `XCENGINE_BUILD_XCUI_EDITOR_CORE`, which
|
|
defaults to `ON` and is independent of `XCENGINE_BUILD_XCUI_EDITOR_APP`.
|
|
App-off core validation must configure with
|
|
`XCENGINE_BUILD_XCUI_EDITOR_APP=OFF` while keeping
|
|
`XCENGINE_BUILD_XCUI_EDITOR_CORE=ON`.
|
|
- `editor_app_core_tests` links `XCEditorCore` directly and is the build
|
|
gate that proves the product-core boundary outside the executable host.
|
|
- `editor_app_feature_tests` also links `XCEditorCore` directly. It restores
|
|
app feature and viewport coverage without reintroducing the old app-wide
|
|
include root or concrete Win32/D3D12 host dependencies.
|
|
- `XCEditorCore` does not publish the whole `editor/app` root as a usage
|
|
include directory. Its public app include surface is limited to shared
|
|
contracts under `app/Core`, `app/Commands`, `app/State`, and
|
|
`app/Host/Interfaces`.
|
|
- `XCEditorCore` also does not consume the whole `editor/app` root privately.
|
|
Its implementation include paths enumerate concrete app module roots such as
|
|
`app/Composition`, `app/Features`, `app/Windowing`, `app/Rendering`,
|
|
`app/Scene`, `app/Services`, and `app/Support`.
|
|
- `XCEditorCore` and `XCEditor` require
|
|
`XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT=ON`; the root build defaults that
|
|
support on when either the core library or app executable is enabled.
|
|
- `XCEditor` is built when `XCENGINE_BUILD_XCUI_EDITOR_APP=ON`; that mode
|
|
also requires `XCENGINE_BUILD_XCUI_EDITOR_CORE=ON`. The executable target is
|
|
named `XCEditor`, but its output name is `XCEngine`.
|
|
- The executable target owns process startup, Win32 hosting, D3D12 window
|
|
rendering, native resources, and the final composition-root wiring.
|
|
- Keep the CMake target named `XCEditor` so it does not collide with the engine
|
|
library target named `XCEngine`; keep the built executable output name as
|
|
`XCEngine`.
|
|
- Shared code uses C++20 and MSVC `/utf-8`; keep new files ASCII unless the
|
|
surrounding file already uses another encoding for a real reason.
|
|
|
|
## Directory Map
|
|
|
|
- `include/XCEditor/` is the public editor UI API: collections, docking,
|
|
fields, foundation, menus, panels, shell, viewport, widgets, windowing, and
|
|
workspace.
|
|
- `src/` implements that public API and may include private `src/**/Internal.h`
|
|
helpers. It should stay independent of app, Win32, D3D12, and project
|
|
runtime concerns.
|
|
- `app/Bootstrap/` contains process startup and shutdown through
|
|
`Application`.
|
|
- `app/Core/` contains app-level contracts and shared app model definitions
|
|
that are not owned by a concrete feature or composition implementation.
|
|
Current examples are panel IDs, shared window type contracts, host window
|
|
geometry/metrics, frame transfer requests, the panel-facing service view,
|
|
the windowing-facing frame-services/shell-runtime contracts, workspace-panel
|
|
runtime interface, and utility-window runtime/descriptors.
|
|
- `app/Host/Interfaces/` contains neutral host-facing contracts used across
|
|
editor core and executable host code: editor window host interfaces,
|
|
render-runtime factories, UI texture hosts, viewport render hosts, host
|
|
resource services, and system interaction services.
|
|
- `app/Host/Win32/` owns `HWND`, message dispatch, native pointer capture,
|
|
borderless chrome, DPI, placement, and Win32 system integration.
|
|
- `app/Host/D3D12/` owns the concrete D3D12 editor window render runtime, UI
|
|
renderer, texture host, text system, swap-chain presenter, and capture path.
|
|
- `app/Composition/` builds the editor shell asset, coordinates shell update
|
|
phases, and connects app state to hosted panel runtimes.
|
|
- `app/Windowing/` owns window instances, content controllers, lifecycle,
|
|
workspace synchronization, and utility-window creation.
|
|
- `app/Rendering/` owns built-in icons, viewport render targets, object
|
|
picking, scene viewport passes, and viewport render services.
|
|
- `app/Features/` contains user-facing panels and editor tools: Hierarchy,
|
|
Scene viewport, Inspector, Project, Console, Color Picker, and component UI.
|
|
- `app/Features/EditorWorkspacePanelRegistry.*` is the concrete workspace
|
|
panel factory. It owns the concrete workspace panel adapters. Shared
|
|
workspace-panel runtime interfaces live under `app/Core/WorkspacePanels`
|
|
so `app/Composition/**` can depend on the contract without depending on the
|
|
feature registry.
|
|
- `app/Features/EditorUtilityWindowRegistry.*` is the concrete utility-window
|
|
panel factory. Shared utility-window contracts and descriptors live under
|
|
`app/Core/UtilityWindows` so windowing can resolve utility window shape
|
|
without constructing concrete feature panels.
|
|
- `app/Services/Project/`, `app/Scene/`, and `app/State/` hold application
|
|
services that panels should use instead of owning global state themselves.
|
|
`ProjectBrowserModel` and `EditorProjectRuntime` live under
|
|
`app/Services/Project`; project panels adapt those service models into
|
|
widget-specific tree/list presentation data.
|
|
|
|
## Layering
|
|
|
|
- Keep `XCUIEditor` below the app. Public headers under `include/XCEditor`
|
|
must not include `app/**`, Win32, D3D12, or feature-panel headers.
|
|
- Keep platform specifics in `app/Host/Win32`; keep GPU-window specifics in
|
|
`app/Host/D3D12`.
|
|
- Keep neutral host/render/system contracts in `app/Host/Interfaces` or
|
|
shared value contracts in `app/Core`. Do not add new public app contracts
|
|
under concrete `app/Windowing`, `app/Rendering`, `app/Host/Win32`,
|
|
`app/Host/D3D12`, or legacy `app/Platform` paths.
|
|
- `app/Windowing/**` may depend on `app/Core/Windowing` contracts such as
|
|
`EditorFrameServices` and `EditorWorkspaceShellRuntime`, but it must not
|
|
include concrete `app/Composition/EditorContext.h` or
|
|
`app/Composition/EditorShellRuntime.h`.
|
|
- Keep shell composition and widget logic data-driven. The reusable layer should
|
|
emit frames, layouts, draw data, command results, and transfer requests; the
|
|
app decides how those requests affect native windows and engine services.
|
|
- Use existing controller types for mutation:
|
|
`UIEditorWorkspaceController`, `UIEditorWindowWorkspaceController`, and
|
|
`EditorWindowSystem`.
|
|
- Use the existing service objects for app state: `EditorContext`,
|
|
`EditorProjectRuntime`, `EditorSceneRuntime`, `EditorSelectionService`,
|
|
`EditorCommandFocusService`, and utility-window request state.
|
|
|
|
## Startup Flow
|
|
|
|
1. `app/main.cpp` enters `RunXCEditor`, which creates `Application`.
|
|
2. `Application::Initialize` resolves the repo root, enables DPI awareness,
|
|
initializes runtime tracing under the executable `logs/` directory, and
|
|
installs the unhandled-exception crash trace hook.
|
|
3. `EditorContext::Initialize` builds and validates the shell asset, initializes
|
|
project and scene runtimes, resets selection/focus/tool state, builds
|
|
command and shortcut services, and marks the shell ready.
|
|
4. `Application` registers the Win32 window class, creates the Win32 system
|
|
interaction host, bootstraps `EditorWindowSystem` with the primary
|
|
workspace state, creates `EditorWindowHostRuntime`, creates the D3D12 render
|
|
runtime factory, and constructs `EditorWindowManager`.
|
|
5. `EditorWindowManager::CreateWorkspaceWindow` creates an
|
|
`EditorWindowInstance`, attaches an `EditorWorkspaceWindowContentController`,
|
|
asks the host runtime to create the native window, and initializes the
|
|
per-window render/content runtime.
|
|
6. The main loop drains up to 64 Win32 messages per tick, updates async
|
|
resource loads, reaps destroyed windows, renders all running windows, and
|
|
honors smoke-test auto-exit settings.
|
|
7. `Application::WndProc` forwards registered windows to
|
|
`EditorWindowMessageDispatcher`; unknown messages fall back to
|
|
`DefWindowProcW`.
|
|
|
|
## Frame Runtime Ownership
|
|
|
|
- `EditorContext` owns the app-level shell asset, editor session, command
|
|
routing, selection/focus services, project runtime, scene runtime, color
|
|
picker state, pending utility-window requests, and the
|
|
`EditorFrameServices` implementation consumed by windowing.
|
|
- `EditorWindowSystem` owns the authoritative
|
|
`UIEditorWindowWorkspaceSet`. Workspace windows should derive their local
|
|
projection from this state rather than storing independent layout truth.
|
|
- `EditorWorkspaceWindowContentController` asks `EditorWindowSystem` for a live
|
|
`UIEditorWorkspaceController` every frame. A live controller writes mutations
|
|
through to the authoritative window workspace state; a copied controller is
|
|
only a preview.
|
|
- `EditorShellRuntime` owns per-window interactive runtime state: viewport host
|
|
service, built-in icons, the workspace panel runtime set, shell interaction
|
|
state/frame, splitter correction state, trace entries, draw composer,
|
|
interaction engine, hosted panel coordinator, and session coordinator.
|
|
- `EditorWorkspaceShellRuntime` is the windowing-facing shell runtime contract.
|
|
`EditorShellRuntime` is the current concrete implementation, and
|
|
`Application` injects it through the content factory instead of letting
|
|
`app/Windowing/**` construct or name the concrete type directly.
|
|
- The workspace shell runtime factory passed into windowing is intentionally
|
|
zero-argument. `Application` composes the concrete workspace-panel runtime
|
|
set with `EditorShellRuntime`; `app/Windowing/**` must not accept or call
|
|
`EditorWorkspacePanelRuntimeSetFactory`.
|
|
- `EditorWindowRuntimeController` owns the content controller, render runtime,
|
|
screenshot controller, title-bar logo texture, text measurer access, DPI
|
|
scale, and frame-rate display.
|
|
- `EditorWindowInstance` is the managed host-window object. It owns lifecycle
|
|
state and bridges its native peer to the runtime controller.
|
|
- `EditorWindow` in `app/Host/Win32/Windowing` owns the native peer
|
|
behavior: `HWND`, queued input, pointer capture, chrome interaction, resize
|
|
snapshots, cursor feedback, invalidation, and native destruction.
|
|
|
|
## Window Authority Model
|
|
|
|
- The authoritative window/workspace state is the
|
|
`UIEditorWindowWorkspaceSet` stored by `EditorWindowSystem`.
|
|
- Presentation data is derived from state through
|
|
`BuildEditorWorkspaceWindowProjection`; do not hand-maintain detached window
|
|
title, tab-strip title, primary flag, or minimum size in separate places.
|
|
- Workspace mutations that can affect multiple windows should start with
|
|
`EditorWindowSystem::BuildWorkspaceMutationController`, validate through
|
|
`ValidateWindowSet`, build a synchronization plan, apply host-window actions,
|
|
then commit the plan back to `EditorWindowSystem`.
|
|
- `EditorWindowSynchronizationPlanner` compares target workspace state against
|
|
host snapshots and emits create/update/close actions. Extend this planner and
|
|
its tests when changing workspace-window synchronization rules.
|
|
- Destroying the primary workspace window intentionally closes remaining
|
|
workspace windows. Destroying a detached workspace window reconciles the
|
|
authoritative window set and refreshes the remaining windows.
|
|
- `EditorWindowWorkspaceCoordinator::RefreshWindowPresentation` is the normal
|
|
path for refreshing projections and titles after a frame.
|
|
|
|
## Frame Transfer Requests
|
|
|
|
Frame transfer requests are the app boundary for work that cannot be committed
|
|
inside pure shell/widget code.
|
|
|
|
- The request contracts live in
|
|
`app/Core/Windowing/EditorWindowTransferRequests.h`.
|
|
- `EditorWindowFrameOrchestrator` converts shell results into
|
|
`EditorWindowFrameTransferRequests`.
|
|
- Workspace requests currently include `beginGlobalTabDrag` and `detachPanel`.
|
|
These are consumed by `EditorWindowWorkspaceCoordinator`.
|
|
- Utility requests currently include `openUtilityWindow`. These are produced
|
|
from `EditorContext::RequestOpenUtilityWindow` and consumed by
|
|
`EditorUtilityWindowCoordinator`.
|
|
- Panels and shell code should request window-level work through transfer
|
|
requests or context request state, not by creating/destroying native windows
|
|
directly.
|
|
- Global tab drag uses screen coordinates, a captured owner window, an external
|
|
dock-host drop preview on the target window, and
|
|
`EditorWindowPointerCaptureOwner::GlobalTabDrag`.
|
|
|
|
## Window Categories
|
|
|
|
- Workspace windows use `EditorWorkspaceWindowContentController`. They expose
|
|
workspace, dock-host, input-feedback, title-bar, and viewport-rendering
|
|
capabilities.
|
|
- Detached workspace windows are still workspace windows. Their projection can
|
|
enable the detached title-bar tab strip and derive the window title from the
|
|
single visible panel.
|
|
- Utility windows use `EditorUtilityWindowContentController`. They host an
|
|
`EditorUtilityWindowPanel`, do not participate in workspace synchronization,
|
|
and currently do not expose dock-host or viewport capabilities.
|
|
- Utility descriptors live in `app/Core/UtilityWindows/EditorUtilityWindowRegistry.cpp`.
|
|
Concrete utility panels are created by
|
|
`app/Features/EditorUtilityWindowRegistry.*` and injected through the window
|
|
content factory. Current utility windows are Color Picker and Add Component;
|
|
both are single-instance topmost tool windows.
|
|
|
|
## Shell, Panels, And Commands
|
|
|
|
- `EditorShellAssetBuilder.cpp` defines the product shell: panel registry,
|
|
default workspace layout, command registry, menus, toolbar buttons, shortcuts,
|
|
capture root, and status-bar definitions.
|
|
- Panel IDs are centralized in `app/Core/Panels/EditorPanelIds.h`; prefer
|
|
these constants over raw string literals in app code.
|
|
- `EditorPanelServices` is the Core service view passed into concrete
|
|
workspace and utility panels. Panels should use it instead of including
|
|
`Composition/EditorContext.h`; `EditorContext` remains a composition-owned
|
|
aggregate and request bridge.
|
|
- Workspace panels are adapted behind `EditorWorkspacePanelRuntimeSet`, whose
|
|
contract lives in `app/Core/WorkspacePanels/EditorWorkspacePanelRuntime.h`.
|
|
Composition code should ask that runtime set to initialize, prepare command
|
|
routes, update, draw, expose cursor/capture state, and collect frame events
|
|
instead of directly naming `HierarchyPanel`, `ProjectPanel`, `InspectorPanel`,
|
|
`ConsolePanel`, or `SceneViewportFeature`.
|
|
- Hosted panels receive mounted bounds and filtered input through
|
|
`UIEditorHostedPanelDispatchFrame`; concrete workspace-panel adapters resolve
|
|
their own dispatch entries from that frame.
|
|
- `EditorShellHostedPanelCoordinator` filters hosted-panel input when shell
|
|
capture owns the pointer stream, then updates `EditorWorkspacePanelRuntimeSet`.
|
|
Concrete adapters wire app services into their panels through
|
|
`EditorPanelServices`. The coordinator syncs command focus between the main
|
|
update phase and after-focus panels such as Console.
|
|
- `EditorHostCommandBridge` routes host commands to focused edit routes,
|
|
project asset routes, scene routes, inspector routes, workspace commands, or
|
|
the app exit handler.
|
|
- `WorkspaceEventSync` consumes generic `EditorWorkspacePanelFrameEvent`
|
|
entries from the workspace panel runtime set. Concrete hierarchy/project
|
|
event formatting lives behind the feature registry, while this sync layer
|
|
owns selection-backed session state, scene-open requests, status updates, and
|
|
runtime trace entries.
|
|
- Project services must not include `app/Features/**`. Keep project filesystem
|
|
state and command-target resolution in `app/Services/Project`; keep
|
|
`UIEditorTreeViewItem` and other widget presentation projections in
|
|
`Features/Project/ProjectPanel`.
|
|
|
|
## Viewport Rendering
|
|
|
|
- Scene and Game are `ViewportShell` presentations. The Scene panel is the
|
|
active editor viewport implementation; Game is registered as a viewport panel
|
|
but is not equivalent to the runtime game view yet.
|
|
- `SceneViewportFeature` owns `SceneViewportController` and
|
|
`SceneViewportRenderService`.
|
|
- `ViewportHostService` is the per-window manager for viewport requests,
|
|
render-target allocation, retirement, fallback clearing, and dispatch to the
|
|
attached `ViewportRenderHost`.
|
|
- `SceneViewportRenderService` renders scene content through the engine
|
|
renderer and owns object-id picking state. Keep editor picking/render support
|
|
behind `XCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT`.
|
|
- D3D12 window rendering is behind the abstract
|
|
`Rendering::Host::EditorWindowRenderRuntime`; native startup surface data is
|
|
passed through the neutral
|
|
`Rendering::Host::EditorWindowRenderRuntimeSurface` value contract, not a
|
|
concrete Win32 adapter type. Use the host interfaces when adding app-level
|
|
features.
|
|
|
|
## Modification Rules
|
|
|
|
- Add reusable widgets, docking/workspace behavior, shell interaction, or field
|
|
logic to `include/XCEditor/**` and `src/**`, with unit coverage in
|
|
`tests/UI/Editor/unit`.
|
|
- Add product editor behavior to `app/Features/**`. Workspace panels must
|
|
enter composition through `EditorWorkspacePanelRegistry.*` and the
|
|
`EditorWorkspacePanel` adapter interface; do not include concrete feature
|
|
panel headers from `EditorShellRuntime`, `EditorShellHostedPanelCoordinator`,
|
|
`EditorShellDrawComposer`, or `EditorShellSessionCoordinator`.
|
|
- Add new workspace panels by updating the panel ID constants, panel registry,
|
|
default workspace model, shell presentation, workspace panel runtime adapter,
|
|
and command/menu entries together.
|
|
- Add new utility windows through `app/Core/UtilityWindows` for the kind,
|
|
shared descriptor, and `EditorUtilityWindowPanel` contract; add the concrete
|
|
panel factory case in `app/Features/EditorUtilityWindowRegistry.*`; then wire
|
|
the context/request path. Do not model utility windows as workspace panels
|
|
unless they really dock inside the workspace.
|
|
- Add new commands in the command registry first, then menu/shortcut bindings,
|
|
host command bridge routing, and focused route tests.
|
|
- Keep workspace/window mutations transactional. Save the previous state,
|
|
validate after mutation, and roll back on invalid output, matching existing
|
|
controller patterns.
|
|
- Keep per-frame transient panel events separate from persistent app services.
|
|
Panels may emit frame events; `EditorContext` and runtime services own
|
|
persistent selection, command focus, project, and scene state.
|
|
- Release UI textures and GPU resources in `Shutdown` paths. D3D12 shutdown
|
|
should wait for GPU idle before releasing window resources.
|
|
- Do not write new manual-validation screenshots under the source tree.
|
|
Shared manual-validation hosts should write captures under the active build
|
|
directory.
|
|
|
|
## Current Architecture Notes
|
|
|
|
- `XCEditorCore` is the app/product-core target. It exists to make the app
|
|
boundary build-visible before finer-grained directories are cleaned up.
|
|
- `XCEditorCore` is not gated by the executable-host option. Keep
|
|
`XCENGINE_BUILD_XCUI_EDITOR_CORE` as the switch for product-core builds and
|
|
`XCENGINE_BUILD_XCUI_EDITOR_APP` as the switch for the concrete executable
|
|
host.
|
|
- `XCEditorCore` does not use `editor/app` as a private implementation include
|
|
root. Its public usage requirements expose only `app/Core`, `app/Commands`,
|
|
`app/State`, `app/Host/Interfaces`, `include`, and engine headers;
|
|
implementation files use explicit module roots instead of the app-wide
|
|
compatibility root.
|
|
- App-facing unit tests follow the same rule. `editor_app_core_tests` uses
|
|
explicit module include roots and must not regain the whole `editor/app`
|
|
root to make stale tests compile.
|
|
- App feature/viewport unit tests follow the same rule through
|
|
`editor_app_feature_tests`. Fix stale includes to current contracts instead
|
|
of adding compatibility headers for removed `Ports/**`, old
|
|
`Rendering/Viewport/**Internal.h`, or legacy `app/Platform/**` paths.
|
|
- `XCEditor` is the thin executable host that wires `XCEditorCore` to concrete
|
|
Win32 and D3D12 implementations. Do not move concrete platform/render host
|
|
code into `XCEditorCore` without first introducing neutral host contracts.
|
|
- `app/Core/Windowing/EditorFrameServices.h` and
|
|
`app/Core/Windowing/EditorWorkspaceShellRuntime.h` are the current
|
|
composition-to-windowing contract boundary. `EditorContext` and
|
|
`EditorShellRuntime` remain concrete composition types; `app/Windowing/**`
|
|
uses the contracts instead of those concrete headers. The shell-runtime
|
|
factory is the only workspace-shell construction hook visible to windowing;
|
|
workspace panel runtime construction stays in the application composition
|
|
root.
|
|
- Legacy fine-grained app-split CMake targets are retired architecture history.
|
|
Current production editor targets are `XCUIEditor`, `XCEditorCore`, and
|
|
`XCEditor`.
|
|
- Existing source-tree capture history is present under some manual-validation
|
|
scenarios, but new captures should go to the build output directory.
|
|
- Runtime trace files are the main app smoke diagnostic. Avoid replacing
|
|
trace-backed diagnostics with UI-only feedback that tests cannot observe.
|
|
|
|
## Validation
|
|
|
|
- Build shared editor UI after reusable-layer changes:
|
|
`cmake --build <build-dir> --config Debug --target XCUIEditor`.
|
|
- Build product editor core after app composition, service, feature, windowing,
|
|
or host-contract changes:
|
|
`cmake --build <build-dir> --config Debug --target XCEditorCore`.
|
|
- Validate the product-core boundary without the executable host by configuring
|
|
a separate build with
|
|
`-DXCENGINE_BUILD_XCUI_EDITOR_APP=OFF -DXCENGINE_BUILD_XCUI_EDITOR_CORE=ON -DXCENGINE_ENABLE_RENDERING_EDITOR_SUPPORT=ON`,
|
|
then building `XCEditorCore`, `editor_app_core_tests`, and
|
|
`editor_app_feature_tests`.
|
|
- Build app-core tests after product editor core or app-facing test changes:
|
|
`cmake --build <build-dir> --config Debug --target editor_app_core_tests`.
|
|
- Build app feature/viewport tests after feature panel, scene viewport,
|
|
viewport service, or app-facing input-routing changes:
|
|
`cmake --build <build-dir> --config Debug --target editor_app_feature_tests`.
|
|
- Build the app after startup, windowing, rendering, feature-panel, or resource
|
|
changes:
|
|
`cmake --build <build-dir> --config Debug --target XCEditor`.
|
|
- Build reusable editor unit tests:
|
|
`cmake --build <build-dir> --config Debug --target editor_ui_tests`.
|
|
- Build window synchronization tests:
|
|
`cmake --build <build-dir> --config Debug --target editor_windowing_phase1_tests`.
|
|
- Build aggregate editor unit targets:
|
|
`cmake --build <build-dir> --config Debug --target editor_ui_unit_tests`.
|
|
- Build app smoke support:
|
|
`cmake --build <build-dir> --config Debug --target editor_ui_smoke_targets`.
|
|
- Run app smoke through CTest when `XCEditor` is enabled:
|
|
`ctest -C Debug -R xceditor_smoke --output-on-failure`.
|
|
- Useful environment flags:
|
|
`XCUIEDITOR_VERBOSE_TRACE=1`, `XCUI_AUTO_CAPTURE_ON_STARTUP=1`,
|
|
`XCUIEDITOR_SMOKE_TEST=1`, `XCUIEDITOR_SMOKE_TEST_DURATION_SECONDS=<n>`,
|
|
and `XCUIEDITOR_SMOKE_TEST_FRAME_LIMIT=<n>`.
|
|
|
|
## Recommended Reading
|
|
|
|
- `editor/CMakeLists.txt`
|
|
- `editor/app/Bootstrap/Application.cpp`
|
|
- `editor/app/Composition/EditorContext.cpp`
|
|
- `editor/app/Services/Project/EditorProjectRuntime.cpp`
|
|
- `editor/app/Services/Project/ProjectBrowserModel.cpp`
|
|
- `editor/app/Composition/EditorShellRuntime.cpp`
|
|
- `editor/app/Composition/EditorShellAssetBuilder.cpp`
|
|
- `editor/app/Windowing/EditorWindowManager.cpp`
|
|
- `editor/app/Windowing/EditorWindowInstance.cpp`
|
|
- `editor/app/Windowing/Content/EditorWorkspaceWindowContentController.cpp`
|
|
- `editor/app/Windowing/Frame/EditorWindowFrameOrchestrator.cpp`
|
|
- `editor/app/Windowing/Coordinator/EditorWindowWorkspaceCoordinator.cpp`
|
|
- `editor/include/XCEditor/Windowing/System/EditorWindowSystem.h`
|
|
- `editor/src/Windowing/System/EditorWindowSystem.cpp`
|
|
- `editor/include/XCEditor/Workspace/UIEditorWorkspaceController.h`
|
|
- `editor/src/Workspace/UIEditorWorkspaceController.cpp`
|
|
- `editor/include/XCEditor/Workspace/UIEditorWindowWorkspaceController.h`
|
|
- `editor/src/Workspace/UIEditorWindowWorkspaceController.cpp`
|
|
- `editor/app/Host/Win32/Windowing/EditorWindowMessageDispatcher.cpp`
|
|
- `editor/app/Host/Interfaces/EditorWindowRenderRuntime.h`
|
|
- `editor/app/Host/Interfaces/EditorWindowHostInterfaces.h`
|
|
- `editor/app/Core/Windowing/EditorWindowTransferRequests.h`
|
|
- `editor/app/Rendering/Viewport/ViewportHostService.h`
|
|
- `tests/UI/Editor/unit/CMakeLists.txt`
|
|
- `tests/UI/Editor/smoke/CMakeLists.txt`
|
|
- `tests/UI/Editor/manual_validation/README.md`
|
|
|
|
## Recent Cuts
|
|
|
|
This section is intentionally important. Keep it as the running ledger of
|
|
architecture cuts that have already been made, so future agents do not
|
|
re-litigate or accidentally undo them. Add concrete entries here whenever a
|
|
change closes a boundary, removes an obsolete path, or establishes a new
|
|
ownership rule.
|
|
|
|
- Primary workspace state is bootstrapped into `EditorWindowSystem` before
|
|
native window creation.
|
|
- Workspace content now pulls a live authoritative workspace controller every
|
|
frame instead of trusting a stale local copy.
|
|
- Panel detach and cross-window tab drag are frame transfer requests handled by
|
|
`EditorWindowWorkspaceCoordinator`, then synchronized through
|
|
`EditorWindowSynchronizationPlanner`.
|
|
- Utility windows are app content controllers backed by
|
|
`EditorUtilityWindowPanel`; they are not workspace windows.
|
|
- Utility-window runtime contracts and descriptors now live under
|
|
`app/Core/UtilityWindows`. Concrete Color Picker/Add Component construction
|
|
is owned by `app/Features/EditorUtilityWindowRegistry.*` and injected from
|
|
`Application`, so `app/Windowing/**` no longer constructs concrete utility
|
|
feature panels.
|
|
- Shared window category, lifecycle, chrome-policy, native-host-policy,
|
|
screen geometry, chrome metrics, and frame-transfer request contracts now
|
|
live under `app/Core/Windowing`.
|
|
- Windowing now consumes composition through
|
|
`app/Core/Windowing/EditorFrameServices.h` and
|
|
`app/Core/Windowing/EditorWorkspaceShellRuntime.h`. `EditorContext`
|
|
implements the frame-services contract, `EditorShellRuntime` implements the
|
|
shell-runtime contract, and `Application` injects the concrete shell runtime
|
|
factory so `app/Windowing/**` no longer includes composition concrete types.
|
|
- `app/Windowing/**` no longer receives
|
|
`EditorWorkspacePanelRuntimeSetFactory` or constructs workspace panel runtime
|
|
sets. `Application` composes `CreateEditorWorkspacePanelRuntimeSet()` with
|
|
`CreateEditorWorkspaceShellRuntime(...)` before handing windowing a
|
|
zero-argument `EditorWorkspaceShellRuntimeFactory`.
|
|
- Viewport rendering is routed through `ViewportHostService` and the per-window
|
|
render runtime rather than directly from shell composition.
|
|
- The old fine-grained app-split target residue was removed from CMake and
|
|
tests. The current app split is coarse: `XCEditorCore` for product logic and
|
|
`XCEditor` for the executable host with output name `XCEngine`.
|
|
- Workspace panel runtimes are now behind `EditorWorkspacePanelRuntimeSet` and
|
|
`EditorWorkspacePanelRegistry.*`. `app/Composition/**` no longer directly
|
|
owns or dispatches concrete Console, Hierarchy, Inspector, Project, or Scene
|
|
panel classes.
|
|
- Shared app panel contracts started moving into `app/Core`: panel IDs now live
|
|
under `app/Core/Panels`, and the workspace-panel runtime interface lives
|
|
under `app/Core/WorkspacePanels`. `Application` is the composition root for
|
|
the concrete workspace panel factory.
|
|
- Panel-facing app services now live behind
|
|
`app/Core/Panels/EditorPanelServices.h`. Workspace-panel and utility-window
|
|
runtime contracts no longer expose `EditorContext`, and concrete feature
|
|
panels no longer include `Composition/EditorContext.h`.
|
|
- Project service ownership moved out of `app/Features`: `ProjectBrowserModel`
|
|
and `EditorProjectRuntime` now live under `app/Services/Project`, and the
|
|
Project panel owns the widget-tree projection instead of making the service
|
|
model depend on `UIEditorTreeViewItem`.
|
|
- The old `Win32EditorWindowRenderRuntimeSurface` adapter was removed. Win32
|
|
now captures native render startup data into the neutral
|
|
`Rendering::Host::EditorWindowRenderRuntimeSurface` value contract, so D3D12
|
|
no longer includes concrete Win32 editor surface headers.
|
|
- Neutral host-facing contracts moved under `app/Host/Interfaces`, including
|
|
editor window host interfaces, render runtime contracts, UI texture/viewport
|
|
host contracts, pointer-capture contracts, and system interaction service.
|
|
`XCEditorCore` no longer publishes the entire `editor/app` root through its
|
|
public CMake include surface.
|
|
- Concrete host code now lives under `app/Host/Win32` and `app/Host/D3D12`.
|
|
`XCEditorCore` publicly exposes only `app/Host/Interfaces`, while `XCEditor`
|
|
consumes the concrete host module roots privately.
|
|
- Native PNG resource loading and executable-directory discovery now enter
|
|
editor core through `Host/Interfaces/EditorHostResourceService.h`. Concrete
|
|
Win32 resource IDs and Win32 resource APIs live under
|
|
`app/Host/Win32/Resources`, so `XCEditorCore` no longer consumes
|
|
`app/Bootstrap` or Win32 resource helpers to initialize built-in icons,
|
|
title-bar branding, or screenshot output roots.
|
|
- The private `editor/app` CMake include root was removed from `XCEditorCore`
|
|
and `XCEditor`. App sources and editor app-facing unit files now include
|
|
through explicit module roots, so app-wide include-root drift is caught by
|
|
the build instead of being hidden by a compatibility path.
|
|
- The initial `editor_app_core_tests` target now links `XCEditorCore`
|
|
directly. It covers host command routing, project runtime, shell asset
|
|
validation, project browser model, hierarchy scene binding, and inspector
|
|
presentation without starting `XCEditor` or using the `editor/app` include
|
|
root.
|
|
- Stale app feature/viewport unit tests now build as
|
|
`editor_app_feature_tests` against `XCEditorCore` with explicit module
|
|
roots. Project panel tests use `SystemInteractionService`, viewport tests use
|
|
current `ViewportRenderTargets`/`ViewportRenderTargetUtils`, object-id picker
|
|
tests use `Viewport/ViewportObjectIdPicker.h`, and the old Win32 tab-drop
|
|
test now covers `XCEditor/Docking/UIEditorDockHostTransfer.h` through
|
|
`editor_windowing_phase1_tests`.
|
|
- `XCEditorCore` is now controlled by `XCENGINE_BUILD_XCUI_EDITOR_CORE`
|
|
instead of `XCENGINE_BUILD_XCUI_EDITOR_APP`. The executable host option only
|
|
creates `XCEditor`, and app-off builds can still compile `XCEditorCore`,
|
|
`editor_app_core_tests`, and `editor_app_feature_tests`.
|