24 KiB
24 KiB
XCUI Phase Status 2026-04-05
Scope
Current execution stays inside the XCUI module and new_editor.
Old editor replacement is explicitly out of scope for this phase.
Latest Checkpoint
- Phase 1 sandbox batch committed and pushed as
67a28bd(Add XCUI new editor sandbox phase 1). - Phase 2 common/runtime batch committed and pushed as
ade5be3(Add XCUI runtime screen layer and demo textarea). - Phase 3 has now produced a stable mixed batch across common/runtime/editor:
- schema document definition data is now retained on
UIDocumentModeland round-trips through the UI artifact path - schema self-definition validation is now stricter around enum/document-only metadata combinations
- engine runtime coverage was tightened again around
UISystemand concrete document-host rendering LayoutLabcontinues as the editor widget proving ground for tree/list/property-section style controls- the demo sandbox and editor bridge APIs were tightened again without touching the old editor replacement scope
new_editornow has an explicit two-step window compositor seam throughIWindowUICompositor/ImGuiWindowUICompositor, layered on top ofIEditorHostCompositor/ImGuiHostCompositor
- schema document definition data is now retained on
- Old
editorreplacement remains deferred; all active execution still stays inside XCUI shared code andnew_editor.
Three-Layer Status
1. Common Core
UI::DrawData, input event types, focus routing, style/theme resolution are in active use.UIDocumentCompileris buildable again after repairing the duplicated schema helper regression introduced by overlapping schema work.UIDocumentModel/UIDocumentResourcenow retain schema definition metadata explicitly, including memory accounting andUISchemaaccessors..xcschemaround-trip coverage is now present through compile, loader, artifact write, and artifact read paths.- Build-system hardening for MSVC/PDB output paths has started in root CMake,
engine/CMakeLists.txt,new_editor/CMakeLists.txt, andtests/NewEditor/CMakeLists.txt. - Shared engine-side XCUI runtime scaffolding is now present under
engine/include/XCEngine/UI/Runtimeandengine/src/UI/Runtime. - Shared engine-side
UIDocumentScreenHostnow compiles.xcui/.xcthemescreen documents into a runtime-facing document host path instead of leaving all document ownership innew_editor. - Shared text-editing primitives now live under
engine/include/XCEngine/UI/Textandengine/src/UI/Text, so UTF-8 caret movement, line splitting, and multiline navigation are no longer trapped insideXCUI Demo. - Shared text-input controller/state now also lives under
engine/include/XCEngine/UI/Textandengine/src/UI/Text, so character insertion, backspace/delete, submit, and multiline key handling no longer need to be reimplemented per host. - Shared editor collection primitive classification and metric helpers now also live under
engine/include/XCEngine/UI/Widgetsandengine/src/UI/Widgets, covering the currentScrollView/TreeView/ListView/PropertySection/FieldRowprototype taxonomy. - Shared single-selection state now also lives under
engine/include/XCEngine/UI/Widgetsandengine/src/UI/WidgetsasUISelectionModel, so collection-style widget selection no longer has to stay private toLayoutLab. - Shared expansion state now also lives under
engine/include/XCEngine/UI/Widgetsandengine/src/UI/WidgetsasUIExpansionModel, so collapsible tree/property-style widget state no longer has to stay private toLayoutLab. - Shared keyboard-navigation state now also lives under
engine/include/XCEngine/UI/Widgetsandengine/src/UI/WidgetsasUIKeyboardNavigationModel, so list/tree/property-style widgets can share current-index, anchor, and home/end/step navigation rules instead of re-rolling them per sandbox. - Shared property-edit session state now also lives under
engine/include/XCEngine/UI/Widgetsandengine/src/UI/WidgetsasUIPropertyEditModel, so editor-facing field rows can reuse begin/edit/commit/cancel transaction state instead of baking that directly into sandbox runtimes. - Core regression coverage now includes
UIContext, layout, style, runtime screen player/system, and real document-host tests throughcore_ui_tests.
Current gap:
- Minimal schema self-definition support is landed, including consistency checks for enum/document-only schema metadata, but schema-driven validation for
.xcui/.xcthemeinstances is still not implemented. - Shared widget/runtime instantiation is still thin and mostly editor-side.
- Common widget primitives are still incomplete: shared text-input presentation/composition on top of the new text controller, multi-selection/focus-traversal/virtualized collection state on top of the new editor-primitive helpers, and native image/source-rect level APIs.
2. Runtime/Game Layer
- The main concrete progress here is that the retained-mode demo runtime now supports a real
TextFieldinput path with UTF-8 text entry and backspace handling. - The demo runtime has moved past single-line input: multiline
TextAreabehavior is now covered in the sandbox testbed. - Engine-side runtime ownership is no longer zero:
UIScreenPlayer,UIDocumentScreenHost, andUISystemnow define a shared runtime contract for loading a screen document, ticking it with input, and collectingUI::UIDrawData. UISystemnow supports layered screen composition semantics: stacked screen players, top-interactive input routing, and modal layers that block lower screens.UIScreenStackController::ReplaceTopnow preserves the previous top screen if the replacement screen fails to load, so runtime menu flows do not silently drop their active layer on bad assets.SceneRuntimenow owns a dedicatedUISceneRuntimeContext, so game/runtime code has a first-class place to configure viewport/focus, queueUIInputEvents, driveUISystemeachUpdate, and inspect the latest UI frame result.- Runtime screen emission now also carries concrete button text in the shared document host path instead of silently dropping button labels.
UISystemFrameResultnow also preserves viewport rect, submitted input count, frame delta, and focus state, and bothUISystemandUISceneRuntimeContextnow exposeConsumeLastFrame()so runtime/game hosts can drain the last retained frame packet without copying editor-side concepts into the shared layer.UIScreenPlayernow also exposesConsumeLastFrame(), so player/system/context all share the same consume-vs-borrow frame ownership semantics in the runtime layer.
Current gap:
- Runtime UI is now wired into
SceneRuntime, but render submission is still limited to producingUIDrawData; there is no game-view/runtime presenter path that automatically draws those frames yet. - The runtime widget library is still shallow and missing the editor-grade controls that will later be shared downward.
3. Editor Layer
new_editorremains the isolated XCUI sandbox.- Native hosted preview is working as
RHI offscreen surface -> ImGui shell texture embed. - Hosted preview surface descriptors now stay on XCUI-owned value types (
UITextureHandle,UIPoint,UIRect) instead of exposing ImGui texture/UV types through the generic preview contract. XCUI Demoremains the long-lived effect and behavior testbed.XCUI Demonow covers both single-line and multiline text authoring behavior, including click caret placement, delete/backspace, tab indentation, and optional text-area line numbers.XCUI Demonow consumes the sharedUITextInputControllerpath for text editing instead of carrying a private key-handling state machine.LayoutLabnow includes aScrollViewprototype and a more editor-like three-column authored layout.LayoutLabnow also covers editor-facing widget prototypes:TreeView,TreeItem,ListView,ListItem,PropertySection, andFieldRow.LayoutLabnow consumes the sharedUIEditorCollectionPrimitiveshelper layer for collection-widget tag classification, clipping flags, and default metric resolution instead of keeping that taxonomy private to the sandbox runtime.LayoutLabnow also consumes the sharedUISelectionModelfor click-selection persistence across collection-style widgets, and the diagnostics panel now exposes both hovered and selected element ids.LayoutLabnow also consumes the sharedUIExpansionModelfor tree expansion and property-section collapse, with reserved property headers, disclosure glyphs, and persisted click-toggle behavior in the sandbox runtime.new_editornow also has an isolatedXCUIEditorCommandRoutermodel with shortcut matching, enable predicates, and direct command invocation semantics covered by dedicated tests, ready for shell-frame integration.XCUI Demonow exports pending per-frame command ids throughDrainPendingCommandIds(), so editor-side hosts have a clean seam for observing demo/runtime command traffic without parsing draw data.XCUI DemoandLayoutLabpanel canvases are now being pulled behind a dedicatedIXCUIPanelCanvasHostseam, so canvas surface presentation, hover/focus fallback state, and overlay draw hooks no longer have to stay hard-coded inside each ImGui panel implementation.- The panel-canvas seam now also exposes explicit backend/capability metadata and a minimal
NullXCUIPanelCanvasHost, so non-ImGui host paths have a concrete placeholder backend instead of relying on an implicit ImGui default. - Panel diagnostics were expanded to clearly separate preview/runtime/input state and native vs legacy paths.
- The editor bridge layer now has smoke coverage for swapchain after-UI rendering hooks and SRV-backed ImGui texture descriptor registration.
Applicationno longer owns the ImGui backend directly; window presentation now routes throughIWindowUICompositorwith anImGuiWindowUICompositorimplementation, which currently delegates toIEditorHostCompositor/ImGuiHostCompositor.- Hosted preview offscreen surfaces now keep compositor-returned
UITextureRegistration/UITextureHandledata insideApplicationinstead of storingImTextureIDdirectly. - The generic hosted-preview presenter contract no longer owns
ImGuiTransitionBackend; the ImGui presenter now sits in a separateImGuiXCUIHostedPreviewPresenterheader while the native queue/surface registry remains XCUI-generic. - The generic hosted-preview frame contract no longer carries an ImGui draw-list pointer; the legacy ImGui presenter resolves its inline draw target from the active ImGui window context instead of pushing that type through the XCUI contract.
- The legacy ImGui hosted-preview presenter now also accepts an explicit draw-target binding object, so presenter-side
ImGui::GetWindowDrawList()lookup is no longer hard-coded inside the generic presenter path and can stay isolated behind the ImGui adapter layer. Applicationshell menu toggles and global shortcuts now route throughXCUIEditorCommandRouterinstead of directly mutating shell booleans from menu callbacks, giving the editor layer a real command-routing seam.LayoutLabruntime now consumes the sharedUIKeyboardNavigationModelfor abstract list/tree/property navigation actions (previous/next/home/end/collapse/expand), so keyboard collection traversal rules are no longer trapped in sandbox-local state.LayoutLabpanel input now also maps concrete arrow/home/end keys into those shared navigation actions, so keyboard traversal is reachable from the sandbox UI instead of staying runtime-only.XCUIDemoRuntimenow bridges pointer activation, text-edit commands, and shortcut-triggered commands through a unified command path, andDrainPendingCommandIds()now preserves mixed pointer/text/shortcut ordering.new_editornow also has a pureXCUIShellChromeStatemodel covering panel visibility, hosted-preview mode, and shell-level view toggles without depending on ImGui,Application, or the old editor.XCNewEditorbuilds successfully tobuild/new_editor/bin/Debug/XCNewEditor.exe.
Current gap:
- The shell is still ImGui-hosted.
- Legacy hosted preview still depends on an ImGui-specific inline draw target binding for presentation.
- The new panel-canvas seam still only has an ImGui adapter today; a native panel/shell host still needs to replace it before ImGui can stop being the default editor host path.
- Editor-specialized widgets are still incomplete at the shared-module level: the authored prototypes exist, but virtualization, multi-selection/focus traversal, toolbar/menu chrome, and icon-atlas widgets are not yet extracted into reusable XCUI modules, and broader editor-host keybinding plus full shell-state adoption are still only partially integrated.
Validated This Phase
new_editor_xcui_demo_runtime_tests:12/12new_editor_xcui_layout_lab_runtime_tests:12/12new_editor_xcui_rhi_command_compiler_tests:6/6new_editor_xcui_rhi_render_backend_tests:5/5new_editor_xcui_hosted_preview_presenter_tests:17/17new_editor_imgui_window_ui_compositor_tests:7/7new_editor_xcui_editor_command_router_tests:5/5new_editor_application_shell_command_bindings_tests:6/6new_editor_xcui_shell_chrome_state_tests:8/8new_editor_xcui_panel_canvas_host_tests:2/2new_editor_imgui_xcui_panel_canvas_host_tests:1/1new_editor_xcui_layout_lab_panel_tests:2/2XCNewEditorDebug target builds successfullycore_ui_tests:52 total(50passed,2skipped becauseKeyCode::Deletecurrently aliasesBackspace)scene_tests:68/68core_ui_style_tests:5/5ui_resource_tests:11/11editor_teststargeted bridge smoke:3/3
Landed This Phase
- Demo runtime
TextFieldwith UTF-8 text insertion, caret state, and backspace. - Demo runtime multiline
TextAreapath in the sandbox and test coverage for caret movement / multiline input. - Common-core
UITextEditingextraction now owns UTF-8 offset stepping, codepoint counting, line splitting, and vertical caret motion with dedicatedcore_ui_testscoverage. - Common-core
UITextInputControllerextraction now owns per-field text state, character insertion, enter-submit, and multiline keyboard editing behavior with dedicatedcore_ui_testscoverage. - Common-core
UIEditorCollectionPrimitivesextraction now owns the editor collection tag taxonomy and default metric resolution used by currentLayoutLabwidget prototypes, with dedicatedcore_ui_testscoverage. - Common-core
UISelectionModelextraction now owns reusable single-selection state for collection-style widgets, with dedicatedcore_ui_testscoverage. - Common-core
UIExpansionModelextraction now owns reusable expansion/collapse state for tree/property-style widgets, with dedicatedcore_ui_testscoverage. - Common-core
UIKeyboardNavigationModelextraction now owns reusable current-index/anchor navigation state for collection-style widgets, with dedicatedcore_ui_testscoverage. - Common-core
UIPropertyEditModelextraction now owns reusable property-field edit session state, including staged values and commit/cancel behavior, with dedicatedcore_ui_testscoverage. - Runtime frame ownership was tightened again:
UIScreenPlayer::ConsumeLastFrame()now exposes consume-style packet ownership at the player layerUISystemFrameResultnow carries viewport rect, submitted input event count, frame delta, and focus stateUISystem::ConsumeLastFrame()moves the retained packet out of the runtime layerUISceneRuntimeContext::ConsumeLastFrame()forwards the same shared runtime seam upward
- Demo runtime text editing was extended with:
- click-to-place caret
DeletesupportTab/Shift+Tabindentation for text areas- optional text-area line-number gutter rendering
- Demo authored resources updated to exercise the input field.
- LayoutLab
ScrollViewprototype with clipping and hover rejection outside clipped content. - LayoutLab editor-widget prototypes for tree/list/property-style sections with dedicated runtime coverage.
- LayoutLab click-selection now persists through the shared
UISelectionModel, including selected-state diagnostics and reusable visual selection feedback on cards, collection rows, and field rows. - LayoutLab tree expansion and property-section collapse now persist through the shared
UIExpansionModel, including reserved property headers, disclosure glyphs, and runtime coverage for collapsed/expanded visibility. XCUIDemoRuntimenow exposesDrainPendingCommandIds()so hosts can observe emitted runtime commands in order across pointer/text interactions without scraping UI text or draw-command payloads.XCUIDemoRuntimecommand recording was tightened so pointer activation, text editing, and shortcut-triggered commands now share one bridge path and preserve mixed ordering inDrainPendingCommandIds().- Schema document support extended with:
- retained
UISchemaDefinitiondata onUIDocumentModel - artifact schema version bump for UI documents
- loader/resource accessors and memory accounting
- schema compile/load/artifact regression coverage
- schema consistency rules for:
allowedValuesonly onenumdocumentKind/restrictDocumentKindonly ondocument- explicit
documentKindrequired whenrestrictDocumentKind=true
- retained
- Engine runtime layer added:
UIScreenPlayerUIDocumentScreenHostUISceneRuntimeContextUIScreenStackControllerUISystem- layered screen composition and modal blocking semantics
- Runtime/game integration scaffolding now includes reusable
HUD/menu/modalstack helpers on top ofUISystem. UIScreenStackControllerreplacement now rolls back safely on failure instead of popping the active top layer first.SceneRuntimenow exposes XCUI runtime ownership directly:GetUISystem()GetUIScreenStackController()GetLastUIFrame()SetUIViewportRect(...)SetUIFocused(...)QueueUIInputEvent(...)ClearQueuedUIInputEvents()- automatic
UISystemticking duringSceneRuntime::Update(...)
- Runtime document-host draw emission now preserves button labels for shared screen rendering.
- RHI image path improvements:
- clipped image UV adjustment
- mirrored image UV preservation
- external texture binding reuse
- per-batch scissor application
- Editor bridge helpers now expose:
- an
afterUiRenderswapchain callback hook inD3D12WindowRenderer - SRV-view based texture descriptor registration in
ImGuiBackendBridge - smoke tests for window renderer, ImGui backend bridge, and console sink registration
- an
new_editorhost presentation now has a first-class compositor seam:IWindowUICompositorImGuiWindowUICompositorIEditorHostCompositorImGuiHostCompositorApplicationframe/present flow routed through the compositor instead of directm_imguiBackendownership
- The window-level XCUI compositor seam now also has a dedicated regression target around
ImGuiWindowUICompositor, covering initialization, render-frame ordering, Win32 message forwarding, texture registration forwarding, and shutdown safety. - The window compositor and hosted-preview seams gained more edge-case coverage around no-UI render passes, compositor re-initialization/rebinding, partial logical-size fallback, and descriptor reuse for repeated queued-frame keys.
new_editornow has a dedicatedXCUIEditorCommandRoutertest target covering command registration, replacement, enable predicates, accelerator matching, and policy gates around focus/keyboard capture/text input.Applicationnow integratesXCUIEditorCommandRouterinto the shell itself:Viewmenu items invoke routed commands instead of directly mutating shell state- shell-level shortcuts now flow from
XCUIWin32InputSourcethroughXCUIInputBridgeinto command matching - hosted-preview mode toggles still trigger presenter reconfiguration through the routed command bindings
new_editorpanel canvas ownership is now being split behindIXCUIPanelCanvasHost, with anImGuiXCUIPanelCanvasHostadapter carrying the legacy path so panel code stops directly owningImGui::Image/ImGui::InvisibleButton/ draw-list preview plumbing.new_editornow also has a pureXCUIShellChromeStatemodel with dedicated tests, covering shell panel visibility, hosted-preview mode, and shell view toggles without depending on ImGui orApplication.XCUIShellChromeStatenow also exposes effective hosted-preview state helpers and shell view-toggle command-id helpers, so shell routing code no longer has to manually combine enablement and requested preview mode.- The panel-canvas seam now has dedicated null/imgui backend coverage, including explicit backend/capability reporting and a non-ImGui placeholder host path for future native shell adoption.
SceneRuntimelayered XCUI routing now has dedicated regression coverage for:- top-interactive layer input ownership
- blocking/modal layer suppression of lower layers
- hidden top-layer pass-through back to visible underlying layers
- Shared
UITextInputControllercoverage now includes more caret-boundary / modifier branches; the remainingDeletedistinction stays blocked onKeyCode::DeleteandKeyCode::Backspacestill sharing the same enum value. - Window compositor texture registration now also flows back into
Applicationas XCUI-ownedUITextureRegistration/UITextureHandledata instead of exposing rawImTextureIDthere. - Hosted preview contracts were tightened again:
- generic preview surface metadata stays on XCUI-owned value types
ImGuiTransitionBackendmoved behindImGuiXCUIHostedPreviewPresenter- generic preview frame submission no longer carries an ImGui draw-list pointer
- the ImGui presenter now resolves inline draw targets through an explicit ImGui-only binding seam
- panel/runtime callers still preserve the same legacy and native-preview behavior
LayoutLabnow resolves editor collection widget taxonomy and metrics through sharedUIEditorCollectionPrimitiveshelpers instead of duplicating the same tag and metric rules inside the sandbox runtime.LayoutLabruntime now consumes shared keyboard-navigation semantics for list/tree/property traversal, while the remaining panel-level key mapping is tracked as an editor-host integration gap rather than a runtime gap.LayoutLabpanel now maps concrete arrow/home/end keys into the shared navigation model, with dedicated panel-level coverage proving that the sandbox UI can actually drive the runtime navigation seam end-to-end.new_editorpanel/shell diagnostics improvements for hosted preview state.- XCUI asset document loading changed to prefer direct source compilation before
ResourceManagerfallback for the sandbox path, fixing the LayoutLab crash. UIDocumentCompiler.cpprepaired enough to restore full local builds after the duplicated schema-helper regression.- MSVC debug build hardening was tightened again so large parallel
enginerebuilds stop tripping over compile-PDB contention.
Phase Risks Still Open
- Schema instance validation is still open beyond
.xcschemaself-definition and artifact round-trip coverage. ScrollViewis still authored/static; no wheel-driven scrolling or virtualization yet.Imagewidgets still do not have source-rect/atlas-subregion level API in the high-level draw command model.- Editor shell still depends on ImGui as host chrome.
- Legacy hosted preview still depends on an ImGui-only inline presenter path when not using the queued native surface path.
- Editor widget coverage is still prototype-driven inside
LayoutLab; it has not yet been promoted into a full reusable shared widget/runtime layer with command routing, virtualization, and property-edit transactions.
Next Phase
- Expand runtime/game-layer ownership from the current
SceneRuntimeUI context into scene-declared HUD/menu bootstrapping, draw submission, and higher-level runtime UI policies. - Promote the current editor-facing widget prototypes out of authored
LayoutLabcontent and into reusable XCUI widget/runtime modules, then continue with toolbar/menu chrome, shell-state adoption, and panel-level keyboard/navigation input plumbing. - Add a native XCUI host compositor on the existing window-level compositor seam so
new_editorcan present without going through ImGui-owned draw data. - Replace the remaining ImGui-only fallback seams in hosted preview and panel canvas hosting with native host implementations so ImGui can become compatibility-only instead of the default shell path.
- Continue phased validation, commit, push, and plan refresh after each stable batch.