Build XCEditor viewport shell contract foundation

This commit is contained in:
2026-04-07 05:33:27 +08:00
parent a53f47e561
commit 044240d2f1
11 changed files with 1141 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ set(EDITOR_UI_UNIT_TEST_SOURCES
test_ui_editor_status_bar.cpp
test_ui_editor_tab_strip.cpp
test_ui_editor_viewport_input_bridge.cpp
test_ui_editor_viewport_shell.cpp
test_ui_editor_viewport_slot.cpp
test_ui_editor_shortcut_manager.cpp
test_ui_editor_workspace_controller.cpp

View File

@@ -0,0 +1,132 @@
#include <gtest/gtest.h>
#include <XCEditor/Core/UIEditorViewportShell.h>
namespace {
using XCEngine::UI::UIInputEvent;
using XCEngine::UI::UIInputEventType;
using XCEngine::UI::UIPoint;
using XCEngine::UI::UIPointerButton;
using XCEngine::UI::UIRect;
using XCEngine::UI::Editor::ResolveUIEditorViewportShellRequest;
using XCEngine::UI::Editor::UIEditorViewportShellModel;
using XCEngine::UI::Editor::UIEditorViewportShellSpec;
using XCEngine::UI::Editor::UIEditorViewportShellState;
using XCEngine::UI::Editor::UpdateUIEditorViewportShell;
using XCEngine::UI::Editor::Widgets::UIEditorStatusBarInvalidIndex;
using XCEngine::UI::Editor::Widgets::UIEditorStatusBarState;
using XCEngine::UI::Editor::Widgets::UIEditorViewportSlotInvalidIndex;
UIInputEvent MakePointerEvent(
UIInputEventType type,
float x,
float y,
UIPointerButton button = UIPointerButton::None) {
UIInputEvent event = {};
event.type = type;
event.position = UIPoint(x, y);
event.pointerButton = button;
return event;
}
TEST(UIEditorViewportShellTest, ResolveRequestUsesViewportInputRectSize) {
UIEditorViewportShellSpec spec = {};
const auto request = ResolveUIEditorViewportShellRequest(
UIRect(10.0f, 20.0f, 800.0f, 600.0f),
spec);
EXPECT_FLOAT_EQ(request.slotLayout.inputRect.width, 800.0f);
EXPECT_FLOAT_EQ(request.slotLayout.inputRect.height, 532.0f);
EXPECT_FLOAT_EQ(request.requestedViewportSize.width, 800.0f);
EXPECT_FLOAT_EQ(request.requestedViewportSize.height, 532.0f);
}
TEST(UIEditorViewportShellTest, ResolveRequestTracksChromeBarVisibility) {
UIEditorViewportShellSpec spec = {};
spec.chrome.showTopBar = false;
spec.chrome.showBottomBar = false;
const auto request = ResolveUIEditorViewportShellRequest(
UIRect(10.0f, 20.0f, 800.0f, 600.0f),
spec);
EXPECT_FLOAT_EQ(request.slotLayout.inputRect.height, 600.0f);
EXPECT_FLOAT_EQ(request.requestedViewportSize.height, 600.0f);
}
TEST(UIEditorViewportShellTest, UpdateShellMapsInputBridgeStateToViewportSlotState) {
UIEditorViewportShellModel model = {};
UIEditorViewportShellState state = {};
const auto request = ResolveUIEditorViewportShellRequest(
UIRect(10.0f, 20.0f, 800.0f, 600.0f),
model.spec);
const float insideX = request.slotLayout.inputRect.x + 80.0f;
const float insideY = request.slotLayout.inputRect.y + 60.0f;
const auto frame = UpdateUIEditorViewportShell(
state,
UIRect(10.0f, 20.0f, 800.0f, 600.0f),
model,
{
MakePointerEvent(UIInputEventType::PointerMove, insideX, insideY),
MakePointerEvent(UIInputEventType::PointerButtonDown, insideX, insideY, UIPointerButton::Left)
});
EXPECT_TRUE(frame.inputFrame.focused);
EXPECT_TRUE(frame.inputFrame.captured);
EXPECT_TRUE(frame.slotState.focused);
EXPECT_TRUE(frame.slotState.surfaceHovered);
EXPECT_TRUE(frame.slotState.surfaceActive);
EXPECT_TRUE(frame.slotState.inputCaptured);
EXPECT_TRUE(frame.slotState.statusBarState.focused);
EXPECT_FLOAT_EQ(frame.requestedViewportSize.width, request.requestedViewportSize.width);
EXPECT_FLOAT_EQ(frame.requestedViewportSize.height, request.requestedViewportSize.height);
}
TEST(UIEditorViewportShellTest, UpdateShellPreservesVisualOverrides) {
UIEditorViewportShellModel model = {};
model.spec.visualState.hoveredToolIndex = 1u;
model.spec.visualState.activeToolIndex = 2u;
model.spec.visualState.statusBarState = UIEditorStatusBarState{
3u,
4u,
true
};
UIEditorViewportShellState state = {};
const auto frame = UpdateUIEditorViewportShell(
state,
UIRect(10.0f, 20.0f, 800.0f, 600.0f),
model,
{});
EXPECT_EQ(frame.slotState.hoveredToolIndex, 1u);
EXPECT_EQ(frame.slotState.activeToolIndex, 2u);
EXPECT_EQ(frame.slotState.statusBarState.hoveredIndex, 3u);
EXPECT_EQ(frame.slotState.statusBarState.activeIndex, 4u);
EXPECT_TRUE(frame.slotState.statusBarState.focused);
EXPECT_FALSE(frame.slotState.focused);
EXPECT_FALSE(frame.slotState.surfaceHovered);
EXPECT_FALSE(frame.slotState.surfaceActive);
EXPECT_FALSE(frame.slotState.inputCaptured);
}
TEST(UIEditorViewportShellTest, UpdateShellDoesNotIntroduceInvalidIndicesByDefault) {
UIEditorViewportShellModel model = {};
UIEditorViewportShellState state = {};
const auto frame = UpdateUIEditorViewportShell(
state,
UIRect(10.0f, 20.0f, 800.0f, 600.0f),
model,
{});
EXPECT_EQ(frame.slotState.hoveredToolIndex, UIEditorViewportSlotInvalidIndex);
EXPECT_EQ(frame.slotState.activeToolIndex, UIEditorViewportSlotInvalidIndex);
EXPECT_EQ(frame.slotState.statusBarState.hoveredIndex, UIEditorStatusBarInvalidIndex);
EXPECT_EQ(frame.slotState.statusBarState.activeIndex, UIEditorStatusBarInvalidIndex);
EXPECT_FALSE(frame.slotState.statusBarState.focused);
}
} // namespace