Integrate XCUI shell state and runtime frame seams
This commit is contained in:
@@ -40,6 +40,15 @@ set(NEW_EDITOR_LAYOUT_LAB_RUNTIME_HEADER
|
||||
set(NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUILayoutLabRuntime.cpp
|
||||
)
|
||||
set(NEW_EDITOR_LAYOUT_LAB_PANEL_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/panels/XCUILayoutLabPanel.h
|
||||
)
|
||||
set(NEW_EDITOR_LAYOUT_LAB_PANEL_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/panels/XCUILayoutLabPanel.cpp
|
||||
)
|
||||
set(NEW_EDITOR_BASE_PANEL_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/panels/Panel.cpp
|
||||
)
|
||||
set(NEW_EDITOR_ASSET_DOCUMENT_SOURCE_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIAssetDocumentSource.h
|
||||
)
|
||||
@@ -64,6 +73,15 @@ set(NEW_EDITOR_COMMAND_ROUTER_HEADER
|
||||
set(NEW_EDITOR_COMMAND_ROUTER_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIEditorCommandRouter.cpp
|
||||
)
|
||||
set(NEW_EDITOR_SHELL_CHROME_STATE_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIShellChromeState.h
|
||||
)
|
||||
set(NEW_EDITOR_SHELL_CHROME_STATE_SOURCE
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIShellChromeState.cpp
|
||||
)
|
||||
set(NEW_EDITOR_APPLICATION_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/Application.h
|
||||
)
|
||||
set(NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/ImGuiXCUIInputAdapter.h
|
||||
)
|
||||
@@ -213,6 +231,52 @@ else()
|
||||
message(STATUS "Skipping new_editor_xcui_layout_lab_runtime_tests because XCUILayoutLabRuntime files are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_LAYOUT_LAB_PANEL_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_LAYOUT_LAB_PANEL_SOURCE}" AND
|
||||
EXISTS "${NEW_EDITOR_LAYOUT_LAB_RUNTIME_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE}" AND
|
||||
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_ASSET_DOCUMENT_SOURCE}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_layout_lab_panel.cpp" AND
|
||||
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||
add_executable(new_editor_xcui_layout_lab_panel_tests
|
||||
test_xcui_layout_lab_panel.cpp
|
||||
${NEW_EDITOR_LAYOUT_LAB_PANEL_SOURCE}
|
||||
${NEW_EDITOR_BASE_PANEL_SOURCE}
|
||||
${NEW_EDITOR_LAYOUT_LAB_RUNTIME_SOURCE}
|
||||
${NEW_EDITOR_ASSET_DOCUMENT_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_layout_lab_panel_tests)
|
||||
|
||||
target_link_libraries(new_editor_xcui_layout_lab_panel_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
user32
|
||||
comdlg32
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_xcui_layout_lab_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_layout_lab_panel_tests PRIVATE
|
||||
XCENGINE_NEW_EDITOR_REPO_ROOT="${XCENGINE_TEST_REPO_ROOT_CMAKE}"
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_xcui_layout_lab_panel_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_xcui_layout_lab_panel_tests because panel, runtime, test, or ImGui sources are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_BACKEND_HEADER}" AND EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||
add_executable(new_editor_imgui_transition_backend_tests
|
||||
test_new_editor_imgui_transition_backend.cpp
|
||||
@@ -388,6 +452,63 @@ else()
|
||||
message(STATUS "Skipping new_editor_xcui_editor_command_router_tests because command router files or the test source are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_SHELL_CHROME_STATE_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_SHELL_CHROME_STATE_SOURCE}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_shell_chrome_state.cpp")
|
||||
add_executable(new_editor_xcui_shell_chrome_state_tests
|
||||
test_xcui_shell_chrome_state.cpp
|
||||
${NEW_EDITOR_SHELL_CHROME_STATE_SOURCE}
|
||||
)
|
||||
|
||||
xcengine_configure_new_editor_test_target(new_editor_xcui_shell_chrome_state_tests)
|
||||
|
||||
target_link_libraries(new_editor_xcui_shell_chrome_state_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_xcui_shell_chrome_state_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_xcui_shell_chrome_state_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_xcui_shell_chrome_state_tests because shell chrome state files or the test source are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_APPLICATION_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_COMMAND_ROUTER_SOURCE}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_application_shell_command_bindings.cpp")
|
||||
add_executable(new_editor_application_shell_command_bindings_tests
|
||||
test_application_shell_command_bindings.cpp
|
||||
${NEW_EDITOR_COMMAND_ROUTER_SOURCE}
|
||||
)
|
||||
|
||||
xcengine_configure_new_editor_test_target(new_editor_application_shell_command_bindings_tests)
|
||||
|
||||
target_link_libraries(new_editor_application_shell_command_bindings_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_application_shell_command_bindings_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
${CMAKE_SOURCE_DIR}/editor/src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/backends
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_application_shell_command_bindings_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_application_shell_command_bindings_tests because Application header, command router source, or the test source are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_HEADER}" AND
|
||||
EXISTS "${NEW_EDITOR_IMGUI_INPUT_ADAPTER_SOURCE}" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_imgui_xcui_input_adapter.cpp" AND
|
||||
@@ -576,3 +697,63 @@ if(EXISTS "${NEW_EDITOR_RHI_COMMAND_COMPILER_HEADER}" AND
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_xcui_rhi_command_compiler_tests because compiler files are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/XCUIPanelCanvasHost.h" AND
|
||||
EXISTS "${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/NullXCUIPanelCanvasHost.h" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_xcui_panel_canvas_host.cpp")
|
||||
add_executable(new_editor_xcui_panel_canvas_host_tests
|
||||
test_xcui_panel_canvas_host.cpp
|
||||
)
|
||||
|
||||
xcengine_configure_new_editor_test_target(new_editor_xcui_panel_canvas_host_tests)
|
||||
|
||||
target_link_libraries(new_editor_xcui_panel_canvas_host_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_xcui_panel_canvas_host_tests PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_xcui_panel_canvas_host_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_xcui_panel_canvas_host_tests because panel canvas host headers or the test source are missing.")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/new_editor/src/XCUIBackend/ImGuiXCUIPanelCanvasHost.h" AND
|
||||
EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test_imgui_xcui_panel_canvas_host.cpp" AND
|
||||
EXISTS "${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui.cpp")
|
||||
add_executable(new_editor_imgui_xcui_panel_canvas_host_tests
|
||||
test_imgui_xcui_panel_canvas_host.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_tables.cpp
|
||||
${CMAKE_BINARY_DIR}/_deps/imgui-src/imgui_widgets.cpp
|
||||
)
|
||||
|
||||
xcengine_configure_new_editor_test_target(new_editor_imgui_xcui_panel_canvas_host_tests)
|
||||
|
||||
target_link_libraries(new_editor_imgui_xcui_panel_canvas_host_tests
|
||||
PRIVATE
|
||||
XCEngine
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
user32
|
||||
comdlg32
|
||||
)
|
||||
|
||||
target_include_directories(new_editor_imgui_xcui_panel_canvas_host_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
|
||||
)
|
||||
|
||||
xcengine_discover_new_editor_gtests(new_editor_imgui_xcui_panel_canvas_host_tests)
|
||||
else()
|
||||
message(STATUS "Skipping new_editor_imgui_xcui_panel_canvas_host_tests because the ImGui host header, test source, or ImGui sources are missing.")
|
||||
endif()
|
||||
|
||||
250
tests/NewEditor/test_application_shell_command_bindings.cpp
Normal file
250
tests/NewEditor/test_application_shell_command_bindings.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
#include "Application.h"
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Editor::XCUIBackend::XCUIEditorCommandRouter;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta;
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::NewEditor::Application;
|
||||
|
||||
constexpr std::size_t ToPanelIndex(Application::ShellPanelId panelId) {
|
||||
return static_cast<std::size_t>(panelId);
|
||||
}
|
||||
|
||||
struct ShellCommandHarness {
|
||||
Application::ShellViewToggleState viewToggles = {};
|
||||
std::array<Application::ShellPanelChromeState, static_cast<std::size_t>(Application::ShellPanelId::Count)>
|
||||
panels = {};
|
||||
int hostedPreviewReconfigureCount = 0;
|
||||
|
||||
ShellCommandHarness() {
|
||||
panels[ToPanelIndex(Application::ShellPanelId::XCUIDemo)] = {
|
||||
Application::ShellPanelId::XCUIDemo,
|
||||
"XCUI Demo",
|
||||
"XCUI Demo",
|
||||
"new_editor.panels.xcui_demo",
|
||||
true,
|
||||
true,
|
||||
Application::ShellHostedPreviewMode::NativeOffscreen
|
||||
};
|
||||
panels[ToPanelIndex(Application::ShellPanelId::XCUILayoutLab)] = {
|
||||
Application::ShellPanelId::XCUILayoutLab,
|
||||
"XCUI Layout Lab",
|
||||
"XCUI Layout Lab",
|
||||
"new_editor.panels.xcui_layout_lab",
|
||||
true,
|
||||
true,
|
||||
Application::ShellHostedPreviewMode::LegacyImGui
|
||||
};
|
||||
}
|
||||
|
||||
Application::ShellPanelChromeState& Panel(Application::ShellPanelId panelId) {
|
||||
return panels[ToPanelIndex(panelId)];
|
||||
}
|
||||
|
||||
const Application::ShellPanelChromeState& Panel(Application::ShellPanelId panelId) const {
|
||||
return panels[ToPanelIndex(panelId)];
|
||||
}
|
||||
|
||||
Application::ShellCommandBindings BuildBindings() {
|
||||
Application::ShellCommandBindings bindings = {};
|
||||
bindings.getXCUIDemoPanelVisible = [this]() { return Panel(Application::ShellPanelId::XCUIDemo).visible; };
|
||||
bindings.setXCUIDemoPanelVisible = [this](bool visible) {
|
||||
Panel(Application::ShellPanelId::XCUIDemo).visible = visible;
|
||||
};
|
||||
bindings.getXCUILayoutLabPanelVisible = [this]() {
|
||||
return Panel(Application::ShellPanelId::XCUILayoutLab).visible;
|
||||
};
|
||||
bindings.setXCUILayoutLabPanelVisible = [this](bool visible) {
|
||||
Panel(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.getNativeDemoPanelPreviewEnabled = [this]() {
|
||||
return Panel(Application::ShellPanelId::XCUIDemo).previewMode ==
|
||||
Application::ShellHostedPreviewMode::NativeOffscreen;
|
||||
};
|
||||
bindings.setNativeDemoPanelPreviewEnabled = [this](bool enabled) {
|
||||
Panel(Application::ShellPanelId::XCUIDemo).previewMode =
|
||||
enabled
|
||||
? Application::ShellHostedPreviewMode::NativeOffscreen
|
||||
: Application::ShellHostedPreviewMode::LegacyImGui;
|
||||
};
|
||||
bindings.getNativeLayoutLabPreviewEnabled = [this]() {
|
||||
return Panel(Application::ShellPanelId::XCUILayoutLab).previewMode ==
|
||||
Application::ShellHostedPreviewMode::NativeOffscreen;
|
||||
};
|
||||
bindings.setNativeLayoutLabPreviewEnabled = [this](bool enabled) {
|
||||
Panel(Application::ShellPanelId::XCUILayoutLab).previewMode =
|
||||
enabled
|
||||
? Application::ShellHostedPreviewMode::NativeOffscreen
|
||||
: Application::ShellHostedPreviewMode::LegacyImGui;
|
||||
};
|
||||
bindings.onHostedPreviewModeChanged = [this]() { ++hostedPreviewReconfigureCount; };
|
||||
return bindings;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(ApplicationShellCommandBindingsTest, RegisterShellViewCommandsInvokesBoundToggleHandlers) {
|
||||
ShellCommandHarness harness = {};
|
||||
XCUIEditorCommandRouter router = {};
|
||||
|
||||
Application::RegisterShellViewCommands(router, harness.BuildBindings());
|
||||
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleXCUIDemoPanel));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleXCUILayoutLabPanel));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleImGuiDemoWindow));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleNativeBackdrop));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::TogglePulseAccent));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleNativeXCUIOverlay));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleHostedPreviewHud));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleNativeDemoPanelPreview));
|
||||
EXPECT_TRUE(router.HasCommand(Application::ShellCommandIds::ToggleNativeLayoutLabPreview));
|
||||
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleXCUIDemoPanel));
|
||||
EXPECT_FALSE(harness.Panel(Application::ShellPanelId::XCUIDemo).visible);
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleImGuiDemoWindow));
|
||||
EXPECT_TRUE(harness.viewToggles.imguiDemoWindowVisible);
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeBackdrop));
|
||||
EXPECT_FALSE(harness.viewToggles.nativeBackdropVisible);
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeXCUIOverlay));
|
||||
EXPECT_FALSE(harness.viewToggles.nativeXCUIOverlayVisible);
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleHostedPreviewHud));
|
||||
EXPECT_FALSE(harness.viewToggles.hostedPreviewHudVisible);
|
||||
}
|
||||
|
||||
TEST(ApplicationShellCommandBindingsTest, PreviewModeCommandsTriggerHostedPreviewReconfigureCallback) {
|
||||
ShellCommandHarness harness = {};
|
||||
XCUIEditorCommandRouter router = {};
|
||||
|
||||
Application::RegisterShellViewCommands(router, harness.BuildBindings());
|
||||
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeDemoPanelPreview));
|
||||
EXPECT_EQ(
|
||||
harness.Panel(Application::ShellPanelId::XCUIDemo).previewMode,
|
||||
Application::ShellHostedPreviewMode::LegacyImGui);
|
||||
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 1);
|
||||
|
||||
EXPECT_TRUE(router.InvokeCommand(Application::ShellCommandIds::ToggleNativeLayoutLabPreview));
|
||||
EXPECT_EQ(
|
||||
harness.Panel(Application::ShellPanelId::XCUILayoutLab).previewMode,
|
||||
Application::ShellHostedPreviewMode::NativeOffscreen);
|
||||
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 2);
|
||||
}
|
||||
|
||||
TEST(ApplicationShellCommandBindingsTest, BuildShellShortcutSnapshotCarriesBridgeStateAndKeyboardEdges) {
|
||||
XCUIInputBridgeFrameDelta frameDelta = {};
|
||||
frameDelta.state.windowFocused = true;
|
||||
frameDelta.state.wantCaptureKeyboard = true;
|
||||
frameDelta.state.wantTextInput = true;
|
||||
frameDelta.state.modifiers.control = true;
|
||||
frameDelta.state.modifiers.shift = true;
|
||||
frameDelta.keyboard.pressedKeys.push_back(static_cast<std::int32_t>(KeyCode::One));
|
||||
frameDelta.keyboard.repeatedKeys.push_back(static_cast<std::int32_t>(KeyCode::Two));
|
||||
|
||||
const auto snapshot = Application::BuildShellShortcutSnapshot(frameDelta);
|
||||
|
||||
EXPECT_TRUE(snapshot.windowFocused);
|
||||
EXPECT_TRUE(snapshot.wantCaptureKeyboard);
|
||||
EXPECT_TRUE(snapshot.wantTextInput);
|
||||
EXPECT_TRUE(snapshot.modifiers.control);
|
||||
EXPECT_TRUE(snapshot.modifiers.shift);
|
||||
EXPECT_TRUE(snapshot.IsKeyDown(static_cast<std::int32_t>(KeyCode::One)));
|
||||
EXPECT_TRUE(snapshot.IsKeyDown(static_cast<std::int32_t>(KeyCode::Two)));
|
||||
|
||||
const auto* repeatedKey = snapshot.FindKeyState(static_cast<std::int32_t>(KeyCode::Two));
|
||||
ASSERT_NE(repeatedKey, nullptr);
|
||||
EXPECT_TRUE(repeatedKey->repeat);
|
||||
}
|
||||
|
||||
TEST(ApplicationShellCommandBindingsTest, RegisteredShellShortcutsMatchExpectedViewCommands) {
|
||||
ShellCommandHarness harness = {};
|
||||
XCUIEditorCommandRouter router = {};
|
||||
Application::RegisterShellViewCommands(router, harness.BuildBindings());
|
||||
|
||||
XCUIInputBridgeFrameDelta frameDelta = {};
|
||||
frameDelta.state.windowFocused = true;
|
||||
frameDelta.state.modifiers.control = true;
|
||||
frameDelta.keyboard.pressedKeys.push_back(static_cast<std::int32_t>(KeyCode::One));
|
||||
|
||||
const auto demoSnapshot = Application::BuildShellShortcutSnapshot(frameDelta);
|
||||
const auto demoMatch = router.MatchShortcut({ &demoSnapshot });
|
||||
ASSERT_TRUE(demoMatch.matched);
|
||||
EXPECT_EQ(demoMatch.commandId, Application::ShellCommandIds::ToggleXCUIDemoPanel);
|
||||
|
||||
XCUIInputBridgeFrameDelta previewDelta = {};
|
||||
previewDelta.state.windowFocused = true;
|
||||
previewDelta.state.modifiers.control = true;
|
||||
previewDelta.state.modifiers.alt = true;
|
||||
previewDelta.keyboard.pressedKeys.push_back(static_cast<std::int32_t>(KeyCode::Two));
|
||||
|
||||
const auto previewSnapshot = Application::BuildShellShortcutSnapshot(previewDelta);
|
||||
const auto previewMatch = router.MatchShortcut({ &previewSnapshot });
|
||||
ASSERT_TRUE(previewMatch.matched);
|
||||
EXPECT_EQ(previewMatch.commandId, Application::ShellCommandIds::ToggleNativeLayoutLabPreview);
|
||||
}
|
||||
|
||||
TEST(ApplicationShellCommandBindingsTest, RegisteredShellShortcutsRespectCaptureAndRepeatGuards) {
|
||||
ShellCommandHarness harness = {};
|
||||
XCUIEditorCommandRouter router = {};
|
||||
Application::RegisterShellViewCommands(router, harness.BuildBindings());
|
||||
|
||||
XCUIInputBridgeFrameDelta capturedDelta = {};
|
||||
capturedDelta.state.windowFocused = true;
|
||||
capturedDelta.state.wantCaptureKeyboard = true;
|
||||
capturedDelta.state.modifiers.control = true;
|
||||
capturedDelta.keyboard.pressedKeys.push_back(static_cast<std::int32_t>(KeyCode::One));
|
||||
|
||||
const auto capturedSnapshot = Application::BuildShellShortcutSnapshot(capturedDelta);
|
||||
EXPECT_FALSE(router.MatchShortcut({ &capturedSnapshot }).matched);
|
||||
|
||||
XCUIInputBridgeFrameDelta textInputDelta = {};
|
||||
textInputDelta.state.windowFocused = true;
|
||||
textInputDelta.state.wantTextInput = true;
|
||||
textInputDelta.state.modifiers.control = true;
|
||||
textInputDelta.keyboard.pressedKeys.push_back(static_cast<std::int32_t>(KeyCode::One));
|
||||
|
||||
const auto textInputSnapshot = Application::BuildShellShortcutSnapshot(textInputDelta);
|
||||
EXPECT_FALSE(router.MatchShortcut({ &textInputSnapshot }).matched);
|
||||
|
||||
XCUIInputBridgeFrameDelta repeatedDelta = {};
|
||||
repeatedDelta.state.windowFocused = true;
|
||||
repeatedDelta.state.modifiers.control = true;
|
||||
repeatedDelta.keyboard.repeatedKeys.push_back(static_cast<std::int32_t>(KeyCode::One));
|
||||
|
||||
const auto repeatedSnapshot = Application::BuildShellShortcutSnapshot(repeatedDelta);
|
||||
EXPECT_FALSE(router.MatchShortcut({ &repeatedSnapshot }).matched);
|
||||
}
|
||||
|
||||
TEST(ApplicationShellCommandBindingsTest, PreviewShortcutInvokesCommandHandlerAndReconfigureCallback) {
|
||||
ShellCommandHarness harness = {};
|
||||
XCUIEditorCommandRouter router = {};
|
||||
Application::RegisterShellViewCommands(router, harness.BuildBindings());
|
||||
|
||||
XCUIInputBridgeFrameDelta previewDelta = {};
|
||||
previewDelta.state.windowFocused = true;
|
||||
previewDelta.state.modifiers.control = true;
|
||||
previewDelta.state.modifiers.alt = true;
|
||||
previewDelta.keyboard.pressedKeys.push_back(static_cast<std::int32_t>(KeyCode::One));
|
||||
|
||||
const auto previewSnapshot = Application::BuildShellShortcutSnapshot(previewDelta);
|
||||
EXPECT_TRUE(router.InvokeMatchingShortcut({ &previewSnapshot }));
|
||||
EXPECT_EQ(
|
||||
harness.Panel(Application::ShellPanelId::XCUIDemo).previewMode,
|
||||
Application::ShellHostedPreviewMode::LegacyImGui);
|
||||
EXPECT_EQ(harness.hostedPreviewReconfigureCount, 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
25
tests/NewEditor/test_imgui_xcui_panel_canvas_host.cpp
Normal file
25
tests/NewEditor/test_imgui_xcui_panel_canvas_host.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "XCUIBackend/ImGuiXCUIPanelCanvasHost.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Editor::XCUIBackend::CreateImGuiXCUIPanelCanvasHost;
|
||||
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
|
||||
|
||||
TEST(NewEditorImGuiXCUIPanelCanvasHostTest, ReportsExplicitBackendAndCapabilities) {
|
||||
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateImGuiXCUIPanelCanvasHost();
|
||||
ASSERT_NE(host, nullptr);
|
||||
|
||||
EXPECT_STREQ(host->GetDebugName(), "ImGuiXCUIPanelCanvasHost");
|
||||
EXPECT_EQ(host->GetBackend(), XCUIPanelCanvasHostBackend::ImGui);
|
||||
|
||||
const XCUIPanelCanvasHostCapabilities capabilities = host->GetCapabilities();
|
||||
EXPECT_TRUE(capabilities.supportsPointerHitTesting);
|
||||
EXPECT_TRUE(capabilities.supportsHostedSurfaceImages);
|
||||
EXPECT_TRUE(capabilities.supportsPrimitiveOverlays);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -56,6 +56,17 @@ UIInputEvent MakeKeyDownEvent(
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakePointerButtonEvent(
|
||||
UIInputEventType type,
|
||||
const XCEngine::UI::UIPoint& position,
|
||||
XCEngine::UI::UIPointerButton button = XCEngine::UI::UIPointerButton::Left) {
|
||||
UIInputEvent event = {};
|
||||
event.type = type;
|
||||
event.pointerButton = button;
|
||||
event.position = position;
|
||||
return event;
|
||||
}
|
||||
|
||||
fs::path FindDemoResourcePath() {
|
||||
fs::path probe = fs::current_path();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
@@ -263,6 +274,25 @@ TEST(NewEditorXCUIDemoRuntimeTest, DrainPendingCommandIdsCapturesPointerActivati
|
||||
EXPECT_TRUE(runtime.DrainPendingCommandIds().empty());
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUIDemoRuntimeTest, DrainPendingCommandIdsCapturesShortcutCommands) {
|
||||
XCEngine::Editor::XCUIBackend::XCUIDemoRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baselineFrame = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baselineFrame.stats.documentsReady);
|
||||
EXPECT_TRUE(runtime.DrainPendingCommandIds().empty());
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUIDemoInputState shortcutInput = BuildInputState();
|
||||
shortcutInput.events.push_back(MakeKeyDownEvent(XCEngine::Input::KeyCode::P, false, false, true));
|
||||
const auto& shortcutFrame = runtime.Update(shortcutInput);
|
||||
|
||||
ASSERT_TRUE(shortcutFrame.stats.documentsReady);
|
||||
EXPECT_TRUE(shortcutFrame.stats.accentEnabled);
|
||||
EXPECT_EQ(shortcutFrame.stats.lastCommandId, "demo.toggleAccent");
|
||||
EXPECT_EQ(runtime.DrainPendingCommandIds(), std::vector<std::string>({ "demo.toggleAccent" }));
|
||||
EXPECT_TRUE(runtime.DrainPendingCommandIds().empty());
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUIDemoRuntimeTest, DrainPendingCommandIdsPreservesMultipleTextEditCommandsPerFrame) {
|
||||
XCEngine::Editor::XCUIBackend::XCUIDemoRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
@@ -313,6 +343,43 @@ TEST(NewEditorXCUIDemoRuntimeTest, DrainPendingCommandIdsPreservesMultipleTextEd
|
||||
EXPECT_TRUE(runtime.DrainPendingCommandIds().empty());
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUIDemoRuntimeTest, DrainPendingCommandIdsPreserveMixedPointerTextAndShortcutOrder) {
|
||||
XCEngine::Editor::XCUIBackend::XCUIDemoRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baselineFrame = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baselineFrame.stats.documentsReady);
|
||||
EXPECT_TRUE(runtime.DrainPendingCommandIds().empty());
|
||||
|
||||
XCEngine::UI::UIRect promptRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("agentPrompt", promptRect));
|
||||
|
||||
const XCEngine::UI::UIPoint promptCenter(
|
||||
promptRect.x + promptRect.width * 0.5f,
|
||||
promptRect.y + promptRect.height * 0.5f);
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUIDemoInputState mixedInput = BuildInputState();
|
||||
mixedInput.pointerPosition = promptCenter;
|
||||
mixedInput.events.push_back(MakePointerButtonEvent(UIInputEventType::PointerButtonDown, promptCenter));
|
||||
mixedInput.events.push_back(MakePointerButtonEvent(UIInputEventType::PointerButtonUp, promptCenter));
|
||||
mixedInput.events.push_back(MakeCharacterEvent('A'));
|
||||
mixedInput.events.push_back(MakeKeyDownEvent(XCEngine::Input::KeyCode::P, false, false, true));
|
||||
const auto& mixedFrame = runtime.Update(mixedInput);
|
||||
|
||||
ASSERT_TRUE(mixedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(mixedFrame.stats.focusedElementId, "agentPrompt");
|
||||
EXPECT_TRUE(mixedFrame.stats.accentEnabled);
|
||||
EXPECT_EQ(mixedFrame.stats.lastCommandId, "demo.toggleAccent");
|
||||
EXPECT_NE(FindTextCommand(mixedFrame.drawData, "A"), nullptr);
|
||||
EXPECT_EQ(
|
||||
runtime.DrainPendingCommandIds(),
|
||||
std::vector<std::string>({
|
||||
"demo.activate.agentPrompt",
|
||||
"demo.text.edit.agentPrompt",
|
||||
"demo.toggleAccent" }));
|
||||
EXPECT_TRUE(runtime.DrainPendingCommandIds().empty());
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUIDemoRuntimeTest, PointerToggleUpdatesFocusStatusTextAndAccentState) {
|
||||
XCEngine::Editor::XCUIBackend::XCUIDemoRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace {
|
||||
|
||||
using XCEngine::Editor::XCUIBackend::CreateImGuiXCUIHostedPreviewPresenter;
|
||||
using XCEngine::Editor::XCUIBackend::CreateQueuedNativeXCUIHostedPreviewPresenter;
|
||||
using XCEngine::Editor::XCUIBackend::IImGuiXCUIHostedPreviewTargetBinding;
|
||||
using XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewFrame;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIHostedPreviewDrainStats;
|
||||
@@ -36,6 +37,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class RecordingImGuiHostedPreviewTargetBinding final : public IImGuiXCUIHostedPreviewTargetBinding {
|
||||
public:
|
||||
ImDrawList* ResolveTargetDrawList(const XCUIHostedPreviewFrame& frame) const override {
|
||||
++resolveCallCount;
|
||||
lastFrame = &frame;
|
||||
return resolvedDrawList;
|
||||
}
|
||||
|
||||
mutable std::size_t resolveCallCount = 0u;
|
||||
mutable const XCUIHostedPreviewFrame* lastFrame = nullptr;
|
||||
ImDrawList* resolvedDrawList = nullptr;
|
||||
};
|
||||
|
||||
void PrepareImGui(float width = 1024.0f, float height = 768.0f) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2(width, height);
|
||||
@@ -78,13 +92,10 @@ TEST(XCUIHostedPreviewPresenterTest, PresentReturnsFalseAndClearsStatsWhenFrameH
|
||||
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||
}
|
||||
|
||||
TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoProvidedImGuiDrawList) {
|
||||
TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoExplicitBindingResolvedImGuiDrawList) {
|
||||
ImGuiContextScope contextScope;
|
||||
PrepareImGui(800.0f, 600.0f);
|
||||
|
||||
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter = CreateImGuiXCUIHostedPreviewPresenter();
|
||||
ASSERT_NE(presenter, nullptr);
|
||||
|
||||
XCEngine::UI::UIDrawData drawData = {};
|
||||
XCEngine::UI::UIDrawList& drawList = drawData.EmplaceDrawList("HostedPreview");
|
||||
drawList.AddFilledRect(
|
||||
@@ -101,6 +112,15 @@ TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoProvidedImGuiDraw
|
||||
ImDrawList* targetDrawList = ImGui::GetWindowDrawList();
|
||||
ASSERT_NE(targetDrawList, nullptr);
|
||||
|
||||
std::unique_ptr<RecordingImGuiHostedPreviewTargetBinding> targetBinding =
|
||||
std::make_unique<RecordingImGuiHostedPreviewTargetBinding>();
|
||||
RecordingImGuiHostedPreviewTargetBinding* targetBindingPtr = targetBinding.get();
|
||||
targetBindingPtr->resolvedDrawList = targetDrawList;
|
||||
|
||||
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter =
|
||||
CreateImGuiXCUIHostedPreviewPresenter(std::move(targetBinding));
|
||||
ASSERT_NE(presenter, nullptr);
|
||||
|
||||
XCUIHostedPreviewFrame frame = {};
|
||||
frame.drawData = &drawData;
|
||||
|
||||
@@ -116,6 +136,129 @@ TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoProvidedImGuiDraw
|
||||
EXPECT_EQ(stats.submittedCommandCount, 2u);
|
||||
EXPECT_EQ(stats.flushedDrawListCount, 1u);
|
||||
EXPECT_EQ(stats.flushedCommandCount, 2u);
|
||||
EXPECT_EQ(targetBindingPtr->resolveCallCount, 1u);
|
||||
EXPECT_EQ(targetBindingPtr->lastFrame, &frame);
|
||||
EXPECT_GT(targetDrawList->VtxBuffer.Size, 0);
|
||||
EXPECT_GT(targetDrawList->CmdBuffer.Size, 0);
|
||||
}
|
||||
|
||||
TEST(XCUIHostedPreviewPresenterTest, PresentReturnsFalseWhenExplicitBindingDoesNotResolveTargetDrawList) {
|
||||
ImGuiContextScope contextScope;
|
||||
PrepareImGui(800.0f, 600.0f);
|
||||
|
||||
XCEngine::UI::UIDrawData drawData = {};
|
||||
drawData.EmplaceDrawList("HostedPreviewMissingTarget").AddFilledRect(
|
||||
XCEngine::UI::UIRect(10.0f, 12.0f, 44.0f, 28.0f),
|
||||
XCEngine::UI::UIColor(0.9f, 0.3f, 0.2f, 1.0f));
|
||||
|
||||
std::unique_ptr<RecordingImGuiHostedPreviewTargetBinding> targetBinding =
|
||||
std::make_unique<RecordingImGuiHostedPreviewTargetBinding>();
|
||||
RecordingImGuiHostedPreviewTargetBinding* targetBindingPtr = targetBinding.get();
|
||||
|
||||
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter =
|
||||
CreateImGuiXCUIHostedPreviewPresenter(std::move(targetBinding));
|
||||
ASSERT_NE(presenter, nullptr);
|
||||
|
||||
XCUIHostedPreviewFrame frame = {};
|
||||
frame.drawData = &drawData;
|
||||
frame.debugName = "HostedPreviewMissingTarget";
|
||||
|
||||
const bool presented = presenter->Present(frame);
|
||||
const XCUIHostedPreviewStats& stats = presenter->GetLastStats();
|
||||
|
||||
EXPECT_FALSE(presented);
|
||||
EXPECT_FALSE(stats.presented);
|
||||
EXPECT_EQ(stats.submittedDrawListCount, 1u);
|
||||
EXPECT_EQ(stats.submittedCommandCount, 1u);
|
||||
EXPECT_EQ(stats.flushedDrawListCount, 0u);
|
||||
EXPECT_EQ(stats.flushedCommandCount, 0u);
|
||||
EXPECT_EQ(targetBindingPtr->resolveCallCount, 1u);
|
||||
EXPECT_EQ(targetBindingPtr->lastFrame, &frame);
|
||||
}
|
||||
|
||||
TEST(XCUIHostedPreviewPresenterTest, PresentFlushesDrawDataIntoExplicitBindingResolvedForegroundDrawListWithoutWindow) {
|
||||
ImGuiContextScope contextScope;
|
||||
PrepareImGui(800.0f, 600.0f);
|
||||
|
||||
XCEngine::UI::UIDrawData drawData = {};
|
||||
XCEngine::UI::UIDrawList& drawList = drawData.EmplaceDrawList("HostedPreviewForegroundTarget");
|
||||
drawList.AddFilledRect(
|
||||
XCEngine::UI::UIRect(16.0f, 18.0f, 52.0f, 34.0f),
|
||||
XCEngine::UI::UIColor(0.15f, 0.75f, 0.45f, 1.0f));
|
||||
drawList.AddText(
|
||||
XCEngine::UI::UIPoint(24.0f, 28.0f),
|
||||
"foreground",
|
||||
XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
15.0f);
|
||||
|
||||
ImGui::NewFrame();
|
||||
ImDrawList* targetDrawList = ImGui::GetForegroundDrawList();
|
||||
ASSERT_NE(targetDrawList, nullptr);
|
||||
const int baselineVertexCount = targetDrawList->VtxBuffer.Size;
|
||||
const int baselineIndexCount = targetDrawList->IdxBuffer.Size;
|
||||
const int baselineCommandCount = targetDrawList->CmdBuffer.Size;
|
||||
|
||||
std::unique_ptr<RecordingImGuiHostedPreviewTargetBinding> targetBinding =
|
||||
std::make_unique<RecordingImGuiHostedPreviewTargetBinding>();
|
||||
RecordingImGuiHostedPreviewTargetBinding* targetBindingPtr = targetBinding.get();
|
||||
targetBindingPtr->resolvedDrawList = targetDrawList;
|
||||
|
||||
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter =
|
||||
CreateImGuiXCUIHostedPreviewPresenter(std::move(targetBinding));
|
||||
ASSERT_NE(presenter, nullptr);
|
||||
|
||||
XCUIHostedPreviewFrame frame = {};
|
||||
frame.drawData = &drawData;
|
||||
frame.debugName = "HostedPreviewForegroundTarget";
|
||||
|
||||
const bool presented = presenter->Present(frame);
|
||||
const XCUIHostedPreviewStats& stats = presenter->GetLastStats();
|
||||
|
||||
ImGui::EndFrame();
|
||||
|
||||
EXPECT_TRUE(presented);
|
||||
EXPECT_TRUE(stats.presented);
|
||||
EXPECT_EQ(stats.submittedDrawListCount, 1u);
|
||||
EXPECT_EQ(stats.submittedCommandCount, 2u);
|
||||
EXPECT_EQ(stats.flushedDrawListCount, 1u);
|
||||
EXPECT_EQ(stats.flushedCommandCount, 2u);
|
||||
EXPECT_EQ(targetBindingPtr->resolveCallCount, 1u);
|
||||
EXPECT_EQ(targetBindingPtr->lastFrame, &frame);
|
||||
EXPECT_GT(targetDrawList->VtxBuffer.Size, baselineVertexCount);
|
||||
EXPECT_GT(targetDrawList->IdxBuffer.Size, baselineIndexCount);
|
||||
EXPECT_GE(targetDrawList->CmdBuffer.Size, baselineCommandCount);
|
||||
}
|
||||
|
||||
TEST(XCUIHostedPreviewPresenterTest, DefaultFactoryStillUsesCurrentWindowBindingForLegacyImGuiPath) {
|
||||
ImGuiContextScope contextScope;
|
||||
PrepareImGui(800.0f, 600.0f);
|
||||
|
||||
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter = CreateImGuiXCUIHostedPreviewPresenter();
|
||||
ASSERT_NE(presenter, nullptr);
|
||||
|
||||
XCEngine::UI::UIDrawData drawData = {};
|
||||
drawData.EmplaceDrawList("HostedPreviewDefaultBinding").AddFilledRect(
|
||||
XCEngine::UI::UIRect(8.0f, 10.0f, 36.0f, 22.0f),
|
||||
XCEngine::UI::UIColor(0.2f, 0.6f, 0.9f, 1.0f));
|
||||
|
||||
ImGui::NewFrame();
|
||||
ASSERT_TRUE(ImGui::Begin("HostedPreviewPresenterDefaultBindingWindow"));
|
||||
ImDrawList* targetDrawList = ImGui::GetWindowDrawList();
|
||||
ASSERT_NE(targetDrawList, nullptr);
|
||||
|
||||
XCUIHostedPreviewFrame frame = {};
|
||||
frame.drawData = &drawData;
|
||||
|
||||
const bool presented = presenter->Present(frame);
|
||||
const XCUIHostedPreviewStats& stats = presenter->GetLastStats();
|
||||
|
||||
ImGui::End();
|
||||
ImGui::EndFrame();
|
||||
|
||||
EXPECT_TRUE(presented);
|
||||
EXPECT_TRUE(stats.presented);
|
||||
EXPECT_EQ(stats.flushedDrawListCount, 1u);
|
||||
EXPECT_EQ(stats.flushedCommandCount, 1u);
|
||||
EXPECT_GT(targetDrawList->VtxBuffer.Size, 0);
|
||||
EXPECT_GT(targetDrawList->CmdBuffer.Size, 0);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,20 @@ XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState BuildInputState(
|
||||
return input;
|
||||
}
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState BuildKeyboardInputState(
|
||||
float width = 960.0f,
|
||||
float height = 640.0f) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState input = BuildInputState(width, height);
|
||||
input.pointerInside = false;
|
||||
return input;
|
||||
}
|
||||
|
||||
XCEngine::UI::UIPoint RectCenter(const XCEngine::UI::UIRect& rect) {
|
||||
return XCEngine::UI::UIPoint(
|
||||
rect.x + rect.width * 0.5f,
|
||||
rect.y + rect.height * 0.5f);
|
||||
}
|
||||
|
||||
std::vector<const UIDrawCommand*> CollectTextCommands(const XCEngine::UI::UIDrawData& drawData) {
|
||||
std::vector<const UIDrawCommand*> textCommands = {};
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
@@ -363,3 +377,156 @@ TEST(NewEditorXCUILayoutLabRuntimeTest, ClickingPropertySectionHeaderTogglesFiel
|
||||
EXPECT_TRUE(runtime.TryGetElementRect("fieldPosition", fieldRect));
|
||||
EXPECT_GT(fieldRect.height, 0.0f);
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, KeyboardNavigationMovesSelectionAcrossListItems) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baseline = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baseline.stats.documentsReady);
|
||||
|
||||
XCEngine::UI::UIRect listItemRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("assetLighting", listItemRect));
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState selectInput = BuildInputState();
|
||||
selectInput.pointerPosition = RectCenter(listItemRect);
|
||||
selectInput.pointerPressed = true;
|
||||
const auto& selectedFrame = runtime.Update(selectInput);
|
||||
|
||||
ASSERT_TRUE(selectedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(selectedFrame.stats.selectedElementId, "assetLighting");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState nextInput = BuildKeyboardInputState();
|
||||
nextInput.navigateNext = true;
|
||||
const auto& nextFrame = runtime.Update(nextInput);
|
||||
ASSERT_TRUE(nextFrame.stats.documentsReady);
|
||||
EXPECT_EQ(nextFrame.stats.selectedElementId, "assetMaterials");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState endInput = BuildKeyboardInputState();
|
||||
endInput.navigateEnd = true;
|
||||
const auto& endFrame = runtime.Update(endInput);
|
||||
ASSERT_TRUE(endFrame.stats.documentsReady);
|
||||
ASSERT_FALSE(endFrame.stats.selectedElementId.empty());
|
||||
EXPECT_NE(endFrame.stats.selectedElementId, "assetLighting");
|
||||
|
||||
const std::string lastListSelection = endFrame.stats.selectedElementId;
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState nextAtEndInput = BuildKeyboardInputState();
|
||||
nextAtEndInput.navigateNext = true;
|
||||
const auto& nextAtEndFrame = runtime.Update(nextAtEndInput);
|
||||
ASSERT_TRUE(nextAtEndFrame.stats.documentsReady);
|
||||
EXPECT_EQ(nextAtEndFrame.stats.selectedElementId, lastListSelection);
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState homeInput = BuildKeyboardInputState();
|
||||
homeInput.navigateHome = true;
|
||||
const auto& homeFrame = runtime.Update(homeInput);
|
||||
ASSERT_TRUE(homeFrame.stats.documentsReady);
|
||||
EXPECT_EQ(homeFrame.stats.selectedElementId, "assetLighting");
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, KeyboardCollapseAndExpandFollowTreeHierarchy) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baseline = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baseline.stats.documentsReady);
|
||||
|
||||
XCEngine::UI::UIRect treeChildRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("treeScenes", treeChildRect));
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState selectInput = BuildInputState();
|
||||
selectInput.pointerPosition = RectCenter(treeChildRect);
|
||||
selectInput.pointerPressed = true;
|
||||
const auto& selectedFrame = runtime.Update(selectInput);
|
||||
|
||||
ASSERT_TRUE(selectedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(selectedFrame.stats.selectedElementId, "treeScenes");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState collapseToParent = BuildKeyboardInputState();
|
||||
collapseToParent.navigateCollapse = true;
|
||||
const auto& parentFrame = runtime.Update(collapseToParent);
|
||||
ASSERT_TRUE(parentFrame.stats.documentsReady);
|
||||
EXPECT_EQ(parentFrame.stats.selectedElementId, "treeAssetsRoot");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState collapseRoot = BuildKeyboardInputState();
|
||||
collapseRoot.navigateCollapse = true;
|
||||
const auto& collapsedFrame = runtime.Update(collapseRoot);
|
||||
ASSERT_TRUE(collapsedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(collapsedFrame.stats.selectedElementId, "treeAssetsRoot");
|
||||
|
||||
const auto& collapsedPersistedFrame = runtime.Update(BuildKeyboardInputState());
|
||||
ASSERT_TRUE(collapsedPersistedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(collapsedPersistedFrame.stats.expandedTreeItemCount, 0u);
|
||||
EXPECT_FALSE(runtime.TryGetElementRect("treeScenes", treeChildRect));
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState expandRoot = BuildKeyboardInputState();
|
||||
expandRoot.navigateExpand = true;
|
||||
const auto& expandedRootFrame = runtime.Update(expandRoot);
|
||||
ASSERT_TRUE(expandedRootFrame.stats.documentsReady);
|
||||
EXPECT_EQ(expandedRootFrame.stats.selectedElementId, "treeAssetsRoot");
|
||||
|
||||
const auto& expandedPersistedFrame = runtime.Update(BuildKeyboardInputState());
|
||||
ASSERT_TRUE(expandedPersistedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(expandedPersistedFrame.stats.expandedTreeItemCount, 1u);
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("treeScenes", treeChildRect));
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState moveIntoChild = BuildKeyboardInputState();
|
||||
moveIntoChild.navigateExpand = true;
|
||||
const auto& childFrame = runtime.Update(moveIntoChild);
|
||||
ASSERT_TRUE(childFrame.stats.documentsReady);
|
||||
EXPECT_EQ(childFrame.stats.selectedElementId, "treeScenes");
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, KeyboardNavigationTraversesPropertySectionsAndFields) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baseline = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baseline.stats.documentsReady);
|
||||
|
||||
XCEngine::UI::UIRect sectionRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("inspectorTransform", sectionRect));
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState selectInput = BuildInputState();
|
||||
selectInput.pointerPosition = XCEngine::UI::UIPoint(sectionRect.x + 18.0f, sectionRect.y + 10.0f);
|
||||
selectInput.pointerPressed = true;
|
||||
const auto& selectedFrame = runtime.Update(selectInput);
|
||||
|
||||
ASSERT_TRUE(selectedFrame.stats.documentsReady);
|
||||
EXPECT_EQ(selectedFrame.stats.selectedElementId, "inspectorTransform");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState nextSectionInput = BuildKeyboardInputState();
|
||||
nextSectionInput.navigateNext = true;
|
||||
const auto& nextSectionFrame = runtime.Update(nextSectionInput);
|
||||
ASSERT_TRUE(nextSectionFrame.stats.documentsReady);
|
||||
EXPECT_EQ(nextSectionFrame.stats.selectedElementId, "inspectorMesh");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState previousSectionInput = BuildKeyboardInputState();
|
||||
previousSectionInput.navigatePrevious = true;
|
||||
const auto& previousSectionFrame = runtime.Update(previousSectionInput);
|
||||
ASSERT_TRUE(previousSectionFrame.stats.documentsReady);
|
||||
EXPECT_EQ(previousSectionFrame.stats.selectedElementId, "inspectorTransform");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState expandIntoFieldsInput = BuildKeyboardInputState();
|
||||
expandIntoFieldsInput.navigateExpand = true;
|
||||
const auto& expandedSectionFrame = runtime.Update(expandIntoFieldsInput);
|
||||
ASSERT_TRUE(expandedSectionFrame.stats.documentsReady);
|
||||
EXPECT_EQ(expandedSectionFrame.stats.selectedElementId, "inspectorTransform");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState enterFieldsInput = BuildKeyboardInputState();
|
||||
enterFieldsInput.navigateExpand = true;
|
||||
const auto& firstFieldFrame = runtime.Update(enterFieldsInput);
|
||||
ASSERT_TRUE(firstFieldFrame.stats.documentsReady);
|
||||
EXPECT_EQ(firstFieldFrame.stats.selectedElementId, "fieldPosition");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState nextFieldInput = BuildKeyboardInputState();
|
||||
nextFieldInput.navigateNext = true;
|
||||
const auto& nextFieldFrame = runtime.Update(nextFieldInput);
|
||||
ASSERT_TRUE(nextFieldFrame.stats.documentsReady);
|
||||
EXPECT_EQ(nextFieldFrame.stats.selectedElementId, "fieldRotation");
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState collapseToSectionInput = BuildKeyboardInputState();
|
||||
collapseToSectionInput.navigateCollapse = true;
|
||||
const auto& collapseToSectionFrame = runtime.Update(collapseToSectionInput);
|
||||
ASSERT_TRUE(collapseToSectionFrame.stats.documentsReady);
|
||||
EXPECT_EQ(collapseToSectionFrame.stats.selectedElementId, "inspectorTransform");
|
||||
}
|
||||
|
||||
67
tests/NewEditor/test_xcui_panel_canvas_host.cpp
Normal file
67
tests/NewEditor/test_xcui_panel_canvas_host.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "XCUIBackend/NullXCUIPanelCanvasHost.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Editor::XCUIBackend::CreateNullXCUIPanelCanvasHost;
|
||||
using XCEngine::Editor::XCUIBackend::IXCUIPanelCanvasHost;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostBackend;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasHostCapabilities;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasRequest;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIPanelCanvasSession;
|
||||
|
||||
TEST(NewEditorXCUIPanelCanvasHostTest, NullHostReportsExplicitBackendAndCapabilities) {
|
||||
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateNullXCUIPanelCanvasHost();
|
||||
ASSERT_NE(host, nullptr);
|
||||
|
||||
EXPECT_STREQ(host->GetDebugName(), "NullXCUIPanelCanvasHost");
|
||||
EXPECT_EQ(host->GetBackend(), XCUIPanelCanvasHostBackend::Null);
|
||||
|
||||
const XCUIPanelCanvasHostCapabilities capabilities = host->GetCapabilities();
|
||||
EXPECT_FALSE(capabilities.supportsPointerHitTesting);
|
||||
EXPECT_FALSE(capabilities.supportsHostedSurfaceImages);
|
||||
EXPECT_FALSE(capabilities.supportsPrimitiveOverlays);
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUIPanelCanvasHostTest, NullHostBeginCanvasReturnsEmptySessionAndDrawCallsAreNoops) {
|
||||
std::unique_ptr<IXCUIPanelCanvasHost> host = CreateNullXCUIPanelCanvasHost();
|
||||
ASSERT_NE(host, nullptr);
|
||||
|
||||
XCUIPanelCanvasRequest request = {};
|
||||
request.childId = "NullCanvas";
|
||||
request.height = 280.0f;
|
||||
request.topInset = 24.0f;
|
||||
request.bordered = true;
|
||||
request.showSurfaceImage = true;
|
||||
request.drawPreviewFrame = true;
|
||||
request.placeholderTitle = "Placeholder";
|
||||
request.badgeTitle = "Badge";
|
||||
|
||||
const XCUIPanelCanvasSession session = host->BeginCanvas(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.width, 0.0f);
|
||||
EXPECT_FLOAT_EQ(session.canvasRect.height, 0.0f);
|
||||
|
||||
host->DrawFilledRect(
|
||||
XCEngine::UI::UIRect(10.0f, 12.0f, 48.0f, 64.0f),
|
||||
XCEngine::UI::UIColor(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
6.0f);
|
||||
host->DrawOutlineRect(
|
||||
XCEngine::UI::UIRect(5.0f, 6.0f, 100.0f, 40.0f),
|
||||
XCEngine::UI::UIColor(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
2.0f,
|
||||
8.0f);
|
||||
host->DrawText(
|
||||
XCEngine::UI::UIPoint(8.0f, 14.0f),
|
||||
"Null host should ignore text draws",
|
||||
XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
16.0f);
|
||||
host->EndCanvas();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
221
tests/NewEditor/test_xcui_shell_chrome_state.cpp
Normal file
221
tests/NewEditor/test_xcui_shell_chrome_state.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
#include "XCUIBackend/XCUIShellChromeState.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIShellChromeState;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewMode;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewState;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
||||
using XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
||||
|
||||
TEST(XCUIShellChromeStateTest, DefaultsMatchCurrentShellChromeConfiguration) {
|
||||
XCUIShellChromeState state = {};
|
||||
|
||||
const auto& viewToggles = state.GetViewToggles();
|
||||
EXPECT_FALSE(viewToggles.imguiDemoWindowVisible);
|
||||
EXPECT_TRUE(viewToggles.nativeBackdropVisible);
|
||||
EXPECT_TRUE(viewToggles.pulseAccentEnabled);
|
||||
EXPECT_TRUE(viewToggles.nativeXCUIOverlayVisible);
|
||||
EXPECT_TRUE(viewToggles.hostedPreviewHudVisible);
|
||||
|
||||
const auto* demoPanel = state.TryGetPanelState(XCUIShellPanelId::XCUIDemo);
|
||||
ASSERT_NE(demoPanel, nullptr);
|
||||
EXPECT_EQ(demoPanel->panelTitle, "XCUI Demo");
|
||||
EXPECT_EQ(demoPanel->previewDebugName, "XCUI Demo");
|
||||
EXPECT_EQ(demoPanel->previewDebugSource, "new_editor.panels.xcui_demo");
|
||||
EXPECT_TRUE(demoPanel->visible);
|
||||
EXPECT_TRUE(demoPanel->hostedPreviewEnabled);
|
||||
EXPECT_EQ(demoPanel->previewMode, XCUIShellHostedPreviewMode::NativeOffscreen);
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellHostedPreviewState::NativeOffscreen);
|
||||
EXPECT_TRUE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||
EXPECT_FALSE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||
|
||||
const auto* layoutLabPanel = state.TryGetPanelState(XCUIShellPanelId::XCUILayoutLab);
|
||||
ASSERT_NE(layoutLabPanel, nullptr);
|
||||
EXPECT_EQ(layoutLabPanel->panelTitle, "XCUI Layout Lab");
|
||||
EXPECT_EQ(layoutLabPanel->previewDebugName, "XCUI Layout Lab");
|
||||
EXPECT_EQ(layoutLabPanel->previewDebugSource, "new_editor.panels.xcui_layout_lab");
|
||||
EXPECT_TRUE(layoutLabPanel->visible);
|
||||
EXPECT_TRUE(layoutLabPanel->hostedPreviewEnabled);
|
||||
EXPECT_EQ(layoutLabPanel->previewMode, XCUIShellHostedPreviewMode::LegacyImGui);
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellHostedPreviewState::LegacyImGui);
|
||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab));
|
||||
EXPECT_TRUE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUILayoutLab));
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, PanelVisibilityAndPreviewModeMutatorsTrackStateChanges) {
|
||||
XCUIShellChromeState state = {};
|
||||
|
||||
EXPECT_TRUE(state.SetPanelVisible(XCUIShellPanelId::XCUIDemo, false));
|
||||
EXPECT_FALSE(state.IsPanelVisible(XCUIShellPanelId::XCUIDemo));
|
||||
EXPECT_FALSE(state.SetPanelVisible(XCUIShellPanelId::XCUIDemo, false));
|
||||
EXPECT_TRUE(state.TogglePanelVisible(XCUIShellPanelId::XCUIDemo));
|
||||
EXPECT_TRUE(state.IsPanelVisible(XCUIShellPanelId::XCUIDemo));
|
||||
|
||||
EXPECT_TRUE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUILayoutLab, false));
|
||||
EXPECT_FALSE(state.IsHostedPreviewEnabled(XCUIShellPanelId::XCUILayoutLab));
|
||||
EXPECT_FALSE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUILayoutLab, false));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
||||
|
||||
EXPECT_TRUE(state.ToggleHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellHostedPreviewMode::NativeOffscreen);
|
||||
EXPECT_TRUE(state.SetHostedPreviewMode(
|
||||
XCUIShellPanelId::XCUILayoutLab,
|
||||
XCUIShellHostedPreviewMode::LegacyImGui));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
||||
EXPECT_FALSE(state.SetHostedPreviewMode(
|
||||
XCUIShellPanelId::XCUILayoutLab,
|
||||
XCUIShellHostedPreviewMode::LegacyImGui));
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, HostedPreviewStateSeparatesEnablementFromRequestedMode) {
|
||||
XCUIShellChromeState state = {};
|
||||
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellHostedPreviewState::NativeOffscreen);
|
||||
|
||||
EXPECT_TRUE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUIDemo, false));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellHostedPreviewState::Disabled);
|
||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||
EXPECT_FALSE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||
|
||||
EXPECT_TRUE(state.SetHostedPreviewMode(
|
||||
XCUIShellPanelId::XCUIDemo,
|
||||
XCUIShellHostedPreviewMode::LegacyImGui));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellHostedPreviewState::Disabled);
|
||||
|
||||
EXPECT_TRUE(state.SetHostedPreviewEnabled(XCUIShellPanelId::XCUIDemo, true));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellHostedPreviewState::LegacyImGui);
|
||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||
EXPECT_TRUE(state.IsLegacyHostedPreviewActive(XCUIShellPanelId::XCUIDemo));
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, ViewToggleMutatorsOnlyFlipRequestedFlags) {
|
||||
XCUIShellChromeState state = {};
|
||||
|
||||
EXPECT_TRUE(state.SetViewToggle(XCUIShellViewToggleId::ImGuiDemoWindow, true));
|
||||
EXPECT_TRUE(state.GetViewToggle(XCUIShellViewToggleId::ImGuiDemoWindow));
|
||||
EXPECT_FALSE(state.SetViewToggle(XCUIShellViewToggleId::ImGuiDemoWindow, true));
|
||||
|
||||
EXPECT_TRUE(state.ToggleViewToggle(XCUIShellViewToggleId::HostedPreviewHud));
|
||||
EXPECT_FALSE(state.GetViewToggle(XCUIShellViewToggleId::HostedPreviewHud));
|
||||
EXPECT_TRUE(state.GetViewToggle(XCUIShellViewToggleId::NativeBackdrop));
|
||||
EXPECT_TRUE(state.GetViewToggle(XCUIShellViewToggleId::PulseAccent));
|
||||
EXPECT_TRUE(state.GetViewToggle(XCUIShellViewToggleId::NativeXCUIOverlay));
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, CommandInterfaceTogglesShellViewAndPreviewStates) {
|
||||
XCUIShellChromeState state = {};
|
||||
|
||||
EXPECT_TRUE(state.HasCommand(XCUIShellChromeCommandIds::ToggleXCUIDemoPanel));
|
||||
EXPECT_TRUE(state.HasCommand(XCUIShellChromeCommandIds::ToggleHostedPreviewHud));
|
||||
EXPECT_TRUE(state.HasCommand(XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview));
|
||||
EXPECT_FALSE(state.HasCommand("new_editor.view.unknown"));
|
||||
|
||||
EXPECT_TRUE(state.InvokeCommand(XCUIShellChromeCommandIds::ToggleXCUIDemoPanel));
|
||||
EXPECT_FALSE(state.IsPanelVisible(XCUIShellPanelId::XCUIDemo));
|
||||
|
||||
EXPECT_TRUE(state.InvokeCommand(XCUIShellChromeCommandIds::ToggleHostedPreviewHud));
|
||||
EXPECT_FALSE(state.GetViewToggle(XCUIShellViewToggleId::HostedPreviewHud));
|
||||
|
||||
EXPECT_TRUE(state.InvokeCommand(XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellHostedPreviewMode::NativeOffscreen);
|
||||
EXPECT_TRUE(state.InvokeCommand(XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
||||
|
||||
EXPECT_FALSE(state.InvokeCommand("new_editor.view.unknown"));
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, PanelCommandIdHelpersMatchCurrentShellCommands) {
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellChromeCommandIds::ToggleXCUIDemoPanel);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetPanelVisibilityCommandId(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellChromeCommandIds::ToggleXCUILayoutLabPanel);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUIDemo),
|
||||
XCUIShellChromeCommandIds::ToggleNativeDemoPanelPreview);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetPanelPreviewModeCommandId(XCUIShellPanelId::XCUILayoutLab),
|
||||
XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview);
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, ViewToggleCommandIdHelpersMatchCurrentShellCommands) {
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetViewToggleCommandId(XCUIShellViewToggleId::ImGuiDemoWindow),
|
||||
XCUIShellChromeCommandIds::ToggleImGuiDemoWindow);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetViewToggleCommandId(XCUIShellViewToggleId::NativeBackdrop),
|
||||
XCUIShellChromeCommandIds::ToggleNativeBackdrop);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetViewToggleCommandId(XCUIShellViewToggleId::PulseAccent),
|
||||
XCUIShellChromeCommandIds::TogglePulseAccent);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetViewToggleCommandId(XCUIShellViewToggleId::NativeXCUIOverlay),
|
||||
XCUIShellChromeCommandIds::ToggleNativeXCUIOverlay);
|
||||
EXPECT_EQ(
|
||||
XCUIShellChromeState::GetViewToggleCommandId(XCUIShellViewToggleId::HostedPreviewHud),
|
||||
XCUIShellChromeCommandIds::ToggleHostedPreviewHud);
|
||||
}
|
||||
|
||||
TEST(XCUIShellChromeStateTest, InvalidPanelAndToggleIdsFailGracefully) {
|
||||
XCUIShellChromeState state = {};
|
||||
|
||||
const XCUIShellPanelId invalidPanelId = static_cast<XCUIShellPanelId>(255);
|
||||
const XCUIShellViewToggleId invalidToggleId = static_cast<XCUIShellViewToggleId>(255);
|
||||
|
||||
EXPECT_EQ(state.TryGetPanelState(invalidPanelId), nullptr);
|
||||
EXPECT_FALSE(state.IsPanelVisible(invalidPanelId));
|
||||
EXPECT_FALSE(state.SetPanelVisible(invalidPanelId, true));
|
||||
EXPECT_FALSE(state.TogglePanelVisible(invalidPanelId));
|
||||
EXPECT_FALSE(state.IsHostedPreviewEnabled(invalidPanelId));
|
||||
EXPECT_FALSE(state.SetHostedPreviewEnabled(invalidPanelId, false));
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewMode(invalidPanelId),
|
||||
XCUIShellHostedPreviewMode::LegacyImGui);
|
||||
EXPECT_EQ(
|
||||
state.GetHostedPreviewState(invalidPanelId),
|
||||
XCUIShellHostedPreviewState::Disabled);
|
||||
EXPECT_FALSE(state.IsNativeHostedPreviewActive(invalidPanelId));
|
||||
EXPECT_FALSE(state.IsLegacyHostedPreviewActive(invalidPanelId));
|
||||
EXPECT_FALSE(state.SetHostedPreviewMode(invalidPanelId, XCUIShellHostedPreviewMode::NativeOffscreen));
|
||||
EXPECT_FALSE(state.ToggleHostedPreviewMode(invalidPanelId));
|
||||
|
||||
EXPECT_FALSE(state.GetViewToggle(invalidToggleId));
|
||||
EXPECT_FALSE(state.SetViewToggle(invalidToggleId, true));
|
||||
EXPECT_FALSE(state.ToggleViewToggle(invalidToggleId));
|
||||
|
||||
EXPECT_TRUE(XCUIShellChromeState::GetPanelVisibilityCommandId(invalidPanelId).empty());
|
||||
EXPECT_TRUE(XCUIShellChromeState::GetPanelPreviewModeCommandId(invalidPanelId).empty());
|
||||
EXPECT_TRUE(XCUIShellChromeState::GetViewToggleCommandId(invalidToggleId).empty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user