Contain XCUI ImGui adapters behind explicit host seams
This commit is contained in:
@@ -64,7 +64,7 @@ Current gap:
|
|||||||
### 3. Editor Layer
|
### 3. Editor Layer
|
||||||
|
|
||||||
- `new_editor` remains the isolated XCUI sandbox.
|
- `new_editor` remains the isolated XCUI sandbox.
|
||||||
- Native hosted preview is working as `RHI offscreen surface -> ImGui shell texture embed`.
|
- Native hosted preview is working as `RHI offscreen surface -> hosted surface image present` through the current shell adapter path.
|
||||||
- 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.
|
- 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 Demo` remains the long-lived effect and behavior testbed.
|
- `XCUI Demo` remains the long-lived effect and behavior testbed.
|
||||||
- `XCUI Demo` now covers both single-line and multiline text authoring behavior, including click caret placement, delete/backspace, tab indentation, and optional text-area line numbers.
|
- `XCUI Demo` now covers both single-line and multiline text authoring behavior, including click caret placement, delete/backspace, tab indentation, and optional text-area line numbers.
|
||||||
@@ -78,6 +78,8 @@ Current gap:
|
|||||||
- `XCUI Demo` now exports pending per-frame command ids through `DrainPendingCommandIds()`, so editor-side hosts have a clean seam for observing demo/runtime command traffic without parsing draw data.
|
- `XCUI Demo` now exports pending per-frame command ids through `DrainPendingCommandIds()`, so editor-side hosts have a clean seam for observing demo/runtime command traffic without parsing draw data.
|
||||||
- `XCUI Demo` and `LayoutLab` panel canvases are now being pulled behind a dedicated `IXCUIPanelCanvasHost` seam, so canvas surface presentation, hover/focus fallback state, and overlay draw hooks no longer have to stay hard-coded inside each ImGui panel implementation.
|
- `XCUI Demo` and `LayoutLab` panel canvases are now being pulled behind a dedicated `IXCUIPanelCanvasHost` seam, 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.
|
- 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.
|
||||||
|
- `XCUI Demo` and `LayoutLab` panel input now also flows through an explicit `IXCUIInputSnapshotSource` seam, so panel/runtime code no longer reads `ImGuiIO` / `ImGui::IsKeyPressed` / `ImGui::IsMouseClicked` directly when the shell wants to use an ImGui adapter.
|
||||||
|
- `new_editor` now also has an explicit `ImGuiXCUIInputSnapshotSource` adapter, keeping ImGui-specific input capture in the host adapter layer instead of inside panel/runtime update code.
|
||||||
- Panel diagnostics were expanded to clearly separate preview/runtime/input state and native vs legacy paths.
|
- 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.
|
- The editor bridge layer now has smoke coverage for swapchain after-UI rendering hooks and SRV-backed ImGui texture descriptor registration.
|
||||||
- `Application` no longer owns the ImGui backend directly; window presentation now routes through `IWindowUICompositor` with an `ImGuiWindowUICompositor` implementation, which currently delegates to `IEditorHostCompositor` / `ImGuiHostCompositor`.
|
- `Application` no longer owns the ImGui backend directly; window presentation now routes through `IWindowUICompositor` with an `ImGuiWindowUICompositor` implementation, which currently delegates to `IEditorHostCompositor` / `ImGuiHostCompositor`.
|
||||||
@@ -90,29 +92,33 @@ Current gap:
|
|||||||
- `LayoutLab` panel 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.
|
- `LayoutLab` panel 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.
|
||||||
- `XCUIDemoRuntime` now bridges pointer activation, text-edit commands, and shortcut-triggered commands through a unified command path, and `DrainPendingCommandIds()` now preserves mixed pointer/text/shortcut ordering.
|
- `XCUIDemoRuntime` now bridges pointer activation, text-edit commands, and shortcut-triggered commands through a unified command path, and `DrainPendingCommandIds()` now preserves mixed pointer/text/shortcut ordering.
|
||||||
- `new_editor` now also has a pure `XCUIShellChromeState` model covering panel visibility, hosted-preview mode, and shell-level view toggles without depending on ImGui, `Application`, or the old editor.
|
- `new_editor` now also has a pure `XCUIShellChromeState` model covering panel visibility, hosted-preview mode, and shell-level view toggles without depending on ImGui, `Application`, or the old editor.
|
||||||
|
- `XCUIShellChromeState` hosted-preview mode naming is now backend-neutral (`HostedPresenter` / `NativeOffscreen`) instead of encoding `ImGui` into the XCUI shell model.
|
||||||
- `XCNewEditor` builds successfully to `build/new_editor/bin/Debug/XCNewEditor.exe`.
|
- `XCNewEditor` builds successfully to `build/new_editor/bin/Debug/XCNewEditor.exe`.
|
||||||
|
|
||||||
Current gap:
|
Current gap:
|
||||||
|
|
||||||
- The shell is still ImGui-hosted.
|
- The shell is still ImGui-hosted.
|
||||||
- Legacy hosted preview still depends on an ImGui-specific inline draw target binding for presentation.
|
- Hosted-preview compatibility presentation still depends on an ImGui-specific inline draw target binding when the native queued surface path is disabled.
|
||||||
- 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.
|
- The panel-canvas seam still only has an ImGui adapter today; a native panel/shell host still needs to replace it before the editor shell can stop depending on ImGui host chrome.
|
||||||
- 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.
|
- 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
|
## Validated This Phase
|
||||||
|
|
||||||
|
- `new_editor_xcui_demo_panel_tests`: `3/3`
|
||||||
- `new_editor_xcui_demo_runtime_tests`: `12/12`
|
- `new_editor_xcui_demo_runtime_tests`: `12/12`
|
||||||
|
- `new_editor_xcui_input_bridge_tests`: `4/4`
|
||||||
|
- `new_editor_imgui_xcui_input_adapter_tests`: `2/2`
|
||||||
- `new_editor_xcui_layout_lab_runtime_tests`: `12/12`
|
- `new_editor_xcui_layout_lab_runtime_tests`: `12/12`
|
||||||
- `new_editor_xcui_rhi_command_compiler_tests`: `6/6`
|
- `new_editor_xcui_rhi_command_compiler_tests`: `6/6`
|
||||||
- `new_editor_xcui_rhi_render_backend_tests`: `5/5`
|
- `new_editor_xcui_rhi_render_backend_tests`: `5/5`
|
||||||
- `new_editor_xcui_hosted_preview_presenter_tests`: `17/17`
|
- `new_editor_xcui_hosted_preview_presenter_tests`: `20/20`
|
||||||
- `new_editor_imgui_window_ui_compositor_tests`: `7/7`
|
- `new_editor_imgui_window_ui_compositor_tests`: `7/7`
|
||||||
- `new_editor_xcui_editor_command_router_tests`: `5/5`
|
- `new_editor_xcui_editor_command_router_tests`: `5/5`
|
||||||
- `new_editor_application_shell_command_bindings_tests`: `6/6`
|
- `new_editor_application_shell_command_bindings_tests`: `6/6`
|
||||||
- `new_editor_xcui_shell_chrome_state_tests`: `8/8`
|
- `new_editor_xcui_shell_chrome_state_tests`: `11/11`
|
||||||
- `new_editor_xcui_panel_canvas_host_tests`: `2/2`
|
- `new_editor_xcui_panel_canvas_host_tests`: `4/4`
|
||||||
- `new_editor_imgui_xcui_panel_canvas_host_tests`: `1/1`
|
- `new_editor_imgui_xcui_panel_canvas_host_tests`: `1/1`
|
||||||
- `new_editor_xcui_layout_lab_panel_tests`: `2/2`
|
- `new_editor_xcui_layout_lab_panel_tests`: `3/3`
|
||||||
- `XCNewEditor` Debug target builds successfully
|
- `XCNewEditor` Debug target builds successfully
|
||||||
- `core_ui_tests`: `52 total` (`50` passed, `2` skipped because `KeyCode::Delete` currently aliases `Backspace`)
|
- `core_ui_tests`: `52 total` (`50` passed, `2` skipped because `KeyCode::Delete` currently aliases `Backspace`)
|
||||||
- `scene_tests`: `68/68`
|
- `scene_tests`: `68/68`
|
||||||
@@ -199,8 +205,12 @@ Current gap:
|
|||||||
- shell-level shortcuts now flow from `XCUIWin32InputSource` through `XCUIInputBridge` into command matching
|
- shell-level shortcuts now flow from `XCUIWin32InputSource` through `XCUIInputBridge` into command matching
|
||||||
- hosted-preview mode toggles still trigger presenter reconfiguration through the routed command bindings
|
- hosted-preview mode toggles still trigger presenter reconfiguration through the routed command bindings
|
||||||
- `new_editor` panel canvas ownership is now being split behind `IXCUIPanelCanvasHost`, with an `ImGuiXCUIPanelCanvasHost` adapter carrying the legacy path so panel code stops directly owning `ImGui::Image` / `ImGui::InvisibleButton` / draw-list preview plumbing.
|
- `new_editor` panel canvas ownership is now being split behind `IXCUIPanelCanvasHost`, with an `ImGuiXCUIPanelCanvasHost` adapter carrying the legacy path so panel code stops directly owning `ImGui::Image` / `ImGui::InvisibleButton` / draw-list preview plumbing.
|
||||||
|
- `XCUIDemoPanel` and `XCUILayoutLabPanel` no longer create an ImGui hosted-preview presenter or ImGui panel canvas host implicitly; default construction now stays on null/explicitly injected backends until the outer shell binds a concrete host adapter.
|
||||||
|
- `Application` now binds `ImGuiXCUIPanelCanvasHost` explicitly at the shell composition root, so the current ImGui panel host path is visible as a host-layer decision instead of a panel-layer fallback.
|
||||||
|
- `XCUIDemoPanel` and `XCUILayoutLabPanel` no longer read ImGui input directly; both now consume an injected `IXCUIInputSnapshotSource`, and the new `ImGuiXCUIInputSnapshotSource` keeps the current ImGui-backed input path isolated behind an explicit adapter.
|
||||||
- `new_editor` now also has a pure `XCUIShellChromeState` model with dedicated tests, covering shell panel visibility, hosted-preview mode, and shell view toggles without depending on ImGui or `Application`.
|
- `new_editor` now also has a pure `XCUIShellChromeState` model with dedicated tests, covering shell panel visibility, hosted-preview mode, and shell view toggles without depending on ImGui or `Application`.
|
||||||
- `XCUIShellChromeState` now 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.
|
- `XCUIShellChromeState` now 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.
|
||||||
|
- `XCUIShellChromeState` hosted-preview modes were renamed away from `LegacyImGui`, so XCUI shell state no longer treats ImGui as the generic fallback concept.
|
||||||
- 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.
|
- 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.
|
||||||
- `SceneRuntime` layered XCUI routing now has dedicated regression coverage for:
|
- `SceneRuntime` layered XCUI routing now has dedicated regression coverage for:
|
||||||
- top-interactive layer input ownership
|
- top-interactive layer input ownership
|
||||||
@@ -228,13 +238,13 @@ Current gap:
|
|||||||
- `ScrollView` is still authored/static; no wheel-driven scrolling or virtualization yet.
|
- `ScrollView` is still authored/static; no wheel-driven scrolling or virtualization yet.
|
||||||
- `Image` widgets still do not have source-rect/atlas-subregion level API in the high-level draw command model.
|
- `Image` widgets 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.
|
- 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.
|
- Hosted-preview compatibility presentation 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.
|
- 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
|
## Next Phase
|
||||||
|
|
||||||
1. Expand runtime/game-layer ownership from the current `SceneRuntime` UI context into scene-declared HUD/menu bootstrapping, draw submission, and higher-level runtime UI policies.
|
1. Expand runtime/game-layer ownership from the current `SceneRuntime` UI context into scene-declared HUD/menu bootstrapping, draw submission, and higher-level runtime UI policies.
|
||||||
2. Promote the current editor-facing widget prototypes out of authored `LayoutLab` content and into reusable XCUI widget/runtime modules, then continue with toolbar/menu chrome, shell-state adoption, and panel-level keyboard/navigation input plumbing.
|
2. Promote the current editor-facing widget prototypes out of authored `LayoutLab` content and into reusable XCUI widget/runtime modules, then continue with toolbar/menu chrome, shell-state adoption, virtualization, and broader focus/multi-selection behavior.
|
||||||
3. Add a native XCUI host compositor on the existing window-level compositor seam so `new_editor` can present without going through ImGui-owned draw data.
|
3. Add a native XCUI host compositor on the existing window-level compositor seam so `new_editor` can present without going through ImGui-owned draw data.
|
||||||
4. 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.
|
4. 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.
|
||||||
5. Continue phased validation, commit, push, and plan refresh after each stable batch.
|
5. Continue phased validation, commit, push, and plan refresh after each stable batch.
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ set(NEW_EDITOR_SOURCES
|
|||||||
src/XCUIBackend/ImGuiHostCompositor.cpp
|
src/XCUIBackend/ImGuiHostCompositor.cpp
|
||||||
src/XCUIBackend/XCUIEditorFontSetup.cpp
|
src/XCUIBackend/XCUIEditorFontSetup.cpp
|
||||||
src/XCUIBackend/XCUIAssetDocumentSource.cpp
|
src/XCUIBackend/XCUIAssetDocumentSource.cpp
|
||||||
|
src/XCUIBackend/XCUIEditorCommandRouter.cpp
|
||||||
src/XCUIBackend/XCUIInputBridge.cpp
|
src/XCUIBackend/XCUIInputBridge.cpp
|
||||||
|
src/XCUIBackend/XCUIShellChromeState.cpp
|
||||||
src/XCUIBackend/XCUIRHICommandCompiler.cpp
|
src/XCUIBackend/XCUIRHICommandCompiler.cpp
|
||||||
src/XCUIBackend/XCUIRHIRenderBackend.cpp
|
src/XCUIBackend/XCUIRHIRenderBackend.cpp
|
||||||
src/XCUIBackend/XCUIStandaloneTextAtlasProvider.cpp
|
src/XCUIBackend/XCUIStandaloneTextAtlasProvider.cpp
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
||||||
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
||||||
#include "XCUIBackend/ImGuiWindowUICompositor.h"
|
#include "XCUIBackend/ImGuiWindowUICompositor.h"
|
||||||
|
|
||||||
@@ -41,12 +42,12 @@ const char* GetHostedPreviewPathLabel(bool nativeRequested, bool nativePresenter
|
|||||||
return "native queued offscreen surface";
|
return "native queued offscreen surface";
|
||||||
}
|
}
|
||||||
if (nativeRequested) {
|
if (nativeRequested) {
|
||||||
return "native requested, legacy presenter bound";
|
return "native requested, hosted presenter bound";
|
||||||
}
|
}
|
||||||
if (nativePresenterBound) {
|
if (nativePresenterBound) {
|
||||||
return "legacy requested, native presenter still bound";
|
return "hosted presenter requested, native presenter still bound";
|
||||||
}
|
}
|
||||||
return "legacy imgui transition";
|
return "hosted presenter";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetHostedPreviewStateLabel(
|
const char* GetHostedPreviewStateLabel(
|
||||||
@@ -90,70 +91,20 @@ Application::CreateHostedPreviewPresenter(bool nativePreview) {
|
|||||||
return ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
return ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::ShellPanelChromeState* Application::TryGetShellPanelState(ShellPanelId panelId) {
|
|
||||||
const std::size_t index = GetShellPanelIndex(panelId);
|
|
||||||
if (index >= m_shellPanels.size()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m_shellPanels[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Application::ShellPanelChromeState* Application::TryGetShellPanelState(ShellPanelId panelId) const {
|
const Application::ShellPanelChromeState* Application::TryGetShellPanelState(ShellPanelId panelId) const {
|
||||||
const std::size_t index = GetShellPanelIndex(panelId);
|
return m_shellChromeState.TryGetPanelState(panelId);
|
||||||
if (index >= m_shellPanels.size()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &m_shellPanels[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::IsShellViewToggleEnabled(ShellViewToggleId toggleId) const {
|
bool Application::IsShellViewToggleEnabled(ShellViewToggleId toggleId) const {
|
||||||
switch (toggleId) {
|
return m_shellChromeState.GetViewToggle(toggleId);
|
||||||
case ShellViewToggleId::ImGuiDemoWindow:
|
|
||||||
return m_shellViewToggles.imguiDemoWindowVisible;
|
|
||||||
case ShellViewToggleId::NativeBackdrop:
|
|
||||||
return m_shellViewToggles.nativeBackdropVisible;
|
|
||||||
case ShellViewToggleId::PulseAccent:
|
|
||||||
return m_shellViewToggles.pulseAccentEnabled;
|
|
||||||
case ShellViewToggleId::NativeXCUIOverlay:
|
|
||||||
return m_shellViewToggles.nativeXCUIOverlayVisible;
|
|
||||||
case ShellViewToggleId::HostedPreviewHud:
|
|
||||||
return m_shellViewToggles.hostedPreviewHudVisible;
|
|
||||||
case ShellViewToggleId::Count:
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::SetShellViewToggleEnabled(ShellViewToggleId toggleId, bool enabled) {
|
void Application::SetShellViewToggleEnabled(ShellViewToggleId toggleId, bool enabled) {
|
||||||
switch (toggleId) {
|
m_shellChromeState.SetViewToggle(toggleId, enabled);
|
||||||
case ShellViewToggleId::ImGuiDemoWindow:
|
|
||||||
m_shellViewToggles.imguiDemoWindowVisible = enabled;
|
|
||||||
return;
|
|
||||||
case ShellViewToggleId::NativeBackdrop:
|
|
||||||
m_shellViewToggles.nativeBackdropVisible = enabled;
|
|
||||||
return;
|
|
||||||
case ShellViewToggleId::PulseAccent:
|
|
||||||
m_shellViewToggles.pulseAccentEnabled = enabled;
|
|
||||||
return;
|
|
||||||
case ShellViewToggleId::NativeXCUIOverlay:
|
|
||||||
m_shellViewToggles.nativeXCUIOverlayVisible = enabled;
|
|
||||||
return;
|
|
||||||
case ShellViewToggleId::HostedPreviewHud:
|
|
||||||
m_shellViewToggles.hostedPreviewHudVisible = enabled;
|
|
||||||
return;
|
|
||||||
case ShellViewToggleId::Count:
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::IsNativeHostedPreviewEnabled(ShellPanelId panelId) const {
|
bool Application::IsNativeHostedPreviewEnabled(ShellPanelId panelId) const {
|
||||||
const ShellPanelChromeState* panelState = TryGetShellPanelState(panelId);
|
return m_shellChromeState.IsNativeHostedPreviewActive(panelId);
|
||||||
return panelState != nullptr &&
|
|
||||||
panelState->hostedPreviewEnabled &&
|
|
||||||
panelState->previewMode == ShellHostedPreviewMode::NativeOffscreen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::ConfigureHostedPreviewPresenters() {
|
void Application::ConfigureHostedPreviewPresenters() {
|
||||||
@@ -178,25 +129,19 @@ void Application::ConfigureShellCommandRouter() {
|
|||||||
|
|
||||||
ShellCommandBindings bindings = {};
|
ShellCommandBindings bindings = {};
|
||||||
bindings.getXCUIDemoPanelVisible = [this]() {
|
bindings.getXCUIDemoPanelVisible = [this]() {
|
||||||
const ShellPanelChromeState* panelState = TryGetShellPanelState(ShellPanelId::XCUIDemo);
|
return m_shellChromeState.IsPanelVisible(ShellPanelId::XCUIDemo);
|
||||||
return panelState != nullptr && panelState->visible;
|
|
||||||
};
|
};
|
||||||
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
||||||
if (ShellPanelChromeState* panelState = TryGetShellPanelState(ShellPanelId::XCUIDemo)) {
|
m_shellChromeState.SetPanelVisible(ShellPanelId::XCUIDemo, visible);
|
||||||
panelState->visible = visible;
|
|
||||||
}
|
|
||||||
if (m_demoPanel != nullptr) {
|
if (m_demoPanel != nullptr) {
|
||||||
m_demoPanel->SetVisible(visible);
|
m_demoPanel->SetVisible(visible);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
||||||
const ShellPanelChromeState* panelState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab);
|
return m_shellChromeState.IsPanelVisible(ShellPanelId::XCUILayoutLab);
|
||||||
return panelState != nullptr && panelState->visible;
|
|
||||||
};
|
};
|
||||||
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
||||||
if (ShellPanelChromeState* panelState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab)) {
|
m_shellChromeState.SetPanelVisible(ShellPanelId::XCUILayoutLab, visible);
|
||||||
panelState->visible = visible;
|
|
||||||
}
|
|
||||||
if (m_layoutLabPanel != nullptr) {
|
if (m_layoutLabPanel != nullptr) {
|
||||||
m_layoutLabPanel->SetVisible(visible);
|
m_layoutLabPanel->SetVisible(visible);
|
||||||
}
|
}
|
||||||
@@ -235,23 +180,17 @@ void Application::ConfigureShellCommandRouter() {
|
|||||||
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo);
|
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo);
|
||||||
};
|
};
|
||||||
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
||||||
if (ShellPanelChromeState* panelState = TryGetShellPanelState(ShellPanelId::XCUIDemo)) {
|
m_shellChromeState.SetHostedPreviewMode(
|
||||||
panelState->previewMode =
|
ShellPanelId::XCUIDemo,
|
||||||
enabled
|
enabled ? ShellHostedPreviewMode::NativeOffscreen : ShellHostedPreviewMode::HostedPresenter);
|
||||||
? ShellHostedPreviewMode::NativeOffscreen
|
|
||||||
: ShellHostedPreviewMode::LegacyImGui;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
||||||
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab);
|
return IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab);
|
||||||
};
|
};
|
||||||
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
||||||
if (ShellPanelChromeState* panelState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab)) {
|
m_shellChromeState.SetHostedPreviewMode(
|
||||||
panelState->previewMode =
|
ShellPanelId::XCUILayoutLab,
|
||||||
enabled
|
enabled ? ShellHostedPreviewMode::NativeOffscreen : ShellHostedPreviewMode::HostedPresenter);
|
||||||
? ShellHostedPreviewMode::NativeOffscreen
|
|
||||||
: ShellHostedPreviewMode::LegacyImGui;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
bindings.onHostedPreviewModeChanged = [this]() { ConfigureHostedPreviewPresenters(); };
|
bindings.onHostedPreviewModeChanged = [this]() { ConfigureHostedPreviewPresenters(); };
|
||||||
|
|
||||||
@@ -356,10 +295,12 @@ int Application::Run(HINSTANCE instance, int nCmdShow) {
|
|||||||
InitializeWindowCompositor();
|
InitializeWindowCompositor();
|
||||||
m_demoPanel = std::make_unique<XCUIDemoPanel>(
|
m_demoPanel = std::make_unique<XCUIDemoPanel>(
|
||||||
&m_xcuiInputSource,
|
&m_xcuiInputSource,
|
||||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)));
|
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)),
|
||||||
|
::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost());
|
||||||
m_layoutLabPanel = std::make_unique<XCUILayoutLabPanel>(
|
m_layoutLabPanel = std::make_unique<XCUILayoutLabPanel>(
|
||||||
&m_xcuiInputSource,
|
&m_xcuiInputSource,
|
||||||
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)));
|
CreateHostedPreviewPresenter(IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)),
|
||||||
|
::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost());
|
||||||
ConfigureHostedPreviewPresenters();
|
ConfigureHostedPreviewPresenters();
|
||||||
m_shellInputBridge.Reset();
|
m_shellInputBridge.Reset();
|
||||||
ConfigureShellCommandRouter();
|
ConfigureShellCommandRouter();
|
||||||
@@ -531,13 +472,12 @@ void Application::DestroyHostedPreviewSurfaces() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::SyncShellChromePanelStateFromPanels() {
|
void Application::SyncShellChromePanelStateFromPanels() {
|
||||||
if (ShellPanelChromeState* demoState = TryGetShellPanelState(ShellPanelId::XCUIDemo)) {
|
m_shellChromeState.SetPanelVisible(
|
||||||
demoState->visible = m_demoPanel != nullptr && m_demoPanel->IsVisible();
|
ShellPanelId::XCUIDemo,
|
||||||
}
|
m_demoPanel != nullptr && m_demoPanel->IsVisible());
|
||||||
|
m_shellChromeState.SetPanelVisible(
|
||||||
if (ShellPanelChromeState* layoutLabState = TryGetShellPanelState(ShellPanelId::XCUILayoutLab)) {
|
ShellPanelId::XCUILayoutLab,
|
||||||
layoutLabState->visible = m_layoutLabPanel != nullptr && m_layoutLabPanel->IsVisible();
|
m_layoutLabPanel != nullptr && m_layoutLabPanel->IsVisible());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::SyncHostedPreviewSurfaces() {
|
void Application::SyncHostedPreviewSurfaces() {
|
||||||
@@ -864,14 +804,14 @@ void Application::RenderShellChrome() {
|
|||||||
"XCUI Demo preview: %s",
|
"XCUI Demo preview: %s",
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUIDemo)
|
||||||
? "native offscreen preview surface"
|
? "native offscreen preview surface"
|
||||||
: "ImGui hosted preview");
|
: "hosted presenter");
|
||||||
}
|
}
|
||||||
if (m_layoutLabPanel != nullptr) {
|
if (m_layoutLabPanel != nullptr) {
|
||||||
ImGui::TextDisabled(
|
ImGui::TextDisabled(
|
||||||
"Layout Lab preview: %s",
|
"Layout Lab preview: %s",
|
||||||
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)
|
IsNativeHostedPreviewEnabled(ShellPanelId::XCUILayoutLab)
|
||||||
? "native offscreen preview surface"
|
? "native offscreen preview surface"
|
||||||
: "ImGui hosted preview");
|
: "hosted presenter");
|
||||||
}
|
}
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
@@ -1102,8 +1042,10 @@ void Application::Frame() {
|
|||||||
if (m_layoutLabPanel) {
|
if (m_layoutLabPanel) {
|
||||||
m_layoutLabPanel->RenderIfVisible();
|
m_layoutLabPanel->RenderIfVisible();
|
||||||
}
|
}
|
||||||
if (m_shellViewToggles.imguiDemoWindowVisible) {
|
bool showImGuiDemoWindow = IsShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow);
|
||||||
ImGui::ShowDemoWindow(&m_shellViewToggles.imguiDemoWindowVisible);
|
if (showImGuiDemoWindow) {
|
||||||
|
ImGui::ShowDemoWindow(&showImGuiDemoWindow);
|
||||||
|
SetShellViewToggleEnabled(ShellViewToggleId::ImGuiDemoWindow, showImGuiDemoWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncShellChromePanelStateFromPanels();
|
SyncShellChromePanelStateFromPanels();
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "XCUIBackend/XCUIShellChromeState.h"
|
#include "XCUIBackend/XCUIShellChromeState.h"
|
||||||
#include "XCUIBackend/XCUIStandaloneTextAtlasProvider.h"
|
#include "XCUIBackend/XCUIStandaloneTextAtlasProvider.h"
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -31,6 +30,7 @@ namespace NewEditor {
|
|||||||
|
|
||||||
class Application {
|
class Application {
|
||||||
public:
|
public:
|
||||||
|
using ShellChromeState = ::XCEngine::Editor::XCUIBackend::XCUIShellChromeState;
|
||||||
using ShellPanelId = ::XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
using ShellPanelId = ::XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
||||||
using ShellViewToggleId = ::XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
using ShellViewToggleId = ::XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
||||||
using ShellHostedPreviewMode = ::XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewMode;
|
using ShellHostedPreviewMode = ::XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewMode;
|
||||||
@@ -248,35 +248,6 @@ public:
|
|||||||
int Run(HINSTANCE instance, int nCmdShow);
|
int Run(HINSTANCE instance, int nCmdShow);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using ShellPanelStateArray = std::array<ShellPanelChromeState, static_cast<std::size_t>(ShellPanelId::Count)>;
|
|
||||||
|
|
||||||
static constexpr std::size_t GetShellPanelIndex(ShellPanelId panelId) {
|
|
||||||
return static_cast<std::size_t>(panelId);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ShellPanelStateArray CreateDefaultShellPanelStates() {
|
|
||||||
ShellPanelStateArray panels = {};
|
|
||||||
panels[GetShellPanelIndex(ShellPanelId::XCUIDemo)] = {
|
|
||||||
ShellPanelId::XCUIDemo,
|
|
||||||
"XCUI Demo",
|
|
||||||
"XCUI Demo",
|
|
||||||
"new_editor.panels.xcui_demo",
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
ShellHostedPreviewMode::NativeOffscreen
|
|
||||||
};
|
|
||||||
panels[GetShellPanelIndex(ShellPanelId::XCUILayoutLab)] = {
|
|
||||||
ShellPanelId::XCUILayoutLab,
|
|
||||||
"XCUI Layout Lab",
|
|
||||||
"XCUI Layout Lab",
|
|
||||||
"new_editor.panels.xcui_layout_lab",
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
ShellHostedPreviewMode::LegacyImGui
|
|
||||||
};
|
|
||||||
return panels;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HostedPreviewPanelDiagnostics {
|
struct HostedPreviewPanelDiagnostics {
|
||||||
std::string debugName = {};
|
std::string debugName = {};
|
||||||
std::string debugSource = {};
|
std::string debugSource = {};
|
||||||
@@ -334,7 +305,6 @@ private:
|
|||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> CreateHostedPreviewPresenter(
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> CreateHostedPreviewPresenter(
|
||||||
bool nativePreview);
|
bool nativePreview);
|
||||||
void ConfigureHostedPreviewPresenters();
|
void ConfigureHostedPreviewPresenters();
|
||||||
ShellPanelChromeState* TryGetShellPanelState(ShellPanelId panelId);
|
|
||||||
const ShellPanelChromeState* TryGetShellPanelState(ShellPanelId panelId) const;
|
const ShellPanelChromeState* TryGetShellPanelState(ShellPanelId panelId) const;
|
||||||
bool IsShellViewToggleEnabled(ShellViewToggleId toggleId) const;
|
bool IsShellViewToggleEnabled(ShellViewToggleId toggleId) const;
|
||||||
void SetShellViewToggleEnabled(ShellViewToggleId toggleId, bool enabled);
|
void SetShellViewToggleEnabled(ShellViewToggleId toggleId, bool enabled);
|
||||||
@@ -379,8 +349,7 @@ private:
|
|||||||
::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewSurfaceRegistry m_hostedPreviewSurfaceRegistry;
|
::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewSurfaceRegistry m_hostedPreviewSurfaceRegistry;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIStandaloneTextAtlasProvider m_hostedPreviewTextAtlasProvider;
|
::XCEngine::Editor::XCUIBackend::XCUIStandaloneTextAtlasProvider m_hostedPreviewTextAtlasProvider;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIRHIRenderBackend m_hostedPreviewRenderBackend;
|
::XCEngine::Editor::XCUIBackend::XCUIRHIRenderBackend m_hostedPreviewRenderBackend;
|
||||||
ShellViewToggleState m_shellViewToggles = {};
|
ShellChromeState m_shellChromeState = {};
|
||||||
ShellPanelStateArray m_shellPanels = CreateDefaultShellPanelStates();
|
|
||||||
std::vector<HostedPreviewOffscreenSurface> m_hostedPreviewSurfaces = {};
|
std::vector<HostedPreviewOffscreenSurface> m_hostedPreviewSurfaces = {};
|
||||||
::XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime m_nativeOverlayRuntime;
|
::XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime m_nativeOverlayRuntime;
|
||||||
MainWindowNativeBackdropRenderer m_nativeBackdropRenderer;
|
MainWindowNativeBackdropRenderer m_nativeBackdropRenderer;
|
||||||
|
|||||||
56
new_editor/src/XCUIBackend/ImGuiXCUIInputSource.h
Normal file
56
new_editor/src/XCUIBackend/ImGuiXCUIInputSource.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XCUIBackend/ImGuiXCUIInputAdapter.h"
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Editor {
|
||||||
|
namespace XCUIBackend {
|
||||||
|
|
||||||
|
class ImGuiXCUIInputSnapshotSource final : public IXCUIInputSnapshotSource {
|
||||||
|
public:
|
||||||
|
explicit ImGuiXCUIInputSnapshotSource(const ImGuiIO* io = nullptr)
|
||||||
|
: m_io(io) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetIO(const ImGuiIO* io) {
|
||||||
|
m_io = io;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImGuiIO* GetIO() const {
|
||||||
|
return ResolveIO();
|
||||||
|
}
|
||||||
|
|
||||||
|
XCUIInputBridgeFrameSnapshot CaptureSnapshot(
|
||||||
|
const XCUIInputBridgeCaptureOptions& options = XCUIInputBridgeCaptureOptions()) const override {
|
||||||
|
const ImGuiIO* io = ResolveIO();
|
||||||
|
return io != nullptr
|
||||||
|
? ImGuiXCUIInputAdapter::CaptureSnapshot(*io, options)
|
||||||
|
: XCUIInputBridgeFrameSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ::XCEngine::UI::UIPoint& GetPointerPosition() const override {
|
||||||
|
m_cachedPointerPosition = {};
|
||||||
|
const ImGuiIO* io = ResolveIO();
|
||||||
|
if (io != nullptr) {
|
||||||
|
m_cachedPointerPosition = ::XCEngine::UI::UIPoint(io->MousePos.x, io->MousePos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_cachedPointerPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ImGuiIO* ResolveIO() const {
|
||||||
|
if (m_io != nullptr) {
|
||||||
|
return m_io;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImGui::GetCurrentContext() != nullptr ? &ImGui::GetIO() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImGuiIO* m_io = nullptr;
|
||||||
|
mutable ::XCEngine::UI::UIPoint m_cachedPointerPosition = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace XCUIBackend
|
||||||
|
} // namespace Editor
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -23,8 +23,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override {
|
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override {
|
||||||
(void)request;
|
m_canvasSession = BuildPassiveXCUIPanelCanvasSession(request);
|
||||||
return {};
|
return m_canvasSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawFilledRect(
|
void DrawFilledRect(
|
||||||
@@ -59,7 +59,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EndCanvas() override {
|
void EndCanvas() override {
|
||||||
|
m_canvasSession = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
XCUIPanelCanvasSession m_canvasSession = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<IXCUIPanelCanvasHost> CreateNullXCUIPanelCanvasHost() {
|
inline std::unique_ptr<IXCUIPanelCanvasHost> CreateNullXCUIPanelCanvasHost() {
|
||||||
|
|||||||
@@ -260,6 +260,27 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NullXCUIHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter {
|
||||||
|
public:
|
||||||
|
bool Present(const XCUIHostedPreviewFrame& frame) override {
|
||||||
|
m_lastStats = {};
|
||||||
|
if (frame.drawData == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastStats.submittedDrawListCount = frame.drawData->GetDrawListCount();
|
||||||
|
m_lastStats.submittedCommandCount = frame.drawData->GetTotalCommandCount();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XCUIHostedPreviewStats& GetLastStats() const override {
|
||||||
|
return m_lastStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
XCUIHostedPreviewStats m_lastStats = {};
|
||||||
|
};
|
||||||
|
|
||||||
class QueuedNativeXCUIHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter {
|
class QueuedNativeXCUIHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter {
|
||||||
public:
|
public:
|
||||||
QueuedNativeXCUIHostedPreviewPresenter(
|
QueuedNativeXCUIHostedPreviewPresenter(
|
||||||
@@ -306,6 +327,10 @@ inline std::unique_ptr<IXCUIHostedPreviewPresenter> CreateQueuedNativeXCUIHosted
|
|||||||
return std::make_unique<QueuedNativeXCUIHostedPreviewPresenter>(queue, surfaceRegistry);
|
return std::make_unique<QueuedNativeXCUIHostedPreviewPresenter>(queue, surfaceRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::unique_ptr<IXCUIHostedPreviewPresenter> CreateNullXCUIHostedPreviewPresenter() {
|
||||||
|
return std::make_unique<NullXCUIHostedPreviewPresenter>();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace XCUIBackend
|
} // namespace XCUIBackend
|
||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
} // namespace XCEngine
|
} // namespace XCEngine
|
||||||
|
|||||||
@@ -85,6 +85,15 @@ struct XCUIInputBridgeFrameDelta {
|
|||||||
bool HasEventType(UI::UIInputEventType type) const;
|
bool HasEventType(UI::UIInputEventType type) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IXCUIInputSnapshotSource {
|
||||||
|
public:
|
||||||
|
virtual ~IXCUIInputSnapshotSource() = default;
|
||||||
|
|
||||||
|
virtual XCUIInputBridgeFrameSnapshot CaptureSnapshot(
|
||||||
|
const XCUIInputBridgeCaptureOptions& options = XCUIInputBridgeCaptureOptions()) const = 0;
|
||||||
|
virtual const UI::UIPoint& GetPointerPosition() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class XCUIInputBridge {
|
class XCUIInputBridge {
|
||||||
public:
|
public:
|
||||||
void Reset();
|
void Reset();
|
||||||
@@ -109,16 +118,16 @@ private:
|
|||||||
XCUIInputBridgeFrameSnapshot m_baseline = {};
|
XCUIInputBridgeFrameSnapshot m_baseline = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class XCUIWin32InputSource {
|
class XCUIWin32InputSource : public IXCUIInputSnapshotSource {
|
||||||
public:
|
public:
|
||||||
void Reset();
|
void Reset();
|
||||||
void HandleWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
void HandleWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
void ClearFrameTransients();
|
void ClearFrameTransients();
|
||||||
|
|
||||||
XCUIInputBridgeFrameSnapshot CaptureSnapshot(
|
XCUIInputBridgeFrameSnapshot CaptureSnapshot(
|
||||||
const XCUIInputBridgeCaptureOptions& options = XCUIInputBridgeCaptureOptions()) const;
|
const XCUIInputBridgeCaptureOptions& options = XCUIInputBridgeCaptureOptions()) const override;
|
||||||
|
|
||||||
const UI::UIPoint& GetPointerPosition() const {
|
const UI::UIPoint& GetPointerPosition() const override {
|
||||||
return m_pointerPosition;
|
return m_pointerPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,36 @@ struct XCUIPanelCanvasSession {
|
|||||||
bool windowFocused = false;
|
bool windowFocused = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline const char* ResolveXCUIPanelCanvasChildId(
|
||||||
|
const XCUIPanelCanvasRequest& request,
|
||||||
|
const char* fallback = "XCUIPanelCanvasHost") {
|
||||||
|
if (request.childId != nullptr && request.childId[0] != '\0') {
|
||||||
|
return request.childId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback != nullptr ? fallback : "XCUIPanelCanvasHost";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline XCUIPanelCanvasSession BuildPassiveXCUIPanelCanvasSession(
|
||||||
|
const XCUIPanelCanvasRequest& request) {
|
||||||
|
const float hostHeight = request.height > 0.0f ? request.height : 0.0f;
|
||||||
|
const float topInset = request.topInset > 0.0f ? request.topInset : 0.0f;
|
||||||
|
const float clampedTopInset = topInset < hostHeight ? topInset : hostHeight;
|
||||||
|
|
||||||
|
XCUIPanelCanvasSession session = {};
|
||||||
|
session.hostRect = ::XCEngine::UI::UIRect(0.0f, 0.0f, 0.0f, hostHeight);
|
||||||
|
session.canvasRect = ::XCEngine::UI::UIRect(
|
||||||
|
0.0f,
|
||||||
|
clampedTopInset,
|
||||||
|
0.0f,
|
||||||
|
hostHeight - clampedTopInset);
|
||||||
|
session.pointerPosition = {};
|
||||||
|
session.validCanvas = false;
|
||||||
|
session.hovered = false;
|
||||||
|
session.windowFocused = false;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
class IXCUIPanelCanvasHost {
|
class IXCUIPanelCanvasHost {
|
||||||
public:
|
public:
|
||||||
virtual ~IXCUIPanelCanvasHost() = default;
|
virtual ~IXCUIPanelCanvasHost() = default;
|
||||||
|
|||||||
@@ -10,6 +10,17 @@ constexpr std::size_t ToIndex(XCUIShellPanelId panelId) {
|
|||||||
return static_cast<std::size_t>(panelId);
|
return static_cast<std::size_t>(panelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr std::string_view kViewMenuLabel = "View";
|
||||||
|
constexpr std::string_view kXCUIDemoShortcut = "Ctrl+1";
|
||||||
|
constexpr std::string_view kXCUILayoutLabShortcut = "Ctrl+2";
|
||||||
|
constexpr std::string_view kImGuiDemoShortcut = "Ctrl+3";
|
||||||
|
constexpr std::string_view kNativeBackdropShortcut = "Ctrl+Shift+B";
|
||||||
|
constexpr std::string_view kPulseAccentShortcut = "Ctrl+Shift+P";
|
||||||
|
constexpr std::string_view kNativeXCUIOverlayShortcut = "Ctrl+Shift+O";
|
||||||
|
constexpr std::string_view kHostedPreviewHudShortcut = "Ctrl+Shift+H";
|
||||||
|
constexpr std::string_view kNativeDemoPanelPreviewShortcut = "Ctrl+Alt+1";
|
||||||
|
constexpr std::string_view kNativeLayoutLabPreviewShortcut = "Ctrl+Alt+2";
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
XCUIShellChromeState::XCUIShellChromeState() {
|
XCUIShellChromeState::XCUIShellChromeState() {
|
||||||
@@ -29,7 +40,7 @@ XCUIShellChromeState::XCUIShellChromeState() {
|
|||||||
"new_editor.panels.xcui_layout_lab",
|
"new_editor.panels.xcui_layout_lab",
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui
|
XCUIShellHostedPreviewMode::HostedPresenter
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +115,7 @@ XCUIShellHostedPreviewMode XCUIShellChromeState::GetHostedPreviewMode(XCUIShellP
|
|||||||
const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId);
|
const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId);
|
||||||
return panelState != nullptr
|
return panelState != nullptr
|
||||||
? panelState->previewMode
|
? panelState->previewMode
|
||||||
: XCUIShellHostedPreviewMode::LegacyImGui;
|
: XCUIShellHostedPreviewMode::HostedPresenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
XCUIShellHostedPreviewState XCUIShellChromeState::GetHostedPreviewState(XCUIShellPanelId panelId) const {
|
XCUIShellHostedPreviewState XCUIShellChromeState::GetHostedPreviewState(XCUIShellPanelId panelId) const {
|
||||||
@@ -115,15 +126,15 @@ XCUIShellHostedPreviewState XCUIShellChromeState::GetHostedPreviewState(XCUIShel
|
|||||||
|
|
||||||
return panelState->previewMode == XCUIShellHostedPreviewMode::NativeOffscreen
|
return panelState->previewMode == XCUIShellHostedPreviewMode::NativeOffscreen
|
||||||
? XCUIShellHostedPreviewState::NativeOffscreen
|
? XCUIShellHostedPreviewState::NativeOffscreen
|
||||||
: XCUIShellHostedPreviewState::LegacyImGui;
|
: XCUIShellHostedPreviewState::HostedPresenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XCUIShellChromeState::IsNativeHostedPreviewActive(XCUIShellPanelId panelId) const {
|
bool XCUIShellChromeState::IsNativeHostedPreviewActive(XCUIShellPanelId panelId) const {
|
||||||
return GetHostedPreviewState(panelId) == XCUIShellHostedPreviewState::NativeOffscreen;
|
return GetHostedPreviewState(panelId) == XCUIShellHostedPreviewState::NativeOffscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XCUIShellChromeState::IsLegacyHostedPreviewActive(XCUIShellPanelId panelId) const {
|
bool XCUIShellChromeState::IsHostedPresenterPreviewActive(XCUIShellPanelId panelId) const {
|
||||||
return GetHostedPreviewState(panelId) == XCUIShellHostedPreviewState::LegacyImGui;
|
return GetHostedPreviewState(panelId) == XCUIShellHostedPreviewState::HostedPresenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XCUIShellChromeState::SetHostedPreviewMode(
|
bool XCUIShellChromeState::SetHostedPreviewMode(
|
||||||
@@ -146,7 +157,7 @@ bool XCUIShellChromeState::ToggleHostedPreviewMode(XCUIShellPanelId panelId) {
|
|||||||
|
|
||||||
panelState->previewMode =
|
panelState->previewMode =
|
||||||
panelState->previewMode == XCUIShellHostedPreviewMode::NativeOffscreen
|
panelState->previewMode == XCUIShellHostedPreviewMode::NativeOffscreen
|
||||||
? XCUIShellHostedPreviewMode::LegacyImGui
|
? XCUIShellHostedPreviewMode::HostedPresenter
|
||||||
: XCUIShellHostedPreviewMode::NativeOffscreen;
|
: XCUIShellHostedPreviewMode::NativeOffscreen;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -205,15 +216,8 @@ bool XCUIShellChromeState::ToggleViewToggle(XCUIShellViewToggleId toggleId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool XCUIShellChromeState::HasCommand(std::string_view commandId) const {
|
bool XCUIShellChromeState::HasCommand(std::string_view commandId) const {
|
||||||
return commandId == GetPanelVisibilityCommandId(XCUIShellPanelId::XCUIDemo) ||
|
XCUIShellCommandDescriptor descriptor = {};
|
||||||
commandId == GetPanelVisibilityCommandId(XCUIShellPanelId::XCUILayoutLab) ||
|
return TryGetCommandDescriptor(commandId, descriptor);
|
||||||
commandId == GetViewToggleCommandId(XCUIShellViewToggleId::ImGuiDemoWindow) ||
|
|
||||||
commandId == GetViewToggleCommandId(XCUIShellViewToggleId::NativeBackdrop) ||
|
|
||||||
commandId == GetViewToggleCommandId(XCUIShellViewToggleId::PulseAccent) ||
|
|
||||||
commandId == GetViewToggleCommandId(XCUIShellViewToggleId::NativeXCUIOverlay) ||
|
|
||||||
commandId == GetViewToggleCommandId(XCUIShellViewToggleId::HostedPreviewHud) ||
|
|
||||||
commandId == GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUIDemo) ||
|
|
||||||
commandId == GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUILayoutLab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XCUIShellChromeState::InvokeCommand(std::string_view commandId) {
|
bool XCUIShellChromeState::InvokeCommand(std::string_view commandId) {
|
||||||
@@ -248,6 +252,142 @@ bool XCUIShellChromeState::InvokeCommand(std::string_view commandId) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XCUIShellChromeState::TryGetCommandDescriptor(
|
||||||
|
std::string_view commandId,
|
||||||
|
XCUIShellCommandDescriptor& outDescriptor) const {
|
||||||
|
outDescriptor = {};
|
||||||
|
outDescriptor.checkable = false;
|
||||||
|
outDescriptor.enabled = false;
|
||||||
|
|
||||||
|
const auto tryBuildPanelVisibilityDescriptor =
|
||||||
|
[this, commandId, &outDescriptor](
|
||||||
|
XCUIShellPanelId panelId,
|
||||||
|
std::string_view shortcut) {
|
||||||
|
if (commandId != GetPanelVisibilityCommandId(panelId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XCUIShellPanelChromeState* panelState = TryGetPanelState(panelId);
|
||||||
|
if (panelState == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outDescriptor.label = panelState->panelTitle;
|
||||||
|
outDescriptor.shortcut = shortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = panelState->visible;
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tryBuildPanelVisibilityDescriptor(XCUIShellPanelId::XCUIDemo, kXCUIDemoShortcut)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (tryBuildPanelVisibilityDescriptor(XCUIShellPanelId::XCUILayoutLab, kXCUILayoutLabShortcut)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::ImGuiDemoWindow)) {
|
||||||
|
outDescriptor.label = "ImGui Demo";
|
||||||
|
outDescriptor.shortcut = kImGuiDemoShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::ImGuiDemoWindow);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::NativeBackdrop)) {
|
||||||
|
outDescriptor.label = "Native Backdrop";
|
||||||
|
outDescriptor.shortcut = kNativeBackdropShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::NativeBackdrop);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::PulseAccent)) {
|
||||||
|
outDescriptor.label = "Pulse Accent";
|
||||||
|
outDescriptor.shortcut = kPulseAccentShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::PulseAccent);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::NativeXCUIOverlay)) {
|
||||||
|
outDescriptor.label = "Native XCUI Overlay";
|
||||||
|
outDescriptor.shortcut = kNativeXCUIOverlayShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::NativeXCUIOverlay);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (commandId == GetViewToggleCommandId(XCUIShellViewToggleId::HostedPreviewHud)) {
|
||||||
|
outDescriptor.label = "Hosted Preview HUD";
|
||||||
|
outDescriptor.shortcut = kHostedPreviewHudShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = GetViewToggle(XCUIShellViewToggleId::HostedPreviewHud);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (commandId == GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUIDemo)) {
|
||||||
|
outDescriptor.label = "Native Demo Panel Preview";
|
||||||
|
outDescriptor.shortcut = kNativeDemoPanelPreviewShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (commandId == GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUILayoutLab)) {
|
||||||
|
outDescriptor.label = "Native Layout Lab Preview";
|
||||||
|
outDescriptor.shortcut = kNativeLayoutLabPreviewShortcut;
|
||||||
|
outDescriptor.commandId = commandId;
|
||||||
|
outDescriptor.checkable = true;
|
||||||
|
outDescriptor.checked = IsNativeHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab);
|
||||||
|
outDescriptor.enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCUIShellMenuDescriptor XCUIShellChromeState::BuildViewMenuDescriptor() const {
|
||||||
|
XCUIShellMenuDescriptor descriptor = {};
|
||||||
|
descriptor.label = kViewMenuLabel;
|
||||||
|
descriptor.items.reserve(10u);
|
||||||
|
|
||||||
|
const auto appendCommandItem = [this, &descriptor](std::string_view commandId) {
|
||||||
|
XCUIShellCommandDescriptor commandDescriptor = {};
|
||||||
|
if (!TryGetCommandDescriptor(commandId, commandDescriptor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCUIShellMenuItemDescriptor item = {};
|
||||||
|
item.kind = XCUIShellMenuItemKind::Command;
|
||||||
|
item.command = commandDescriptor;
|
||||||
|
descriptor.items.push_back(item);
|
||||||
|
};
|
||||||
|
|
||||||
|
appendCommandItem(GetPanelVisibilityCommandId(XCUIShellPanelId::XCUIDemo));
|
||||||
|
appendCommandItem(GetPanelVisibilityCommandId(XCUIShellPanelId::XCUILayoutLab));
|
||||||
|
appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::ImGuiDemoWindow));
|
||||||
|
|
||||||
|
descriptor.items.push_back({ XCUIShellMenuItemKind::Separator, {} });
|
||||||
|
|
||||||
|
appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::NativeBackdrop));
|
||||||
|
appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::PulseAccent));
|
||||||
|
appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::NativeXCUIOverlay));
|
||||||
|
appendCommandItem(GetViewToggleCommandId(XCUIShellViewToggleId::HostedPreviewHud));
|
||||||
|
appendCommandItem(GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUIDemo));
|
||||||
|
appendCommandItem(GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUILayoutLab));
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
std::string_view XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId panelId) {
|
std::string_view XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId panelId) {
|
||||||
switch (panelId) {
|
switch (panelId) {
|
||||||
case XCUIShellPanelId::XCUIDemo:
|
case XCUIShellPanelId::XCUIDemo:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace Editor {
|
namespace Editor {
|
||||||
@@ -24,13 +25,13 @@ enum class XCUIShellViewToggleId : std::uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class XCUIShellHostedPreviewMode : std::uint8_t {
|
enum class XCUIShellHostedPreviewMode : std::uint8_t {
|
||||||
LegacyImGui = 0,
|
HostedPresenter = 0,
|
||||||
NativeOffscreen
|
NativeOffscreen
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class XCUIShellHostedPreviewState : std::uint8_t {
|
enum class XCUIShellHostedPreviewState : std::uint8_t {
|
||||||
Disabled = 0,
|
Disabled = 0,
|
||||||
LegacyImGui,
|
HostedPresenter,
|
||||||
NativeOffscreen
|
NativeOffscreen
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ struct XCUIShellPanelChromeState {
|
|||||||
std::string_view previewDebugSource = {};
|
std::string_view previewDebugSource = {};
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
bool hostedPreviewEnabled = true;
|
bool hostedPreviewEnabled = true;
|
||||||
XCUIShellHostedPreviewMode previewMode = XCUIShellHostedPreviewMode::LegacyImGui;
|
XCUIShellHostedPreviewMode previewMode = XCUIShellHostedPreviewMode::HostedPresenter;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XCUIShellViewToggleState {
|
struct XCUIShellViewToggleState {
|
||||||
@@ -64,6 +65,30 @@ struct XCUIShellChromeCommandIds {
|
|||||||
static constexpr const char* ToggleNativeLayoutLabPreview = "new_editor.view.native_layout_lab_preview";
|
static constexpr const char* ToggleNativeLayoutLabPreview = "new_editor.view.native_layout_lab_preview";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class XCUIShellMenuItemKind : std::uint8_t {
|
||||||
|
Command = 0,
|
||||||
|
Separator
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XCUIShellCommandDescriptor {
|
||||||
|
std::string_view label = {};
|
||||||
|
std::string_view shortcut = {};
|
||||||
|
std::string_view commandId = {};
|
||||||
|
bool checkable = true;
|
||||||
|
bool checked = false;
|
||||||
|
bool enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XCUIShellMenuItemDescriptor {
|
||||||
|
XCUIShellMenuItemKind kind = XCUIShellMenuItemKind::Command;
|
||||||
|
XCUIShellCommandDescriptor command = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XCUIShellMenuDescriptor {
|
||||||
|
std::string_view label = {};
|
||||||
|
std::vector<XCUIShellMenuItemDescriptor> items = {};
|
||||||
|
};
|
||||||
|
|
||||||
class XCUIShellChromeState {
|
class XCUIShellChromeState {
|
||||||
public:
|
public:
|
||||||
XCUIShellChromeState();
|
XCUIShellChromeState();
|
||||||
@@ -82,7 +107,7 @@ public:
|
|||||||
XCUIShellHostedPreviewMode GetHostedPreviewMode(XCUIShellPanelId panelId) const;
|
XCUIShellHostedPreviewMode GetHostedPreviewMode(XCUIShellPanelId panelId) const;
|
||||||
XCUIShellHostedPreviewState GetHostedPreviewState(XCUIShellPanelId panelId) const;
|
XCUIShellHostedPreviewState GetHostedPreviewState(XCUIShellPanelId panelId) const;
|
||||||
bool IsNativeHostedPreviewActive(XCUIShellPanelId panelId) const;
|
bool IsNativeHostedPreviewActive(XCUIShellPanelId panelId) const;
|
||||||
bool IsLegacyHostedPreviewActive(XCUIShellPanelId panelId) const;
|
bool IsHostedPresenterPreviewActive(XCUIShellPanelId panelId) const;
|
||||||
bool SetHostedPreviewMode(XCUIShellPanelId panelId, XCUIShellHostedPreviewMode mode);
|
bool SetHostedPreviewMode(XCUIShellPanelId panelId, XCUIShellHostedPreviewMode mode);
|
||||||
bool ToggleHostedPreviewMode(XCUIShellPanelId panelId);
|
bool ToggleHostedPreviewMode(XCUIShellPanelId panelId);
|
||||||
|
|
||||||
@@ -92,6 +117,10 @@ public:
|
|||||||
|
|
||||||
bool HasCommand(std::string_view commandId) const;
|
bool HasCommand(std::string_view commandId) const;
|
||||||
bool InvokeCommand(std::string_view commandId);
|
bool InvokeCommand(std::string_view commandId);
|
||||||
|
bool TryGetCommandDescriptor(
|
||||||
|
std::string_view commandId,
|
||||||
|
XCUIShellCommandDescriptor& outDescriptor) const;
|
||||||
|
XCUIShellMenuDescriptor BuildViewMenuDescriptor() const;
|
||||||
|
|
||||||
static std::string_view GetPanelVisibilityCommandId(XCUIShellPanelId panelId);
|
static std::string_view GetPanelVisibilityCommandId(XCUIShellPanelId panelId);
|
||||||
static std::string_view GetPanelPreviewModeCommandId(XCUIShellPanelId panelId);
|
static std::string_view GetPanelPreviewModeCommandId(XCUIShellPanelId panelId);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "XCUIDemoPanel.h"
|
#include "XCUIDemoPanel.h"
|
||||||
|
|
||||||
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
#include "XCUIBackend/NullXCUIPanelCanvasHost.h"
|
||||||
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
|
||||||
#include "XCUIBackend/ImGuiXCUIInputAdapter.h"
|
|
||||||
|
|
||||||
#include <XCEngine/UI/Types.h>
|
#include <XCEngine/UI/Types.h>
|
||||||
|
|
||||||
@@ -55,15 +53,27 @@ void DrawRectOverlay(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetPreviewPathLabel(bool nativeHostedPreview) {
|
const char* GetPreviewPathLabel(
|
||||||
return nativeHostedPreview ? "native queued offscreen surface" : "legacy imgui transition";
|
const ::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter* previewPresenter) {
|
||||||
|
if (previewPresenter == nullptr) {
|
||||||
|
return "not injected";
|
||||||
|
}
|
||||||
|
|
||||||
|
return previewPresenter->IsNativeQueued()
|
||||||
|
? "native queued offscreen surface"
|
||||||
|
: "hosted presenter";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetPreviewStateLabel(
|
const char* GetPreviewStateLabel(
|
||||||
bool nativeHostedPreview,
|
const ::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter* previewPresenter,
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& previewStats,
|
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& previewStats,
|
||||||
bool hasHostedSurfaceDescriptor,
|
bool hasHostedSurfaceDescriptor,
|
||||||
bool showHostedSurfaceImage) {
|
bool showHostedSurfaceImage) {
|
||||||
|
if (previewPresenter == nullptr) {
|
||||||
|
return "disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool nativeHostedPreview = previewPresenter->IsNativeQueued();
|
||||||
if (nativeHostedPreview) {
|
if (nativeHostedPreview) {
|
||||||
if (showHostedSurfaceImage) {
|
if (showHostedSurfaceImage) {
|
||||||
return "live";
|
return "live";
|
||||||
@@ -77,20 +87,37 @@ const char* GetPreviewStateLabel(
|
|||||||
return previewStats.presented ? "live" : "idle";
|
return previewStats.presented ? "live" : "idle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot BuildPassiveSnapshot(
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession& canvasSession,
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions& options) {
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot snapshot = {};
|
||||||
|
snapshot.pointerPosition = canvasSession.pointerPosition;
|
||||||
|
snapshot.pointerInside = options.hasPointerInsideOverride
|
||||||
|
? options.pointerInsideOverride
|
||||||
|
: (canvasSession.validCanvas && canvasSession.hovered);
|
||||||
|
snapshot.windowFocused = options.windowFocused;
|
||||||
|
snapshot.timestampNanoseconds = options.timestampNanoseconds;
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
XCUIDemoPanel::XCUIDemoPanel(::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource)
|
XCUIDemoPanel::XCUIDemoPanel(::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource)
|
||||||
: XCUIDemoPanel(inputSource, ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter()) {}
|
: XCUIDemoPanel(
|
||||||
|
inputSource,
|
||||||
|
nullptr,
|
||||||
|
::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost()) {}
|
||||||
|
|
||||||
XCUIDemoPanel::XCUIDemoPanel(
|
XCUIDemoPanel::XCUIDemoPanel(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource,
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource,
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter)
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter,
|
||||||
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost)
|
||||||
: Panel("XCUI Demo")
|
: Panel("XCUI Demo")
|
||||||
, m_inputSource(inputSource)
|
, m_inputSource(inputSource)
|
||||||
, m_previewPresenter(std::move(previewPresenter))
|
, m_previewPresenter(std::move(previewPresenter))
|
||||||
, m_canvasHost(::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost()) {
|
, m_canvasHost(std::move(canvasHost)) {
|
||||||
if (m_previewPresenter == nullptr) {
|
if (m_canvasHost == nullptr) {
|
||||||
m_previewPresenter = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
|
||||||
}
|
}
|
||||||
m_lastReloadSucceeded = m_runtime.ReloadDocuments();
|
m_lastReloadSucceeded = m_runtime.ReloadDocuments();
|
||||||
}
|
}
|
||||||
@@ -113,9 +140,6 @@ const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& XCUIDemoPanel::Ge
|
|||||||
void XCUIDemoPanel::SetHostedPreviewPresenter(
|
void XCUIDemoPanel::SetHostedPreviewPresenter(
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
|
||||||
m_previewPresenter = std::move(previewPresenter);
|
m_previewPresenter = std::move(previewPresenter);
|
||||||
if (m_previewPresenter == nullptr) {
|
|
||||||
m_previewPresenter = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
|
||||||
}
|
|
||||||
m_lastPreviewStats = {};
|
m_lastPreviewStats = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +147,7 @@ void XCUIDemoPanel::SetCanvasHost(
|
|||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost) {
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost) {
|
||||||
m_canvasHost = std::move(canvasHost);
|
m_canvasHost = std::move(canvasHost);
|
||||||
if (m_canvasHost == nullptr) {
|
if (m_canvasHost == nullptr) {
|
||||||
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost();
|
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +184,7 @@ void XCUIDemoPanel::Render() {
|
|||||||
const float canvasHeight = (std::max)(140.0f, hostRegion.y - diagnosticsHeight);
|
const float canvasHeight = (std::max)(140.0f, hostRegion.y - diagnosticsHeight);
|
||||||
|
|
||||||
if (m_canvasHost == nullptr) {
|
if (m_canvasHost == nullptr) {
|
||||||
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost();
|
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool nativeHostedPreview = IsUsingNativeHostedPreview();
|
const bool nativeHostedPreview = IsUsingNativeHostedPreview();
|
||||||
@@ -174,7 +198,7 @@ void XCUIDemoPanel::Render() {
|
|||||||
nativeHostedPreview &&
|
nativeHostedPreview &&
|
||||||
m_previewPresenter != nullptr &&
|
m_previewPresenter != nullptr &&
|
||||||
m_previewPresenter->TryGetSurfaceImage(kPreviewDebugName, hostedSurfaceImage);
|
m_previewPresenter->TryGetSurfaceImage(kPreviewDebugName, hostedSurfaceImage);
|
||||||
const char* const previewPathLabel = GetPreviewPathLabel(nativeHostedPreview);
|
const char* const previewPathLabel = GetPreviewPathLabel(m_previewPresenter.get());
|
||||||
const float topInset = m_showCanvasHud ? (kCanvasHudHeight + kCanvasHudPadding) : 0.0f;
|
const float topInset = m_showCanvasHud ? (kCanvasHudHeight + kCanvasHudPadding) : 0.0f;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest canvasRequest = {};
|
::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest canvasRequest = {};
|
||||||
canvasRequest.childId = "XCUIDemoCanvasHost";
|
canvasRequest.childId = "XCUIDemoCanvasHost";
|
||||||
@@ -183,11 +207,11 @@ void XCUIDemoPanel::Render() {
|
|||||||
canvasRequest.showSurfaceImage = showHostedSurfaceImage;
|
canvasRequest.showSurfaceImage = showHostedSurfaceImage;
|
||||||
canvasRequest.surfaceImage = hostedSurfaceImage;
|
canvasRequest.surfaceImage = hostedSurfaceImage;
|
||||||
canvasRequest.placeholderTitle =
|
canvasRequest.placeholderTitle =
|
||||||
nativeHostedPreview ? "Native XCUI preview pending" : "Legacy XCUI canvas host";
|
nativeHostedPreview ? "Native XCUI preview pending" : "Injected XCUI canvas host";
|
||||||
canvasRequest.placeholderSubtitle =
|
canvasRequest.placeholderSubtitle =
|
||||||
nativeHostedPreview
|
nativeHostedPreview
|
||||||
? "Waiting for native queued render output to publish back into the sandbox panel."
|
? "Waiting for native queued render output to publish back into the sandbox panel."
|
||||||
: "Legacy ImGui transition path stays active until native offscreen preview is enabled.";
|
: "Inject a concrete canvas host to render the demo sandbox inside this panel.";
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession canvasSession =
|
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession canvasSession =
|
||||||
m_canvasHost->BeginCanvas(canvasRequest);
|
m_canvasHost->BeginCanvas(canvasRequest);
|
||||||
const UI::UIRect canvasRect = canvasSession.canvasRect;
|
const UI::UIRect canvasRect = canvasSession.canvasRect;
|
||||||
@@ -211,10 +235,7 @@ void XCUIDemoPanel::Render() {
|
|||||||
bridgeOptions.hasPointerInsideOverride = true;
|
bridgeOptions.hasPointerInsideOverride = true;
|
||||||
bridgeOptions.pointerInsideOverride = validCanvas && canvasSession.hovered;
|
bridgeOptions.pointerInsideOverride = validCanvas && canvasSession.hovered;
|
||||||
bridgeOptions.windowFocused = canvasSession.windowFocused;
|
bridgeOptions.windowFocused = canvasSession.windowFocused;
|
||||||
snapshot = ::XCEngine::Editor::XCUIBackend::ImGuiXCUIInputAdapter::CaptureSnapshot(
|
snapshot = BuildPassiveSnapshot(canvasSession, bridgeOptions);
|
||||||
ImGui::GetIO(),
|
|
||||||
bridgeOptions);
|
|
||||||
snapshot.pointerPosition = canvasSession.pointerPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_inputBridge.HasBaseline()) {
|
if (!m_inputBridge.HasBaseline()) {
|
||||||
@@ -253,7 +274,7 @@ void XCUIDemoPanel::Render() {
|
|||||||
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIDemoFrameStats& stats = frame.stats;
|
const ::XCEngine::Editor::XCUIBackend::XCUIDemoFrameStats& stats = frame.stats;
|
||||||
const char* const previewStateLabel = GetPreviewStateLabel(
|
const char* const previewStateLabel = GetPreviewStateLabel(
|
||||||
nativeHostedPreview,
|
m_previewPresenter.get(),
|
||||||
m_lastPreviewStats,
|
m_lastPreviewStats,
|
||||||
hasHostedSurfaceDescriptor,
|
hasHostedSurfaceDescriptor,
|
||||||
showHostedSurfaceImage);
|
showHostedSurfaceImage);
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ namespace NewEditor {
|
|||||||
class XCUIDemoPanel : public Panel {
|
class XCUIDemoPanel : public Panel {
|
||||||
public:
|
public:
|
||||||
explicit XCUIDemoPanel(
|
explicit XCUIDemoPanel(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource = nullptr);
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource = nullptr);
|
||||||
XCUIDemoPanel(
|
XCUIDemoPanel(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource,
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource,
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter);
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter,
|
||||||
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost = nullptr);
|
||||||
~XCUIDemoPanel() override = default;
|
~XCUIDemoPanel() override = default;
|
||||||
|
|
||||||
void Render() override;
|
void Render() override;
|
||||||
@@ -37,7 +38,7 @@ private:
|
|||||||
bool m_hostedPreviewEnabled = true;
|
bool m_hostedPreviewEnabled = true;
|
||||||
bool m_showCanvasHud = true;
|
bool m_showCanvasHud = true;
|
||||||
bool m_showDebugRects = true;
|
bool m_showDebugRects = true;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* m_inputSource = nullptr;
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* m_inputSource = nullptr;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridge m_inputBridge;
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridge m_inputBridge;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIDemoRuntime m_runtime;
|
::XCEngine::Editor::XCUIBackend::XCUIDemoRuntime m_runtime;
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> m_previewPresenter;
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> m_previewPresenter;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
#include "XCUILayoutLabPanel.h"
|
#include "XCUILayoutLabPanel.h"
|
||||||
|
|
||||||
#include "XCUIBackend/ImGuiXCUIHostedPreviewPresenter.h"
|
#include "XCUIBackend/NullXCUIPanelCanvasHost.h"
|
||||||
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
|
||||||
#include <XCEngine/UI/Types.h>
|
#include <XCEngine/UI/Types.h>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
@@ -24,15 +25,27 @@ bool ContainsPoint(const UI::UIRect& rect, const UI::UIPoint& point) {
|
|||||||
point.y <= rect.y + rect.height;
|
point.y <= rect.y + rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetPreviewPathLabel(bool nativeHostedPreview) {
|
const char* GetPreviewPathLabel(
|
||||||
return nativeHostedPreview ? "native queued offscreen surface" : "legacy imgui transition";
|
const ::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter* previewPresenter) {
|
||||||
|
if (previewPresenter == nullptr) {
|
||||||
|
return "not injected";
|
||||||
|
}
|
||||||
|
|
||||||
|
return previewPresenter->IsNativeQueued()
|
||||||
|
? "native queued offscreen surface"
|
||||||
|
: "hosted presenter";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetPreviewStateLabel(
|
const char* GetPreviewStateLabel(
|
||||||
bool nativeHostedPreview,
|
const ::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter* previewPresenter,
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& previewStats,
|
const ::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats& previewStats,
|
||||||
bool hasHostedSurfaceDescriptor,
|
bool hasHostedSurfaceDescriptor,
|
||||||
bool showHostedSurfaceImage) {
|
bool showHostedSurfaceImage) {
|
||||||
|
if (previewPresenter == nullptr) {
|
||||||
|
return "disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool nativeHostedPreview = previewPresenter->IsNativeQueued();
|
||||||
if (nativeHostedPreview) {
|
if (nativeHostedPreview) {
|
||||||
if (showHostedSurfaceImage) {
|
if (showHostedSurfaceImage) {
|
||||||
return "live";
|
return "live";
|
||||||
@@ -46,6 +59,12 @@ const char* GetPreviewStateLabel(
|
|||||||
return previewStats.presented ? "live" : "idle";
|
return previewStats.presented ? "live" : "idle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ContainsKeyTransition(
|
||||||
|
const std::vector<std::int32_t>& keys,
|
||||||
|
std::int32_t keyCode) {
|
||||||
|
return std::find(keys.begin(), keys.end(), keyCode) != keys.end();
|
||||||
|
}
|
||||||
|
|
||||||
bool ShouldCaptureKeyboardNavigation(
|
bool ShouldCaptureKeyboardNavigation(
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession& canvasSession,
|
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession& canvasSession,
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& previousFrame) {
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& previousFrame) {
|
||||||
@@ -60,33 +79,56 @@ bool ShouldCaptureKeyboardNavigation(
|
|||||||
|
|
||||||
void PopulateKeyboardNavigationInput(
|
void PopulateKeyboardNavigationInput(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState& input,
|
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState& input,
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta& frameDelta,
|
||||||
bool captureKeyboardNavigation) {
|
bool captureKeyboardNavigation) {
|
||||||
if (!captureKeyboardNavigation) {
|
if (!captureKeyboardNavigation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.navigatePrevious = ImGui::IsKeyPressed(ImGuiKey_UpArrow);
|
using ::XCEngine::Input::KeyCode;
|
||||||
input.navigateNext = ImGui::IsKeyPressed(ImGuiKey_DownArrow);
|
const auto pressedThisFrame =
|
||||||
input.navigateHome = ImGui::IsKeyPressed(ImGuiKey_Home);
|
[&frameDelta](KeyCode keyCode) {
|
||||||
input.navigateEnd = ImGui::IsKeyPressed(ImGuiKey_End);
|
const std::int32_t code = static_cast<std::int32_t>(keyCode);
|
||||||
input.navigateCollapse = ImGui::IsKeyPressed(ImGuiKey_LeftArrow);
|
return ContainsKeyTransition(frameDelta.keyboard.pressedKeys, code) ||
|
||||||
input.navigateExpand = ImGui::IsKeyPressed(ImGuiKey_RightArrow);
|
ContainsKeyTransition(frameDelta.keyboard.repeatedKeys, code);
|
||||||
|
};
|
||||||
|
|
||||||
|
input.navigatePrevious = pressedThisFrame(KeyCode::Up);
|
||||||
|
input.navigateNext = pressedThisFrame(KeyCode::Down);
|
||||||
|
input.navigateHome = pressedThisFrame(KeyCode::Home);
|
||||||
|
input.navigateEnd = pressedThisFrame(KeyCode::End);
|
||||||
|
input.navigateCollapse = pressedThisFrame(KeyCode::Left);
|
||||||
|
input.navigateExpand = pressedThisFrame(KeyCode::Right);
|
||||||
|
}
|
||||||
|
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot BuildPassiveSnapshot(
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession& canvasSession,
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions& options) {
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot snapshot = {};
|
||||||
|
snapshot.pointerPosition = canvasSession.pointerPosition;
|
||||||
|
snapshot.pointerInside = options.hasPointerInsideOverride
|
||||||
|
? options.pointerInsideOverride
|
||||||
|
: (canvasSession.validCanvas && canvasSession.hovered);
|
||||||
|
snapshot.windowFocused = options.windowFocused;
|
||||||
|
snapshot.timestampNanoseconds = options.timestampNanoseconds;
|
||||||
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
XCUILayoutLabPanel::XCUILayoutLabPanel(::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource)
|
XCUILayoutLabPanel::XCUILayoutLabPanel(::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource)
|
||||||
: XCUILayoutLabPanel(inputSource, ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter()) {}
|
: XCUILayoutLabPanel(inputSource, nullptr, ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost()) {}
|
||||||
|
|
||||||
XCUILayoutLabPanel::XCUILayoutLabPanel(
|
XCUILayoutLabPanel::XCUILayoutLabPanel(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource,
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource,
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter)
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter,
|
||||||
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost)
|
||||||
: Panel("XCUI Layout Lab")
|
: Panel("XCUI Layout Lab")
|
||||||
, m_inputSource(inputSource)
|
, m_inputSource(inputSource)
|
||||||
, m_previewPresenter(std::move(previewPresenter))
|
, m_previewPresenter(std::move(previewPresenter))
|
||||||
, m_canvasHost(::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost()) {
|
, m_canvasHost(std::move(canvasHost)) {
|
||||||
if (m_previewPresenter == nullptr) {
|
if (m_canvasHost == nullptr) {
|
||||||
m_previewPresenter = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
|
||||||
}
|
}
|
||||||
m_lastReloadSucceeded = m_runtime.ReloadDocuments();
|
m_lastReloadSucceeded = m_runtime.ReloadDocuments();
|
||||||
}
|
}
|
||||||
@@ -113,9 +155,6 @@ bool XCUILayoutLabPanel::TryGetElementRect(const std::string& elementId, ::XCEng
|
|||||||
void XCUILayoutLabPanel::SetHostedPreviewPresenter(
|
void XCUILayoutLabPanel::SetHostedPreviewPresenter(
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter) {
|
||||||
m_previewPresenter = std::move(previewPresenter);
|
m_previewPresenter = std::move(previewPresenter);
|
||||||
if (m_previewPresenter == nullptr) {
|
|
||||||
m_previewPresenter = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter();
|
|
||||||
}
|
|
||||||
m_lastPreviewStats = {};
|
m_lastPreviewStats = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +162,7 @@ void XCUILayoutLabPanel::SetCanvasHost(
|
|||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost) {
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost) {
|
||||||
m_canvasHost = std::move(canvasHost);
|
m_canvasHost = std::move(canvasHost);
|
||||||
if (m_canvasHost == nullptr) {
|
if (m_canvasHost == nullptr) {
|
||||||
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost();
|
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +195,7 @@ void XCUILayoutLabPanel::Render() {
|
|||||||
const float canvasHeight = (std::max)(140.0f, hostRegion.y - diagnosticsHeight);
|
const float canvasHeight = (std::max)(140.0f, hostRegion.y - diagnosticsHeight);
|
||||||
|
|
||||||
if (m_canvasHost == nullptr) {
|
if (m_canvasHost == nullptr) {
|
||||||
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost();
|
m_canvasHost = ::XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool nativeHostedPreview = IsUsingNativeHostedPreview();
|
const bool nativeHostedPreview = IsUsingNativeHostedPreview();
|
||||||
@@ -170,18 +209,18 @@ void XCUILayoutLabPanel::Render() {
|
|||||||
nativeHostedPreview &&
|
nativeHostedPreview &&
|
||||||
m_previewPresenter != nullptr &&
|
m_previewPresenter != nullptr &&
|
||||||
m_previewPresenter->TryGetSurfaceImage(kPreviewDebugName, hostedSurfaceImage);
|
m_previewPresenter->TryGetSurfaceImage(kPreviewDebugName, hostedSurfaceImage);
|
||||||
const char* const previewPathLabel = GetPreviewPathLabel(nativeHostedPreview);
|
const char* const previewPathLabel = GetPreviewPathLabel(m_previewPresenter.get());
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest canvasRequest = {};
|
::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest canvasRequest = {};
|
||||||
canvasRequest.childId = "XCUILayoutLabCanvasHost";
|
canvasRequest.childId = "XCUILayoutLabCanvasHost";
|
||||||
canvasRequest.height = canvasHeight;
|
canvasRequest.height = canvasHeight;
|
||||||
canvasRequest.showSurfaceImage = showHostedSurfaceImage;
|
canvasRequest.showSurfaceImage = showHostedSurfaceImage;
|
||||||
canvasRequest.surfaceImage = hostedSurfaceImage;
|
canvasRequest.surfaceImage = hostedSurfaceImage;
|
||||||
canvasRequest.placeholderTitle =
|
canvasRequest.placeholderTitle =
|
||||||
nativeHostedPreview ? "Native layout preview pending" : "Legacy layout canvas host";
|
nativeHostedPreview ? "Native layout preview pending" : "Injected layout canvas host";
|
||||||
canvasRequest.placeholderSubtitle =
|
canvasRequest.placeholderSubtitle =
|
||||||
nativeHostedPreview
|
nativeHostedPreview
|
||||||
? "Waiting for native queued render output to publish back into the layout sandbox."
|
? "Waiting for native queued render output to publish back into the layout sandbox."
|
||||||
: "Legacy ImGui transition path remains active until native offscreen preview is enabled.";
|
: "Inject a concrete canvas host to render the layout sandbox inside this panel.";
|
||||||
canvasRequest.badgeTitle = "Layout Lab";
|
canvasRequest.badgeTitle = "Layout Lab";
|
||||||
canvasRequest.badgeSubtitle = previewPathLabel;
|
canvasRequest.badgeSubtitle = previewPathLabel;
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession canvasSession =
|
const ::XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession canvasSession =
|
||||||
@@ -189,18 +228,40 @@ void XCUILayoutLabPanel::Render() {
|
|||||||
const UI::UIRect canvasRect = canvasSession.canvasRect;
|
const UI::UIRect canvasRect = canvasSession.canvasRect;
|
||||||
const bool validCanvas = canvasSession.validCanvas;
|
const bool validCanvas = canvasSession.validCanvas;
|
||||||
|
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions bridgeOptions = {};
|
||||||
|
bridgeOptions.timestampNanoseconds = static_cast<std::uint64_t>(
|
||||||
|
std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch())
|
||||||
|
.count());
|
||||||
|
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot snapshot = {};
|
||||||
|
if (m_inputSource != nullptr) {
|
||||||
|
bridgeOptions.hasPointerInsideOverride = true;
|
||||||
|
bridgeOptions.windowFocused = canvasSession.windowFocused;
|
||||||
|
const UI::UIPoint pointerPosition = m_inputSource->GetPointerPosition();
|
||||||
|
bridgeOptions.pointerInsideOverride = validCanvas && ContainsPoint(canvasRect, pointerPosition);
|
||||||
|
snapshot = m_inputSource->CaptureSnapshot(bridgeOptions);
|
||||||
|
} else {
|
||||||
|
bridgeOptions.hasPointerInsideOverride = true;
|
||||||
|
bridgeOptions.pointerInsideOverride = validCanvas && canvasSession.hovered;
|
||||||
|
bridgeOptions.windowFocused = canvasSession.windowFocused;
|
||||||
|
snapshot = BuildPassiveSnapshot(canvasSession, bridgeOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_inputBridge.HasBaseline()) {
|
||||||
|
m_inputBridge.Prime(snapshot);
|
||||||
|
}
|
||||||
|
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta frameDelta =
|
||||||
|
m_inputBridge.Translate(snapshot);
|
||||||
|
|
||||||
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState input = {};
|
::XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState input = {};
|
||||||
input.canvasRect = canvasRect;
|
input.canvasRect = canvasRect;
|
||||||
if (m_inputSource != nullptr) {
|
input.pointerPosition = snapshot.pointerPosition;
|
||||||
input.pointerPosition = m_inputSource->GetPointerPosition();
|
input.pointerInside = snapshot.pointerInside;
|
||||||
input.pointerInside = validCanvas && ContainsPoint(input.canvasRect, input.pointerPosition);
|
input.pointerPressed = input.pointerInside && frameDelta.pointer.pressed[0];
|
||||||
} else {
|
|
||||||
input.pointerPosition = canvasSession.pointerPosition;
|
|
||||||
input.pointerInside = validCanvas && canvasSession.hovered;
|
|
||||||
}
|
|
||||||
input.pointerPressed = input.pointerInside && ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
|
||||||
PopulateKeyboardNavigationInput(
|
PopulateKeyboardNavigationInput(
|
||||||
input,
|
input,
|
||||||
|
frameDelta,
|
||||||
ShouldCaptureKeyboardNavigation(canvasSession, m_runtime.GetFrameResult()));
|
ShouldCaptureKeyboardNavigation(canvasSession, m_runtime.GetFrameResult()));
|
||||||
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& frame = m_runtime.Update(input);
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& frame = m_runtime.Update(input);
|
||||||
@@ -220,7 +281,7 @@ void XCUILayoutLabPanel::Render() {
|
|||||||
|
|
||||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameStats& stats = frame.stats;
|
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameStats& stats = frame.stats;
|
||||||
const char* const previewStateLabel = GetPreviewStateLabel(
|
const char* const previewStateLabel = GetPreviewStateLabel(
|
||||||
nativeHostedPreview,
|
m_previewPresenter.get(),
|
||||||
m_lastPreviewStats,
|
m_lastPreviewStats,
|
||||||
hasHostedSurfaceDescriptor,
|
hasHostedSurfaceDescriptor,
|
||||||
showHostedSurfaceImage);
|
showHostedSurfaceImage);
|
||||||
@@ -266,7 +327,7 @@ void XCUILayoutLabPanel::Render() {
|
|||||||
ImGui::TextDisabled("No native surface descriptor has been published back yet.");
|
ImGui::TextDisabled("No native surface descriptor has been published back yet.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextDisabled("Legacy path renders directly into the panel draw list. No native surface descriptor exists.");
|
ImGui::TextDisabled("No native surface descriptor is available without a native queued presenter.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SeparatorText("Runtime");
|
ImGui::SeparatorText("Runtime");
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ namespace NewEditor {
|
|||||||
class XCUILayoutLabPanel : public Panel {
|
class XCUILayoutLabPanel : public Panel {
|
||||||
public:
|
public:
|
||||||
explicit XCUILayoutLabPanel(
|
explicit XCUILayoutLabPanel(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource = nullptr);
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource = nullptr);
|
||||||
XCUILayoutLabPanel(
|
XCUILayoutLabPanel(
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* inputSource,
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* inputSource,
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter);
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> previewPresenter,
|
||||||
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> canvasHost = nullptr);
|
||||||
~XCUILayoutLabPanel() override = default;
|
~XCUILayoutLabPanel() override = default;
|
||||||
|
|
||||||
void Render() override;
|
void Render() override;
|
||||||
@@ -37,7 +38,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool m_lastReloadSucceeded = false;
|
bool m_lastReloadSucceeded = false;
|
||||||
bool m_hostedPreviewEnabled = true;
|
bool m_hostedPreviewEnabled = true;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource* m_inputSource = nullptr;
|
::XCEngine::Editor::XCUIBackend::IXCUIInputSnapshotSource* m_inputSource = nullptr;
|
||||||
|
::XCEngine::Editor::XCUIBackend::XCUIInputBridge m_inputBridge;
|
||||||
::XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime m_runtime;
|
::XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime m_runtime;
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> m_previewPresenter;
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> m_previewPresenter;
|
||||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> m_canvasHost;
|
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost> m_canvasHost;
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ set(NEW_EDITOR_LAYOUT_LAB_PANEL_HEADER
|
|||||||
set(NEW_EDITOR_LAYOUT_LAB_PANEL_SOURCE
|
set(NEW_EDITOR_LAYOUT_LAB_PANEL_SOURCE
|
||||||
${CMAKE_SOURCE_DIR}/new_editor/src/panels/XCUILayoutLabPanel.cpp
|
${CMAKE_SOURCE_DIR}/new_editor/src/panels/XCUILayoutLabPanel.cpp
|
||||||
)
|
)
|
||||||
|
set(NEW_EDITOR_DEMO_PANEL_HEADER
|
||||||
|
${CMAKE_SOURCE_DIR}/new_editor/src/panels/XCUIDemoPanel.h
|
||||||
|
)
|
||||||
|
set(NEW_EDITOR_DEMO_PANEL_SOURCE
|
||||||
|
${CMAKE_SOURCE_DIR}/new_editor/src/panels/XCUIDemoPanel.cpp
|
||||||
|
)
|
||||||
set(NEW_EDITOR_BASE_PANEL_SOURCE
|
set(NEW_EDITOR_BASE_PANEL_SOURCE
|
||||||
${CMAKE_SOURCE_DIR}/new_editor/src/panels/Panel.cpp
|
${CMAKE_SOURCE_DIR}/new_editor/src/panels/Panel.cpp
|
||||||
)
|
)
|
||||||
@@ -237,6 +243,10 @@ if(EXISTS "${NEW_EDITOR_LAYOUT_LAB_PANEL_HEADER}" AND
|
|||||||
EXISTS "${NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE}" AND
|
EXISTS "${NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE}" AND
|
||||||
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE_HEADER}" AND
|
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE_HEADER}" AND
|
||||||
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}" AND
|
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_INPUT_BRIDGE_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_INPUT_BRIDGE_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}" AND
|
||||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_layout_lab_panel.cpp" AND
|
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_layout_lab_panel.cpp" AND
|
||||||
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||||
add_executable(new_editor_xcui_layout_lab_panel_tests
|
add_executable(new_editor_xcui_layout_lab_panel_tests
|
||||||
@@ -245,6 +255,8 @@ if(EXISTS "${NEW_EDITOR_LAYOUT_LAB_PANEL_HEADER}" AND
|
|||||||
${NEW_EDITOR_BASE_PANEL_SOURCE}
|
${NEW_EDITOR_BASE_PANEL_SOURCE}
|
||||||
${NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE}
|
${NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE}
|
||||||
${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}
|
${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}
|
||||||
|
${NEW_EDITOR_INPUT_BRIDGE_SOURCE}
|
||||||
|
${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}
|
||||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp
|
||||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_draw.cpp
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_draw.cpp
|
||||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_tables.cpp
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_tables.cpp
|
||||||
@@ -274,7 +286,59 @@ if(EXISTS "${NEW_EDITOR_LAYOUT_LAB_PANEL_HEADER}" AND
|
|||||||
|
|
||||||
xcengine_discover_new_editor_gtests(new_editor_xcui_layout_lab_panel_tests)
|
xcengine_discover_new_editor_gtests(new_editor_xcui_layout_lab_panel_tests)
|
||||||
else()
|
else()
|
||||||
message(STATUS "Skipping new_editor_xcui_layout_lab_panel_tests because panel, runtime, test, or ImGui sources are missing.")
|
message(STATUS "Skipping new_editor_xcui_layout_lab_panel_tests because panel, runtime, test, input bridge, or ImGui sources are missing.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${NEW_EDITOR_DEMO_PANEL_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_DEMO_PANEL_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_RUNTIME_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_RUNTIME_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_INPUT_BRIDGE_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_INPUT_BRIDGE_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}" AND
|
||||||
|
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_demo_panel.cpp" AND
|
||||||
|
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||||
|
add_executable(new_editor_xcui_demo_panel_tests
|
||||||
|
test_xcui_demo_panel.cpp
|
||||||
|
${NEW_EDITOR_DEMO_PANEL_SOURCE}
|
||||||
|
${NEW_EDITOR_BASE_PANEL_SOURCE}
|
||||||
|
${NEW_EDITOR_RUNTIME_SOURCE}
|
||||||
|
${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}
|
||||||
|
${NEW_EDITOR_INPUT_BRIDGE_SOURCE}
|
||||||
|
${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}
|
||||||
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp
|
||||||
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_draw.cpp
|
||||||
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_tables.cpp
|
||||||
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_widgets.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
xcengine_configure_new_editor_test_target(new_editor_xcui_demo_panel_tests)
|
||||||
|
|
||||||
|
target_link_libraries(new_editor_xcui_demo_panel_tests
|
||||||
|
PRIVATE
|
||||||
|
XCEngine
|
||||||
|
GTest::gtest
|
||||||
|
GTest::gtest_main
|
||||||
|
user32
|
||||||
|
comdlg32
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(new_editor_xcui_demo_panel_tests PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}/engine/include
|
||||||
|
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||||
|
${CMAKE_BINARY_DIR}/_deps/imgui-src
|
||||||
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends
|
||||||
|
)
|
||||||
|
target_compile_definitions(new_editor_xcui_demo_panel_tests PRIVATE
|
||||||
|
XCENGINE_NEW_EDITOR_REPO_ROOT="${XCENGINE_TEST_REPO_ROOT_CMAKE}"
|
||||||
|
)
|
||||||
|
|
||||||
|
xcengine_discover_new_editor_gtests(new_editor_xcui_demo_panel_tests)
|
||||||
|
else()
|
||||||
|
message(STATUS "Skipping new_editor_xcui_demo_panel_tests because panel, runtime, test, input bridge, or ImGui sources are missing.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(EXISTS "${NEW_EDITOR_BACKEND_HEADER}" AND EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
if(EXISTS "${NEW_EDITOR_BACKEND_HEADER}" AND EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||||
@@ -511,11 +575,14 @@ endif()
|
|||||||
|
|
||||||
if(EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER}" AND
|
if(EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER}" AND
|
||||||
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}" AND
|
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_INPUT_BRIDGE_HEADER}" AND
|
||||||
|
EXISTS "${NEW_EDITOR_INPUT_BRIDGE_SOURCE}" AND
|
||||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_imgui_xcui_input_adapter.cpp" AND
|
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_imgui_xcui_input_adapter.cpp" AND
|
||||||
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||||
add_executable(new_editor_imgui_xcui_input_adapter_tests
|
add_executable(new_editor_imgui_xcui_input_adapter_tests
|
||||||
test_imgui_xcui_input_adapter.cpp
|
test_imgui_xcui_input_adapter.cpp
|
||||||
${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}
|
${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}
|
||||||
|
${NEW_EDITOR_INPUT_BRIDGE_SOURCE}
|
||||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp
|
||||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_draw.cpp
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_draw.cpp
|
||||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_tables.cpp
|
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_tables.cpp
|
||||||
@@ -542,7 +609,7 @@ if(EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER}" AND
|
|||||||
|
|
||||||
xcengine_discover_new_editor_gtests(new_editor_imgui_xcui_input_adapter_tests)
|
xcengine_discover_new_editor_gtests(new_editor_imgui_xcui_input_adapter_tests)
|
||||||
else()
|
else()
|
||||||
message(STATUS "Skipping new_editor_imgui_xcui_input_adapter_tests because ImGui adapter files, test source, or ImGui sources are missing.")
|
message(STATUS "Skipping new_editor_imgui_xcui_input_adapter_tests because ImGui adapter files, input bridge files, test source, or ImGui sources are missing.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(EXISTS "${NEW_EDITOR_RHI_COMMAND_SUPPORT_HEADER}")
|
if(EXISTS "${NEW_EDITOR_RHI_COMMAND_SUPPORT_HEADER}")
|
||||||
|
|||||||
@@ -38,59 +38,77 @@ struct ShellCommandHarness {
|
|||||||
"new_editor.panels.xcui_layout_lab",
|
"new_editor.panels.xcui_layout_lab",
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
Application::ShellHostedPreviewMode::LegacyImGui
|
Application::ShellHostedPreviewMode::HostedPresenter
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::ShellPanelChromeState& Panel(Application::ShellPanelId panelId) {
|
|
||||||
return panels[ToPanelIndex(panelId)];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Application::ShellPanelChromeState& Panel(Application::ShellPanelId panelId) const {
|
const Application::ShellPanelChromeState& Panel(Application::ShellPanelId panelId) const {
|
||||||
return panels[ToPanelIndex(panelId)];
|
return panels[ToPanelIndex(panelId)];
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::ShellCommandBindings BuildBindings() {
|
Application::ShellCommandBindings BuildBindings() {
|
||||||
Application::ShellCommandBindings bindings = {};
|
Application::ShellCommandBindings bindings = {};
|
||||||
bindings.getXCUIDemoPanelVisible = [this]() { return Panel(Application::ShellPanelId::XCUIDemo).visible; };
|
bindings.getXCUIDemoPanelVisible = [this]() {
|
||||||
|
return Panel(Application::ShellPanelId::XCUIDemo).visible;
|
||||||
|
};
|
||||||
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
||||||
Panel(Application::ShellPanelId::XCUIDemo).visible = visible;
|
panels[ToPanelIndex(Application::ShellPanelId::XCUIDemo)].visible = visible;
|
||||||
};
|
};
|
||||||
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
||||||
return Panel(Application::ShellPanelId::XCUILayoutLab).visible;
|
return Panel(Application::ShellPanelId::XCUILayoutLab).visible;
|
||||||
};
|
};
|
||||||
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
||||||
Panel(Application::ShellPanelId::XCUILayoutLab).visible = visible;
|
panels[ToPanelIndex(Application::ShellPanelId::XCUILayoutLab)].visible = visible;
|
||||||
|
};
|
||||||
|
bindings.getImGuiDemoWindowVisible = [this]() {
|
||||||
|
return viewToggles.imguiDemoWindowVisible;
|
||||||
|
};
|
||||||
|
bindings.setImGuiDemoWindowVisible = [this](bool visible) {
|
||||||
|
viewToggles.imguiDemoWindowVisible = visible;
|
||||||
|
};
|
||||||
|
bindings.getNativeBackdropVisible = [this]() {
|
||||||
|
return viewToggles.nativeBackdropVisible;
|
||||||
|
};
|
||||||
|
bindings.setNativeBackdropVisible = [this](bool visible) {
|
||||||
|
viewToggles.nativeBackdropVisible = visible;
|
||||||
|
};
|
||||||
|
bindings.getPulseAccentEnabled = [this]() {
|
||||||
|
return viewToggles.pulseAccentEnabled;
|
||||||
|
};
|
||||||
|
bindings.setPulseAccentEnabled = [this](bool enabled) {
|
||||||
|
viewToggles.pulseAccentEnabled = enabled;
|
||||||
|
};
|
||||||
|
bindings.getNativeXCUIOverlayVisible = [this]() {
|
||||||
|
return viewToggles.nativeXCUIOverlayVisible;
|
||||||
|
};
|
||||||
|
bindings.setNativeXCUIOverlayVisible = [this](bool visible) {
|
||||||
|
viewToggles.nativeXCUIOverlayVisible = visible;
|
||||||
|
};
|
||||||
|
bindings.getHostedPreviewHudVisible = [this]() {
|
||||||
|
return viewToggles.hostedPreviewHudVisible;
|
||||||
|
};
|
||||||
|
bindings.setHostedPreviewHudVisible = [this](bool visible) {
|
||||||
|
viewToggles.hostedPreviewHudVisible = visible;
|
||||||
};
|
};
|
||||||
bindings.getImGuiDemoWindowVisible = [this]() { return viewToggles.imguiDemoWindowVisible; };
|
|
||||||
bindings.setImGuiDemoWindowVisible = [this](bool visible) { viewToggles.imguiDemoWindowVisible = visible; };
|
|
||||||
bindings.getNativeBackdropVisible = [this]() { return viewToggles.nativeBackdropVisible; };
|
|
||||||
bindings.setNativeBackdropVisible = [this](bool visible) { viewToggles.nativeBackdropVisible = visible; };
|
|
||||||
bindings.getPulseAccentEnabled = [this]() { return viewToggles.pulseAccentEnabled; };
|
|
||||||
bindings.setPulseAccentEnabled = [this](bool enabled) { viewToggles.pulseAccentEnabled = enabled; };
|
|
||||||
bindings.getNativeXCUIOverlayVisible = [this]() { return viewToggles.nativeXCUIOverlayVisible; };
|
|
||||||
bindings.setNativeXCUIOverlayVisible = [this](bool visible) { viewToggles.nativeXCUIOverlayVisible = visible; };
|
|
||||||
bindings.getHostedPreviewHudVisible = [this]() { return viewToggles.hostedPreviewHudVisible; };
|
|
||||||
bindings.setHostedPreviewHudVisible = [this](bool visible) { viewToggles.hostedPreviewHudVisible = visible; };
|
|
||||||
bindings.getNativeDemoPanelPreviewEnabled = [this]() {
|
bindings.getNativeDemoPanelPreviewEnabled = [this]() {
|
||||||
return Panel(Application::ShellPanelId::XCUIDemo).previewMode ==
|
return Panel(Application::ShellPanelId::XCUIDemo).previewMode ==
|
||||||
Application::ShellHostedPreviewMode::NativeOffscreen;
|
Application::ShellHostedPreviewMode::NativeOffscreen;
|
||||||
};
|
};
|
||||||
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
||||||
Panel(Application::ShellPanelId::XCUIDemo).previewMode =
|
panels[ToPanelIndex(Application::ShellPanelId::XCUIDemo)].previewMode =
|
||||||
enabled
|
enabled
|
||||||
? Application::ShellHostedPreviewMode::NativeOffscreen
|
? Application::ShellHostedPreviewMode::NativeOffscreen
|
||||||
: Application::ShellHostedPreviewMode::LegacyImGui;
|
: Application::ShellHostedPreviewMode::HostedPresenter;
|
||||||
};
|
};
|
||||||
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
||||||
return Panel(Application::ShellPanelId::XCUILayoutLab).previewMode ==
|
return Panel(Application::ShellPanelId::XCUILayoutLab).previewMode ==
|
||||||
Application::ShellHostedPreviewMode::NativeOffscreen;
|
Application::ShellHostedPreviewMode::NativeOffscreen;
|
||||||
};
|
};
|
||||||
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
||||||
Panel(Application::ShellPanelId::XCUILayoutLab).previewMode =
|
panels[ToPanelIndex(Application::ShellPanelId::XCUILayoutLab)].previewMode =
|
||||||
enabled
|
enabled
|
||||||
? Application::ShellHostedPreviewMode::NativeOffscreen
|
? Application::ShellHostedPreviewMode::NativeOffscreen
|
||||||
: Application::ShellHostedPreviewMode::LegacyImGui;
|
: Application::ShellHostedPreviewMode::HostedPresenter;
|
||||||
};
|
};
|
||||||
bindings.onHostedPreviewModeChanged = [this]() { ++hostedPreviewReconfigureCount; };
|
bindings.onHostedPreviewModeChanged = [this]() { ++hostedPreviewReconfigureCount; };
|
||||||
return bindings;
|
return bindings;
|
||||||
@@ -134,7 +152,7 @@ TEST(ApplicationShellCommandBindingsTest, PreviewModeCommandsTriggerHostedPrevie
|
|||||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeDemoPanelPreview));
|
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeDemoPanelPreview));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
harness.Panel(Application::ShellPanelId::XCUIDemo).previewMode,
|
harness.Panel(Application::ShellPanelId::XCUIDemo).previewMode,
|
||||||
Application::ShellHostedPreviewMode::LegacyImGui);
|
Application::ShellHostedPreviewMode::HostedPresenter);
|
||||||
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 1);
|
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 1);
|
||||||
|
|
||||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeLayoutLabPreview));
|
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeLayoutLabPreview));
|
||||||
@@ -243,7 +261,7 @@ TEST(ApplicationShellCommandBindingsTest, PreviewShortcutInvokesCommandHandlerAn
|
|||||||
EXPECT_TRUE(router.InvokeMatchingShortcut({ &previewSnapshot }));
|
EXPECT_TRUE(router.InvokeMatchingShortcut({ &previewSnapshot }));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
harness.Panel(Application::ShellPanelId::XCUIDemo).previewMode,
|
harness.Panel(Application::ShellPanelId::XCUIDemo).previewMode,
|
||||||
Application::ShellHostedPreviewMode::LegacyImGui);
|
Application::ShellHostedPreviewMode::HostedPresenter);
|
||||||
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 1);
|
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ void PrepareImGui(float width = 1024.0f, float height = 768.0f) {
|
|||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.DisplaySize = ImVec2(width, height);
|
io.DisplaySize = ImVec2(width, height);
|
||||||
io.DeltaTime = 1.0f / 60.0f;
|
io.DeltaTime = 1.0f / 60.0f;
|
||||||
|
unsigned char* fontPixels = nullptr;
|
||||||
|
int fontWidth = 0;
|
||||||
|
int fontHeight = 0;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&fontPixels, &fontWidth, &fontHeight);
|
||||||
|
io.Fonts->SetTexID(static_cast<ImTextureID>(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -36,17 +41,17 @@ TEST(ImGuiXCUIInputAdapterTest, CaptureSnapshotMapsImGuiStateIntoXCUIFrameSnapsh
|
|||||||
PrepareImGui(800.0f, 600.0f);
|
PrepareImGui(800.0f, 600.0f);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.MousePos = ImVec2(120.0f, 72.0f);
|
||||||
|
io.MouseDown[0] = true;
|
||||||
|
io.MouseWheel = 1.0f;
|
||||||
io.WantCaptureMouse = true;
|
io.WantCaptureMouse = true;
|
||||||
io.WantCaptureKeyboard = true;
|
io.WantCaptureKeyboard = true;
|
||||||
io.WantTextInput = true;
|
io.WantTextInput = true;
|
||||||
io.AddMousePosEvent(120.0f, 72.0f);
|
io.KeyCtrl = true;
|
||||||
io.AddMouseButtonEvent(0, true);
|
io.KeysData[ImGuiKey_LeftCtrl - ImGuiKey_NamedKey_BEGIN].Down = true;
|
||||||
io.AddMouseWheelEvent(0.0f, 1.0f);
|
io.KeysData[ImGuiKey_P - ImGuiKey_NamedKey_BEGIN].Down = true;
|
||||||
io.AddKeyEvent(ImGuiKey_LeftCtrl, true);
|
io.InputQueueCharacters.resize(0);
|
||||||
io.AddKeyEvent(ImGuiKey_P, true);
|
io.InputQueueCharacters.push_back(static_cast<ImWchar>('p'));
|
||||||
io.AddInputCharacter('p');
|
|
||||||
|
|
||||||
ImGui::NewFrame();
|
|
||||||
|
|
||||||
XCUIInputBridgeCaptureOptions options = {};
|
XCUIInputBridgeCaptureOptions options = {};
|
||||||
options.pointerOffset = XCEngine::UI::UIPoint(20.0f, 12.0f);
|
options.pointerOffset = XCEngine::UI::UIPoint(20.0f, 12.0f);
|
||||||
@@ -55,8 +60,6 @@ TEST(ImGuiXCUIInputAdapterTest, CaptureSnapshotMapsImGuiStateIntoXCUIFrameSnapsh
|
|||||||
|
|
||||||
const auto snapshot = ImGuiXCUIInputAdapter::CaptureSnapshot(io, options);
|
const auto snapshot = ImGuiXCUIInputAdapter::CaptureSnapshot(io, options);
|
||||||
|
|
||||||
ImGui::EndFrame();
|
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(snapshot.pointerPosition.x, 100.0f);
|
EXPECT_FLOAT_EQ(snapshot.pointerPosition.x, 100.0f);
|
||||||
EXPECT_FLOAT_EQ(snapshot.pointerPosition.y, 60.0f);
|
EXPECT_FLOAT_EQ(snapshot.pointerPosition.y, 60.0f);
|
||||||
EXPECT_TRUE(snapshot.pointerInside);
|
EXPECT_TRUE(snapshot.pointerInside);
|
||||||
|
|||||||
213
tests/NewEditor/test_xcui_demo_panel.cpp
Normal file
213
tests/NewEditor/test_xcui_demo_panel.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "panels/XCUIDemoPanel.h"
|
||||||
|
|
||||||
|
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
||||||
|
#include "XCUIBackend/XCUIPanelCanvasHost.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
||||||
|
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession;
|
||||||
|
using XCEngine::NewEditor::XCUIDemoPanel;
|
||||||
|
|
||||||
|
class ImGuiContextScope {
|
||||||
|
public:
|
||||||
|
ImGuiContextScope() {
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ImGuiContextScope() {
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void PrepareImGui(float width = 1280.0f, float height = 900.0f) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.DisplaySize = ImVec2(width, height);
|
||||||
|
io.DeltaTime = 1.0f / 60.0f;
|
||||||
|
unsigned char* fontPixels = nullptr;
|
||||||
|
int fontWidth = 0;
|
||||||
|
int fontHeight = 0;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&fontPixels, &fontWidth, &fontHeight);
|
||||||
|
io.Fonts->SetTexID(static_cast<ImTextureID>(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordingHostedPreviewPresenter final : public IXCUIHostedPreviewPresenter {
|
||||||
|
public:
|
||||||
|
bool Present(const XCUIHostedPreviewFrame& frame) override {
|
||||||
|
++presentCallCount;
|
||||||
|
lastCanvasRect = frame.canvasRect;
|
||||||
|
lastLogicalSize = frame.logicalSize;
|
||||||
|
lastDebugName = frame.debugName != nullptr ? frame.debugName : "";
|
||||||
|
|
||||||
|
m_lastStats = {};
|
||||||
|
if (frame.drawData == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDrawListCount = frame.drawData->GetDrawListCount();
|
||||||
|
lastCommandCount = frame.drawData->GetTotalCommandCount();
|
||||||
|
m_lastStats.presented = true;
|
||||||
|
m_lastStats.submittedDrawListCount = lastDrawListCount;
|
||||||
|
m_lastStats.submittedCommandCount = lastCommandCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XCUIHostedPreviewStats& GetLastStats() const override {
|
||||||
|
return m_lastStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t presentCallCount = 0u;
|
||||||
|
XCEngine::UI::UIRect lastCanvasRect = {};
|
||||||
|
XCEngine::UI::UISize lastLogicalSize = {};
|
||||||
|
std::size_t lastDrawListCount = 0u;
|
||||||
|
std::size_t lastCommandCount = 0u;
|
||||||
|
std::string lastDebugName = {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
XCUIHostedPreviewStats m_lastStats = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class StubCanvasHost final : public IXCUIPanelCanvasHost {
|
||||||
|
public:
|
||||||
|
const char* GetDebugName() const override {
|
||||||
|
return "StubCanvasHost";
|
||||||
|
}
|
||||||
|
|
||||||
|
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend GetBackend() const override {
|
||||||
|
return XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend::Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities GetCapabilities() const override {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
XCUIPanelCanvasSession BeginCanvas(const XCUIPanelCanvasRequest& request) override {
|
||||||
|
lastRequest = request;
|
||||||
|
++beginCanvasCallCount;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawFilledRect(
|
||||||
|
const XCEngine::UI::UIRect&,
|
||||||
|
const XCEngine::UI::UIColor&,
|
||||||
|
float) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawOutlineRect(
|
||||||
|
const XCEngine::UI::UIRect&,
|
||||||
|
const XCEngine::UI::UIColor&,
|
||||||
|
float,
|
||||||
|
float) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawText(
|
||||||
|
const XCEngine::UI::UIPoint&,
|
||||||
|
std::string_view,
|
||||||
|
const XCEngine::UI::UIColor&,
|
||||||
|
float) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndCanvas() override {
|
||||||
|
++endCanvasCallCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t beginCanvasCallCount = 0u;
|
||||||
|
std::size_t endCanvasCallCount = 0u;
|
||||||
|
XCUIPanelCanvasRequest lastRequest = {};
|
||||||
|
XCUIPanelCanvasSession session = {
|
||||||
|
XCEngine::UI::UIRect(0.0f, 0.0f, 960.0f, 640.0f),
|
||||||
|
XCEngine::UI::UIRect(12.0f, 18.0f, 936.0f, 512.0f),
|
||||||
|
XCEngine::UI::UIPoint(120.0f, 140.0f),
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void RenderPanelFrame(XCUIDemoPanel& panel, ImGuiContextScope&) {
|
||||||
|
PrepareImGui();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
panel.Render();
|
||||||
|
ImGui::Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUIDemoPanelTest, DefaultConstructionDoesNotAutoCreateHostedPreviewPresenter) {
|
||||||
|
ImGuiContextScope contextScope;
|
||||||
|
|
||||||
|
auto canvasHost = std::make_unique<StubCanvasHost>();
|
||||||
|
XCUIDemoPanel panel;
|
||||||
|
panel.SetCanvasHost(std::move(canvasHost));
|
||||||
|
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
|
||||||
|
const XCUIHostedPreviewStats& stats = panel.GetLastPreviewStats();
|
||||||
|
EXPECT_FALSE(stats.presented);
|
||||||
|
EXPECT_FALSE(stats.queuedToNativePass);
|
||||||
|
EXPECT_EQ(stats.submittedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.submittedCommandCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUIDemoPanelTest, ConstructorUsesGenericNullCanvasHostUntilOuterLayerInjectsOne) {
|
||||||
|
ImGuiContextScope contextScope;
|
||||||
|
|
||||||
|
auto previewPresenter = std::make_unique<RecordingHostedPreviewPresenter>();
|
||||||
|
RecordingHostedPreviewPresenter* previewPresenterPtr = previewPresenter.get();
|
||||||
|
|
||||||
|
XCUIDemoPanel panel(nullptr, std::move(previewPresenter));
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
|
||||||
|
ASSERT_EQ(previewPresenterPtr->presentCallCount, 1u);
|
||||||
|
EXPECT_EQ(previewPresenterPtr->lastDebugName, "XCUI Demo");
|
||||||
|
EXPECT_FLOAT_EQ(previewPresenterPtr->lastCanvasRect.x, 0.0f);
|
||||||
|
EXPECT_GT(previewPresenterPtr->lastCanvasRect.y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(previewPresenterPtr->lastCanvasRect.width, 0.0f);
|
||||||
|
EXPECT_GT(previewPresenterPtr->lastCanvasRect.height, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(previewPresenterPtr->lastLogicalSize.width, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(
|
||||||
|
previewPresenterPtr->lastLogicalSize.height,
|
||||||
|
previewPresenterPtr->lastCanvasRect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUIDemoPanelTest, ClearingHostedPreviewPresenterDoesNotRestoreImGuiFallback) {
|
||||||
|
ImGuiContextScope contextScope;
|
||||||
|
|
||||||
|
auto previewPresenter = std::make_unique<RecordingHostedPreviewPresenter>();
|
||||||
|
RecordingHostedPreviewPresenter* previewPresenterPtr = previewPresenter.get();
|
||||||
|
auto canvasHost = std::make_unique<StubCanvasHost>();
|
||||||
|
|
||||||
|
XCUIDemoPanel panel(nullptr, std::move(previewPresenter));
|
||||||
|
panel.SetCanvasHost(std::move(canvasHost));
|
||||||
|
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
ASSERT_EQ(previewPresenterPtr->presentCallCount, 1u);
|
||||||
|
EXPECT_TRUE(panel.GetLastPreviewStats().presented);
|
||||||
|
|
||||||
|
panel.SetHostedPreviewPresenter(nullptr);
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
|
||||||
|
const XCUIHostedPreviewStats& stats = panel.GetLastPreviewStats();
|
||||||
|
EXPECT_FALSE(stats.presented);
|
||||||
|
EXPECT_FALSE(stats.queuedToNativePass);
|
||||||
|
EXPECT_EQ(stats.submittedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.submittedCommandCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter;
|
using XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter;
|
||||||
|
using XCEngine::Editor::XCUIBackend::CreateNullXCUIHostedPreviewPresenter;
|
||||||
using XCEngine::Editor::XCUIBackend::CreateQueuedNativeXCUIHostedPreviewPresenter;
|
using XCEngine::Editor::XCUIBackend::CreateQueuedNativeXCUIHostedPreviewPresenter;
|
||||||
using XCEngine::Editor::XCUIBackend::IImGuiXCUIHostedPreviewTargetBinding;
|
using XCEngine::Editor::XCUIBackend::IImGuiXCUIHostedPreviewTargetBinding;
|
||||||
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
||||||
@@ -92,6 +93,80 @@ TEST(XCUIHostedPreviewPresenterTest, PresentReturnsFalseAndClearsStatsWhenFrameH
|
|||||||
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(XCUIHostedPreviewPresenterTest, NullPresenterReturnsFalseAndClearsStatsWhenFrameHasNoDrawData) {
|
||||||
|
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter = CreateNullXCUIHostedPreviewPresenter();
|
||||||
|
ASSERT_NE(presenter, nullptr);
|
||||||
|
|
||||||
|
XCUIHostedPreviewFrame frame = {};
|
||||||
|
const bool presented = presenter->Present(frame);
|
||||||
|
const XCUIHostedPreviewStats& stats = presenter->GetLastStats();
|
||||||
|
|
||||||
|
EXPECT_FALSE(presented);
|
||||||
|
EXPECT_FALSE(stats.presented);
|
||||||
|
EXPECT_FALSE(stats.queuedToNativePass);
|
||||||
|
EXPECT_EQ(stats.submittedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.submittedCommandCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(XCUIHostedPreviewPresenterTest, NullPresenterAcceptsDrawDataWithoutPresentingOrQueueing) {
|
||||||
|
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter = CreateNullXCUIHostedPreviewPresenter();
|
||||||
|
ASSERT_NE(presenter, nullptr);
|
||||||
|
|
||||||
|
XCEngine::UI::UIDrawData drawData = {};
|
||||||
|
XCEngine::UI::UIDrawList& drawList = drawData.EmplaceDrawList("HostedPreviewNull");
|
||||||
|
drawList.AddFilledRect(
|
||||||
|
XCEngine::UI::UIRect(12.0f, 14.0f, 48.0f, 30.0f),
|
||||||
|
XCEngine::UI::UIColor(0.25f, 0.5f, 0.8f, 1.0f));
|
||||||
|
drawList.AddText(
|
||||||
|
XCEngine::UI::UIPoint(18.0f, 24.0f),
|
||||||
|
"null",
|
||||||
|
XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f),
|
||||||
|
14.0f);
|
||||||
|
|
||||||
|
XCUIHostedPreviewFrame frame = {};
|
||||||
|
frame.drawData = &drawData;
|
||||||
|
frame.debugName = "XCUI Null Preview";
|
||||||
|
|
||||||
|
const bool presented = presenter->Present(frame);
|
||||||
|
const XCUIHostedPreviewStats& stats = presenter->GetLastStats();
|
||||||
|
|
||||||
|
EXPECT_FALSE(presented);
|
||||||
|
EXPECT_FALSE(stats.presented);
|
||||||
|
EXPECT_FALSE(stats.queuedToNativePass);
|
||||||
|
EXPECT_EQ(stats.submittedDrawListCount, 1u);
|
||||||
|
EXPECT_EQ(stats.submittedCommandCount, 2u);
|
||||||
|
EXPECT_EQ(stats.flushedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(XCUIHostedPreviewPresenterTest, NullPresenterSurfaceQueriesReturnFalseAndClearOutputs) {
|
||||||
|
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter = CreateNullXCUIHostedPreviewPresenter();
|
||||||
|
ASSERT_NE(presenter, nullptr);
|
||||||
|
|
||||||
|
XCUIHostedPreviewSurfaceDescriptor descriptor = {};
|
||||||
|
descriptor.debugName = "stale";
|
||||||
|
descriptor.debugSource = "stale";
|
||||||
|
descriptor.queuedThisFrame = true;
|
||||||
|
|
||||||
|
XCUIHostedPreviewSurfaceImage image = {};
|
||||||
|
image.texture = MakeHostedPreviewTextureHandle(29u, 256u, 128u);
|
||||||
|
image.surfaceWidth = 256u;
|
||||||
|
image.surfaceHeight = 128u;
|
||||||
|
|
||||||
|
EXPECT_FALSE(presenter->TryGetSurfaceDescriptor("XCUI Demo", descriptor));
|
||||||
|
EXPECT_TRUE(descriptor.debugName.empty());
|
||||||
|
EXPECT_TRUE(descriptor.debugSource.empty());
|
||||||
|
EXPECT_FALSE(descriptor.queuedThisFrame);
|
||||||
|
EXPECT_FALSE(descriptor.image.IsValid());
|
||||||
|
|
||||||
|
EXPECT_FALSE(presenter->TryGetSurfaceImage("XCUI Demo", image));
|
||||||
|
EXPECT_FALSE(image.IsValid());
|
||||||
|
EXPECT_EQ(image.surfaceWidth, 0u);
|
||||||
|
EXPECT_EQ(image.surfaceHeight, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoExplicitBindingResolvedImGuiDrawList) {
|
TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoExplicitBindingResolvedImGuiDrawList) {
|
||||||
ImGuiContextScope contextScope;
|
ImGuiContextScope contextScope;
|
||||||
PrepareImGui(800.0f, 600.0f);
|
PrepareImGui(800.0f, 600.0f);
|
||||||
@@ -229,7 +304,7 @@ TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoExplicitBindingRe
|
|||||||
EXPECT_GE(targetDrawList->CmdBuffer.Size, baselineCommandCount);
|
EXPECT_GE(targetDrawList->CmdBuffer.Size, baselineCommandCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(XCUIHostedPreviewPresenterTest, DefaultFactoryStillUsesCurrentWindowBindingForLegacyImGuiPath) {
|
TEST(XCUIHostedPreviewPresenterTest, DefaultFactoryStillUsesCurrentWindowBindingForImGuiPresenterPath) {
|
||||||
ImGuiContextScope contextScope;
|
ImGuiContextScope contextScope;
|
||||||
PrepareImGui(800.0f, 600.0f);
|
PrepareImGui(800.0f, 600.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "panels/XCUILayoutLabPanel.h"
|
#include "panels/XCUILayoutLabPanel.h"
|
||||||
|
|
||||||
|
#include "XCUIBackend/ImGuiXCUIInputSource.h"
|
||||||
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
#include "XCUIBackend/XCUIHostedPreviewPresenter.h"
|
||||||
#include "XCUIBackend/XCUIPanelCanvasHost.h"
|
#include "XCUIBackend/XCUIPanelCanvasHost.h"
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ namespace {
|
|||||||
|
|
||||||
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
||||||
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
||||||
|
using XCEngine::Editor::XCUIBackend::ImGuiXCUIInputSnapshotSource;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame;
|
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats;
|
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewStats;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
||||||
@@ -155,13 +157,15 @@ void ClickElement(
|
|||||||
RenderPanelFrame(
|
RenderPanelFrame(
|
||||||
panel,
|
panel,
|
||||||
contextScope,
|
contextScope,
|
||||||
[](ImGuiIO& io) {
|
[clickPoint](ImGuiIO& io) {
|
||||||
|
io.AddMousePosEvent(clickPoint.x, clickPoint.y);
|
||||||
io.AddMouseButtonEvent(ImGuiMouseButton_Left, true);
|
io.AddMouseButtonEvent(ImGuiMouseButton_Left, true);
|
||||||
});
|
});
|
||||||
RenderPanelFrame(
|
RenderPanelFrame(
|
||||||
panel,
|
panel,
|
||||||
contextScope,
|
contextScope,
|
||||||
[](ImGuiIO& io) {
|
[clickPoint](ImGuiIO& io) {
|
||||||
|
io.AddMousePosEvent(clickPoint.x, clickPoint.y);
|
||||||
io.AddMouseButtonEvent(ImGuiMouseButton_Left, false);
|
io.AddMouseButtonEvent(ImGuiMouseButton_Left, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -190,10 +194,10 @@ TEST(NewEditorXCUILayoutLabPanelTest, MapsPreviousNextHomeAndEndIntoRuntimeNavig
|
|||||||
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
|
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
|
||||||
auto canvasHost = std::make_unique<StubCanvasHost>();
|
auto canvasHost = std::make_unique<StubCanvasHost>();
|
||||||
StubCanvasHost* canvasHostPtr = canvasHost.get();
|
StubCanvasHost* canvasHostPtr = canvasHost.get();
|
||||||
|
ImGuiXCUIInputSnapshotSource inputSource(nullptr);
|
||||||
|
|
||||||
XCUILayoutLabPanel panel(nullptr, std::move(previewPresenter));
|
XCUILayoutLabPanel panel(&inputSource, std::move(previewPresenter), std::move(canvasHost));
|
||||||
panel.SetHostedPreviewEnabled(false);
|
panel.SetHostedPreviewEnabled(false);
|
||||||
panel.SetCanvasHost(std::move(canvasHost));
|
|
||||||
|
|
||||||
RenderPanelFrame(panel, contextScope);
|
RenderPanelFrame(panel, contextScope);
|
||||||
ClickElement(panel, *canvasHostPtr, "assetLighting", contextScope);
|
ClickElement(panel, *canvasHostPtr, "assetLighting", contextScope);
|
||||||
@@ -223,10 +227,10 @@ TEST(NewEditorXCUILayoutLabPanelTest, MapsCollapseAndExpandIntoRuntimeNavigation
|
|||||||
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
|
auto previewPresenter = std::make_unique<StubHostedPreviewPresenter>();
|
||||||
auto canvasHost = std::make_unique<StubCanvasHost>();
|
auto canvasHost = std::make_unique<StubCanvasHost>();
|
||||||
StubCanvasHost* canvasHostPtr = canvasHost.get();
|
StubCanvasHost* canvasHostPtr = canvasHost.get();
|
||||||
|
ImGuiXCUIInputSnapshotSource inputSource(nullptr);
|
||||||
|
|
||||||
XCUILayoutLabPanel panel(nullptr, std::move(previewPresenter));
|
XCUILayoutLabPanel panel(&inputSource, std::move(previewPresenter), std::move(canvasHost));
|
||||||
panel.SetHostedPreviewEnabled(false);
|
panel.SetHostedPreviewEnabled(false);
|
||||||
panel.SetCanvasHost(std::move(canvasHost));
|
|
||||||
|
|
||||||
RenderPanelFrame(panel, contextScope);
|
RenderPanelFrame(panel, contextScope);
|
||||||
ClickElement(panel, *canvasHostPtr, "treeScenes", contextScope);
|
ClickElement(panel, *canvasHostPtr, "treeScenes", contextScope);
|
||||||
@@ -250,4 +254,17 @@ TEST(NewEditorXCUILayoutLabPanelTest, MapsCollapseAndExpandIntoRuntimeNavigation
|
|||||||
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeScenes");
|
EXPECT_EQ(panel.GetFrameResult().stats.selectedElementId, "treeScenes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUILayoutLabPanelTest, DefaultFallbackDoesNotCreateImplicitHostedPreviewPresenter) {
|
||||||
|
ImGuiContextScope contextScope;
|
||||||
|
|
||||||
|
XCUILayoutLabPanel panel(nullptr);
|
||||||
|
|
||||||
|
RenderPanelFrame(panel, contextScope);
|
||||||
|
|
||||||
|
EXPECT_FALSE(panel.IsUsingNativeHostedPreview());
|
||||||
|
EXPECT_FALSE(panel.GetLastPreviewStats().presented);
|
||||||
|
EXPECT_EQ(panel.GetLastPreviewStats().submittedDrawListCount, 0u);
|
||||||
|
EXPECT_EQ(panel.GetLastPreviewStats().submittedCommandCount, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost;
|
using XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost;
|
||||||
|
using XCEngine::Editor::XCUIBackend::BuildPassiveXCUIPanelCanvasSession;
|
||||||
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
||||||
|
using XCEngine::Editor::XCUIBackend::ResolveXCUIPanelCanvasChildId;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
||||||
@@ -24,7 +26,41 @@ TEST(NewEditorXCUIPanelCanvasHostTest, NullHostReportsExplicitBackendAndCapabili
|
|||||||
EXPECT_FALSE(capabilities.supportsPrimitiveOverlays);
|
EXPECT_FALSE(capabilities.supportsPrimitiveOverlays);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NewEditorXCUIPanelCanvasHostTest, NullHostBeginCanvasReturnsEmptySessionAndDrawCallsAreNoops) {
|
TEST(NewEditorXCUIPanelCanvasHostTest, ResolveChildIdFallsBackToStableDefaultForMissingNames) {
|
||||||
|
XCUIPanelCanvasRequest request = {};
|
||||||
|
EXPECT_STREQ(ResolveXCUIPanelCanvasChildId(request), "XCUIPanelCanvasHost");
|
||||||
|
EXPECT_STREQ(ResolveXCUIPanelCanvasChildId(request, "FallbackCanvas"), "FallbackCanvas");
|
||||||
|
|
||||||
|
request.childId = "";
|
||||||
|
EXPECT_STREQ(ResolveXCUIPanelCanvasChildId(request), "XCUIPanelCanvasHost");
|
||||||
|
|
||||||
|
request.childId = "CanvasHost";
|
||||||
|
EXPECT_STREQ(ResolveXCUIPanelCanvasChildId(request, "FallbackCanvas"), "CanvasHost");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUIPanelCanvasHostTest, PassiveSessionClampsRequestGeometryIntoSafeDefaultState) {
|
||||||
|
XCUIPanelCanvasRequest request = {};
|
||||||
|
request.height = -18.0f;
|
||||||
|
request.topInset = 42.0f;
|
||||||
|
|
||||||
|
XCUIPanelCanvasSession session = BuildPassiveXCUIPanelCanvasSession(request);
|
||||||
|
EXPECT_FALSE(session.validCanvas);
|
||||||
|
EXPECT_FALSE(session.hovered);
|
||||||
|
EXPECT_FALSE(session.windowFocused);
|
||||||
|
EXPECT_FLOAT_EQ(session.hostRect.width, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.hostRect.height, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.canvasRect.y, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.canvasRect.height, 0.0f);
|
||||||
|
|
||||||
|
request.height = 120.0f;
|
||||||
|
request.topInset = 180.0f;
|
||||||
|
session = BuildPassiveXCUIPanelCanvasSession(request);
|
||||||
|
EXPECT_FLOAT_EQ(session.hostRect.height, 120.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.canvasRect.y, 120.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.canvasRect.height, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(NewEditorXCUIPanelCanvasHostTest, NullHostBeginCanvasReturnsSafePassiveSessionAndDrawCallsAreNoops) {
|
||||||
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateNullXCUIPanelCanvasHost();
|
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateNullXCUIPanelCanvasHost();
|
||||||
ASSERT_NE(host, nullptr);
|
ASSERT_NE(host, nullptr);
|
||||||
|
|
||||||
@@ -43,9 +79,12 @@ TEST(NewEditorXCUIPanelCanvasHostTest, NullHostBeginCanvasReturnsEmptySessionAnd
|
|||||||
EXPECT_FALSE(session.hovered);
|
EXPECT_FALSE(session.hovered);
|
||||||
EXPECT_FALSE(session.windowFocused);
|
EXPECT_FALSE(session.windowFocused);
|
||||||
EXPECT_FLOAT_EQ(session.hostRect.width, 0.0f);
|
EXPECT_FLOAT_EQ(session.hostRect.width, 0.0f);
|
||||||
EXPECT_FLOAT_EQ(session.hostRect.height, 0.0f);
|
EXPECT_FLOAT_EQ(session.hostRect.height, 280.0f);
|
||||||
EXPECT_FLOAT_EQ(session.canvasRect.width, 0.0f);
|
EXPECT_FLOAT_EQ(session.canvasRect.width, 0.0f);
|
||||||
EXPECT_FLOAT_EQ(session.canvasRect.height, 0.0f);
|
EXPECT_FLOAT_EQ(session.canvasRect.y, 24.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.canvasRect.height, 256.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.pointerPosition.x, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(session.pointerPosition.y, 0.0f);
|
||||||
|
|
||||||
host->DrawFilledRect(
|
host->DrawFilledRect(
|
||||||
XCEngine::UI::UIRect(10.0f, 12.0f, 48.0f, 64.0f),
|
XCEngine::UI::UIRect(10.0f, 12.0f, 48.0f, 64.0f),
|
||||||
@@ -62,6 +101,11 @@ TEST(NewEditorXCUIPanelCanvasHostTest, NullHostBeginCanvasReturnsEmptySessionAnd
|
|||||||
XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f),
|
XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f),
|
||||||
16.0f);
|
16.0f);
|
||||||
host->EndCanvas();
|
host->EndCanvas();
|
||||||
|
|
||||||
|
const XCUIPanelCanvasSession secondSession = host->BeginCanvas({});
|
||||||
|
EXPECT_FLOAT_EQ(secondSession.hostRect.height, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(secondSession.canvasRect.height, 0.0f);
|
||||||
|
host->EndCanvas();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds;
|
using XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIShellCommandDescriptor;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIShellChromeState;
|
using XCEngine::Editor::XCUIBackend::XCUIShellChromeState;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewMode;
|
using XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewMode;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewState;
|
using XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewState;
|
||||||
|
using XCEngine::Editor::XCUIBackend::XCUIShellMenuItemKind;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
using XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
||||||
using XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
using XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
||||||
|
|
||||||
@@ -33,7 +35,7 @@ TEST(XCUIShellChromeStateTest, DefaultsMatchCurrentShellChromeConfiguration) {
|
|||||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||||
XCUIShellHostedPreviewState::NativeOffscreen);
|
XCUIShellHostedPreviewState::NativeOffscreen);
|
||||||
EXPECT_TRUE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
EXPECT_TRUE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||||
EXPECT_FALSE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
EXPECT_FALSE(state.IsHostedPresenterPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||||
|
|
||||||
const auto* layoutLabPanel = state.TryGetPanelState(XCUIShellPanelId::XCUILayoutLab);
|
const auto* layoutLabPanel = state.TryGetPanelState(XCUIShellPanelId::XCUILayoutLab);
|
||||||
ASSERT_NE(layoutLabPanel, nullptr);
|
ASSERT_NE(layoutLabPanel, nullptr);
|
||||||
@@ -42,12 +44,12 @@ TEST(XCUIShellChromeStateTest, DefaultsMatchCurrentShellChromeConfiguration) {
|
|||||||
EXPECT_EQ(layoutLabPanel->previewDebugSource, "new_editor.panels.xcui_layout_lab");
|
EXPECT_EQ(layoutLabPanel->previewDebugSource, "new_editor.panels.xcui_layout_lab");
|
||||||
EXPECT_TRUE(layoutLabPanel->visible);
|
EXPECT_TRUE(layoutLabPanel->visible);
|
||||||
EXPECT_TRUE(layoutLabPanel->hostedPreviewEnabled);
|
EXPECT_TRUE(layoutLabPanel->hostedPreviewEnabled);
|
||||||
EXPECT_EQ(layoutLabPanel->previewMode, XCUIShellHostedPreviewMode::LegacyImGui);
|
EXPECT_EQ(layoutLabPanel->previewMode, XCUIShellHostedPreviewMode::HostedPresenter);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUILayoutLab),
|
state.GetHostedPreviewState(XCUIShellPanelId::XCUILayoutLab),
|
||||||
XCUIShellHostedPreviewState::LegacyImGui);
|
XCUIShellHostedPreviewState::HostedPresenter);
|
||||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab));
|
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab));
|
||||||
EXPECT_TRUE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab));
|
EXPECT_TRUE(state.IsHostedPresenterPreviewActive(XCUIShellPanelId::XCUILayoutLab));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(XCUIShellChromeStateTest, PanelVisibilityAndPreviewModeMutatorsTrackStateChanges) {
|
TEST(XCUIShellChromeStateTest, PanelVisibilityAndPreviewModeMutatorsTrackStateChanges) {
|
||||||
@@ -64,7 +66,7 @@ TEST(XCUIShellChromeStateTest, PanelVisibilityAndPreviewModeMutatorsTrackStateCh
|
|||||||
EXPECT_FALSE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUILayoutLab, false));
|
EXPECT_FALSE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUILayoutLab, false));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
XCUIShellHostedPreviewMode::HostedPresenter);
|
||||||
|
|
||||||
EXPECT_TRUE(state.ToggleHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab));
|
EXPECT_TRUE(state.ToggleHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@@ -72,13 +74,13 @@ TEST(XCUIShellChromeStateTest, PanelVisibilityAndPreviewModeMutatorsTrackStateCh
|
|||||||
XCUIShellHostedPreviewMode::NativeOffscreen);
|
XCUIShellHostedPreviewMode::NativeOffscreen);
|
||||||
EXPECT_TRUE(state.SetHostedPreviewMode(
|
EXPECT_TRUE(state.SetHostedPreviewMode(
|
||||||
XCUIShellPanelId::XCUILayoutLab,
|
XCUIShellPanelId::XCUILayoutLab,
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui));
|
XCUIShellHostedPreviewMode::HostedPresenter));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
XCUIShellHostedPreviewMode::HostedPresenter);
|
||||||
EXPECT_FALSE(state.SetHostedPreviewMode(
|
EXPECT_FALSE(state.SetHostedPreviewMode(
|
||||||
XCUIShellPanelId::XCUILayoutLab,
|
XCUIShellPanelId::XCUILayoutLab,
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui));
|
XCUIShellHostedPreviewMode::HostedPresenter));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(XCUIShellChromeStateTest, HostedPreviewStateSeparatesEnablementFromRequestedMode) {
|
TEST(XCUIShellChromeStateTest, HostedPreviewStateSeparatesEnablementFromRequestedMode) {
|
||||||
@@ -93,14 +95,14 @@ TEST(XCUIShellChromeStateTest, HostedPreviewStateSeparatesEnablementFromRequeste
|
|||||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||||
XCUIShellHostedPreviewState::Disabled);
|
XCUIShellHostedPreviewState::Disabled);
|
||||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||||
EXPECT_FALSE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
EXPECT_FALSE(state.IsHostedPresenterPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||||
|
|
||||||
EXPECT_TRUE(state.SetHostedPreviewMode(
|
EXPECT_TRUE(state.SetHostedPreviewMode(
|
||||||
XCUIShellPanelId::XCUIDemo,
|
XCUIShellPanelId::XCUIDemo,
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui));
|
XCUIShellHostedPreviewMode::HostedPresenter));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUIDemo),
|
state.GetHostedPreviewMode(XCUIShellPanelId::XCUIDemo),
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
XCUIShellHostedPreviewMode::HostedPresenter);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||||
XCUIShellHostedPreviewState::Disabled);
|
XCUIShellHostedPreviewState::Disabled);
|
||||||
@@ -108,9 +110,9 @@ TEST(XCUIShellChromeStateTest, HostedPreviewStateSeparatesEnablementFromRequeste
|
|||||||
EXPECT_TRUE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUIDemo, true));
|
EXPECT_TRUE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUIDemo, true));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||||
XCUIShellHostedPreviewState::LegacyImGui);
|
XCUIShellHostedPreviewState::HostedPresenter);
|
||||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||||
EXPECT_TRUE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
EXPECT_TRUE(state.IsHostedPresenterPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(XCUIShellChromeStateTest, ViewToggleMutatorsOnlyFlipRequestedFlags) {
|
TEST(XCUIShellChromeStateTest, ViewToggleMutatorsOnlyFlipRequestedFlags) {
|
||||||
@@ -148,11 +150,115 @@ TEST(XCUIShellChromeStateTest, CommandInterfaceTogglesShellViewAndPreviewStates)
|
|||||||
EXPECT_TRUE(state.InvokeCommand(XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview));
|
EXPECT_TRUE(state.InvokeCommand(XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
XCUIShellHostedPreviewMode::HostedPresenter);
|
||||||
|
|
||||||
EXPECT_FALSE(state.InvokeCommand("new_editor.view.unknown"));
|
EXPECT_FALSE(state.InvokeCommand("new_editor.view.unknown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(XCUIShellChromeStateTest, CommandDescriptorsMatchCurrentShellMenuLabelsShortcutsAndCheckedState) {
|
||||||
|
XCUIShellChromeState state = {};
|
||||||
|
XCUIShellCommandDescriptor descriptor = {};
|
||||||
|
|
||||||
|
ASSERT_TRUE(state.TryGetCommandDescriptor(XCUIShellChromeCommandIds::ToggleXCUIDemoPanel, descriptor));
|
||||||
|
EXPECT_EQ(descriptor.label, "XCUI Demo");
|
||||||
|
EXPECT_EQ(descriptor.shortcut, "Ctrl+1");
|
||||||
|
EXPECT_EQ(descriptor.commandId, XCUIShellChromeCommandIds::ToggleXCUIDemoPanel);
|
||||||
|
EXPECT_TRUE(descriptor.checkable);
|
||||||
|
EXPECT_TRUE(descriptor.checked);
|
||||||
|
EXPECT_TRUE(descriptor.enabled);
|
||||||
|
|
||||||
|
ASSERT_TRUE(state.TryGetCommandDescriptor(XCUIShellChromeCommandIds::ToggleHostedPreviewHud, descriptor));
|
||||||
|
EXPECT_EQ(descriptor.label, "Hosted Preview HUD");
|
||||||
|
EXPECT_EQ(descriptor.shortcut, "Ctrl+Shift+H");
|
||||||
|
EXPECT_TRUE(descriptor.checked);
|
||||||
|
|
||||||
|
ASSERT_TRUE(state.TryGetCommandDescriptor(XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview, descriptor));
|
||||||
|
EXPECT_EQ(descriptor.label, "Native Layout Lab Preview");
|
||||||
|
EXPECT_EQ(descriptor.shortcut, "Ctrl+Alt+2");
|
||||||
|
EXPECT_FALSE(descriptor.checked);
|
||||||
|
|
||||||
|
EXPECT_FALSE(state.TryGetCommandDescriptor("new_editor.view.unknown", descriptor));
|
||||||
|
EXPECT_TRUE(descriptor.label.empty());
|
||||||
|
EXPECT_TRUE(descriptor.shortcut.empty());
|
||||||
|
EXPECT_TRUE(descriptor.commandId.empty());
|
||||||
|
EXPECT_FALSE(descriptor.checked);
|
||||||
|
EXPECT_FALSE(descriptor.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(XCUIShellChromeStateTest, ViewMenuDescriptorMatchesCurrentApplicationOrderingAndSeparators) {
|
||||||
|
XCUIShellChromeState state = {};
|
||||||
|
|
||||||
|
const auto menu = state.BuildViewMenuDescriptor();
|
||||||
|
ASSERT_EQ(menu.label, "View");
|
||||||
|
ASSERT_EQ(menu.items.size(), 10u);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[0].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[0].command.label, "XCUI Demo");
|
||||||
|
EXPECT_EQ(menu.items[0].command.shortcut, "Ctrl+1");
|
||||||
|
EXPECT_EQ(menu.items[0].command.commandId, XCUIShellChromeCommandIds::ToggleXCUIDemoPanel);
|
||||||
|
EXPECT_TRUE(menu.items[0].command.checked);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[1].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[1].command.label, "XCUI Layout Lab");
|
||||||
|
EXPECT_EQ(menu.items[1].command.shortcut, "Ctrl+2");
|
||||||
|
EXPECT_EQ(menu.items[1].command.commandId, XCUIShellChromeCommandIds::ToggleXCUILayoutLabPanel);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[2].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[2].command.label, "ImGui Demo");
|
||||||
|
EXPECT_EQ(menu.items[2].command.shortcut, "Ctrl+3");
|
||||||
|
EXPECT_EQ(menu.items[2].command.commandId, XCUIShellChromeCommandIds::ToggleImGuiDemoWindow);
|
||||||
|
|
||||||
|
EXPECT_EQ(menu.items[3].kind, XCUIShellMenuItemKind::Separator);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[4].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[4].command.label, "Native Backdrop");
|
||||||
|
EXPECT_EQ(menu.items[4].command.shortcut, "Ctrl+Shift+B");
|
||||||
|
EXPECT_EQ(menu.items[4].command.commandId, XCUIShellChromeCommandIds::ToggleNativeBackdrop);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[5].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[5].command.label, "Pulse Accent");
|
||||||
|
EXPECT_EQ(menu.items[5].command.shortcut, "Ctrl+Shift+P");
|
||||||
|
EXPECT_EQ(menu.items[5].command.commandId, XCUIShellChromeCommandIds::TogglePulseAccent);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[6].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[6].command.label, "Native XCUI Overlay");
|
||||||
|
EXPECT_EQ(menu.items[6].command.shortcut, "Ctrl+Shift+O");
|
||||||
|
EXPECT_EQ(menu.items[6].command.commandId, XCUIShellChromeCommandIds::ToggleNativeXCUIOverlay);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[7].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[7].command.label, "Hosted Preview HUD");
|
||||||
|
EXPECT_EQ(menu.items[7].command.shortcut, "Ctrl+Shift+H");
|
||||||
|
EXPECT_EQ(menu.items[7].command.commandId, XCUIShellChromeCommandIds::ToggleHostedPreviewHud);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[8].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[8].command.label, "Native Demo Panel Preview");
|
||||||
|
EXPECT_EQ(menu.items[8].command.shortcut, "Ctrl+Alt+1");
|
||||||
|
EXPECT_EQ(menu.items[8].command.commandId, XCUIShellChromeCommandIds::ToggleNativeDemoPanelPreview);
|
||||||
|
|
||||||
|
ASSERT_EQ(menu.items[9].kind, XCUIShellMenuItemKind::Command);
|
||||||
|
EXPECT_EQ(menu.items[9].command.label, "Native Layout Lab Preview");
|
||||||
|
EXPECT_EQ(menu.items[9].command.shortcut, "Ctrl+Alt+2");
|
||||||
|
EXPECT_EQ(menu.items[9].command.commandId, XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(XCUIShellChromeStateTest, ViewMenuDescriptorCheckedStateTracksShellStateChanges) {
|
||||||
|
XCUIShellChromeState state = {};
|
||||||
|
|
||||||
|
EXPECT_TRUE(state.SetPanelVisible(XCUIShellPanelId::XCUIDemo, false));
|
||||||
|
EXPECT_TRUE(state.SetViewToggle(XCUIShellViewToggleId::HostedPreviewHud, false));
|
||||||
|
EXPECT_TRUE(state.SetHostedPreviewMode(
|
||||||
|
XCUIShellPanelId::XCUILayoutLab,
|
||||||
|
XCUIShellHostedPreviewMode::NativeOffscreen));
|
||||||
|
EXPECT_TRUE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUIDemo, false));
|
||||||
|
|
||||||
|
const auto menu = state.BuildViewMenuDescriptor();
|
||||||
|
|
||||||
|
EXPECT_FALSE(menu.items[0].command.checked);
|
||||||
|
EXPECT_FALSE(menu.items[7].command.checked);
|
||||||
|
EXPECT_FALSE(menu.items[8].command.checked);
|
||||||
|
EXPECT_TRUE(menu.items[9].command.checked);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(XCUIShellChromeStateTest, PanelCommandIdHelpersMatchCurrentShellCommands) {
|
TEST(XCUIShellChromeStateTest, PanelCommandIdHelpersMatchCurrentShellCommands) {
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId::XCUIDemo),
|
XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId::XCUIDemo),
|
||||||
@@ -200,12 +306,12 @@ TEST(XCUIShellChromeStateTest, InvalidPanelAndToggleIdsFailGracefully) {
|
|||||||
EXPECT_FALSE(state.SetHostedPreviewEnabled(invalidPanelId, false));
|
EXPECT_FALSE(state.SetHostedPreviewEnabled(invalidPanelId, false));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewMode(invalidPanelId),
|
state.GetHostedPreviewMode(invalidPanelId),
|
||||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
XCUIShellHostedPreviewMode::HostedPresenter);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
state.GetHostedPreviewState(invalidPanelId),
|
state.GetHostedPreviewState(invalidPanelId),
|
||||||
XCUIShellHostedPreviewState::Disabled);
|
XCUIShellHostedPreviewState::Disabled);
|
||||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(invalidPanelId));
|
EXPECT_FALSE(state.IsNativeHostedPreviewActive(invalidPanelId));
|
||||||
EXPECT_FALSE(state.IsLegacyHostedPreviewActive(invalidPanelId));
|
EXPECT_FALSE(state.IsHostedPresenterPreviewActive(invalidPanelId));
|
||||||
EXPECT_FALSE(state.SetHostedPreviewMode(invalidPanelId, XCUIShellHostedPreviewMode::NativeOffscreen));
|
EXPECT_FALSE(state.SetHostedPreviewMode(invalidPanelId, XCUIShellHostedPreviewMode::NativeOffscreen));
|
||||||
EXPECT_FALSE(state.ToggleHostedPreviewMode(invalidPanelId));
|
EXPECT_FALSE(state.ToggleHostedPreviewMode(invalidPanelId));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user