Add XCUI expansion state and coverage tests
This commit is contained in:
@@ -131,6 +131,18 @@ bool DrawDataContainsText(
|
||||
return false;
|
||||
}
|
||||
|
||||
const XCEngine::UI::Runtime::UISystemPresentedLayer* FindPresentedLayerById(
|
||||
const XCEngine::UI::Runtime::UISystemFrameResult& frame,
|
||||
XCEngine::UI::Runtime::UIScreenLayerId layerId) {
|
||||
for (const XCEngine::UI::Runtime::UISystemPresentedLayer& layer : frame.layers) {
|
||||
if (layer.layerId == layerId) {
|
||||
return &layer;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class RecordingScriptRuntime : public IScriptRuntime {
|
||||
public:
|
||||
explicit RecordingScriptRuntime(std::vector<std::string>* events)
|
||||
@@ -430,4 +442,146 @@ TEST_F(SceneRuntimeTest, StopClearsUiRuntimeState) {
|
||||
EXPECT_TRUE(runtime.GetLastUIFrame().layers.empty());
|
||||
}
|
||||
|
||||
TEST_F(SceneRuntimeTest, LayeredSceneUiRoutesInputOnlyToTopInteractivePresentedLayer) {
|
||||
Scene* runtimeScene = CreateScene("RuntimeScene");
|
||||
runtime.Start(runtimeScene);
|
||||
runtime.SetUIViewportRect(XCEngine::UI::UIRect(0.0f, 0.0f, 1280.0f, 720.0f));
|
||||
runtime.SetUIFocused(true);
|
||||
|
||||
TempFileScope gameplayView("xcui_scene_runtime_gameplay", ".xcui", BuildViewMarkup("Gameplay Layer"));
|
||||
TempFileScope overlayView("xcui_scene_runtime_overlay", ".xcui", BuildViewMarkup("Overlay Layer"));
|
||||
|
||||
XCEngine::UI::Runtime::UIScreenLayerOptions gameplayOptions = {};
|
||||
gameplayOptions.debugName = "gameplay";
|
||||
gameplayOptions.acceptsInput = true;
|
||||
gameplayOptions.blocksLayersBelow = false;
|
||||
|
||||
XCEngine::UI::Runtime::UIScreenLayerOptions overlayOptions = {};
|
||||
overlayOptions.debugName = "overlay";
|
||||
overlayOptions.acceptsInput = true;
|
||||
overlayOptions.blocksLayersBelow = false;
|
||||
|
||||
const auto gameplayLayerId = runtime.GetUIScreenStackController().PushScreen(
|
||||
BuildScreenAsset(gameplayView.Path(), "runtime.gameplay"),
|
||||
gameplayOptions);
|
||||
const auto overlayLayerId = runtime.GetUIScreenStackController().PushScreen(
|
||||
BuildScreenAsset(overlayView.Path(), "runtime.overlay"),
|
||||
overlayOptions);
|
||||
ASSERT_NE(gameplayLayerId, 0u);
|
||||
ASSERT_NE(overlayLayerId, 0u);
|
||||
|
||||
XCEngine::UI::UIInputEvent textEvent = {};
|
||||
textEvent.type = XCEngine::UI::UIInputEventType::Character;
|
||||
textEvent.character = 'I';
|
||||
runtime.QueueUIInputEvent(textEvent);
|
||||
|
||||
runtime.Update(0.016f);
|
||||
|
||||
const auto& frame = runtime.GetLastUIFrame();
|
||||
ASSERT_EQ(frame.presentedLayerCount, 2u);
|
||||
ASSERT_EQ(frame.skippedLayerCount, 0u);
|
||||
ASSERT_EQ(frame.layers.size(), 2u);
|
||||
|
||||
const auto* gameplayLayer = FindPresentedLayerById(frame, gameplayLayerId);
|
||||
const auto* overlayLayer = FindPresentedLayerById(frame, overlayLayerId);
|
||||
ASSERT_NE(gameplayLayer, nullptr);
|
||||
ASSERT_NE(overlayLayer, nullptr);
|
||||
EXPECT_EQ(gameplayLayer->stats.inputEventCount, 0u);
|
||||
EXPECT_EQ(overlayLayer->stats.inputEventCount, 1u);
|
||||
EXPECT_TRUE(DrawDataContainsText(frame.drawData, "Gameplay Layer"));
|
||||
EXPECT_TRUE(DrawDataContainsText(frame.drawData, "Overlay Layer"));
|
||||
}
|
||||
|
||||
TEST_F(SceneRuntimeTest, BlockingLayerSkipsLowerLayersAndOwnsQueuedInput) {
|
||||
Scene* runtimeScene = CreateScene("RuntimeScene");
|
||||
runtime.Start(runtimeScene);
|
||||
runtime.SetUIViewportRect(XCEngine::UI::UIRect(0.0f, 0.0f, 1280.0f, 720.0f));
|
||||
runtime.SetUIFocused(true);
|
||||
|
||||
TempFileScope gameplayView("xcui_scene_runtime_blocked_gameplay", ".xcui", BuildViewMarkup("Blocked Gameplay"));
|
||||
TempFileScope modalView("xcui_scene_runtime_modal", ".xcui", BuildViewMarkup("Pause Modal"));
|
||||
|
||||
XCEngine::UI::Runtime::UIScreenLayerOptions gameplayOptions = {};
|
||||
gameplayOptions.debugName = "gameplay";
|
||||
gameplayOptions.acceptsInput = true;
|
||||
gameplayOptions.blocksLayersBelow = false;
|
||||
|
||||
const auto gameplayLayerId = runtime.GetUIScreenStackController().PushScreen(
|
||||
BuildScreenAsset(gameplayView.Path(), "runtime.blocked.gameplay"),
|
||||
gameplayOptions);
|
||||
const auto modalLayerId = runtime.GetUIScreenStackController().PushModal(
|
||||
BuildScreenAsset(modalView.Path(), "runtime.pause.modal"),
|
||||
"pause-modal");
|
||||
ASSERT_NE(gameplayLayerId, 0u);
|
||||
ASSERT_NE(modalLayerId, 0u);
|
||||
|
||||
XCEngine::UI::UIInputEvent textEvent = {};
|
||||
textEvent.type = XCEngine::UI::UIInputEventType::Character;
|
||||
textEvent.character = 'P';
|
||||
runtime.QueueUIInputEvent(textEvent);
|
||||
|
||||
runtime.Update(0.016f);
|
||||
|
||||
const auto& frame = runtime.GetLastUIFrame();
|
||||
ASSERT_EQ(frame.presentedLayerCount, 1u);
|
||||
ASSERT_EQ(frame.skippedLayerCount, 1u);
|
||||
ASSERT_EQ(frame.layers.size(), 1u);
|
||||
|
||||
const auto* modalLayer = FindPresentedLayerById(frame, modalLayerId);
|
||||
ASSERT_NE(modalLayer, nullptr);
|
||||
EXPECT_EQ(modalLayer->stats.inputEventCount, 1u);
|
||||
EXPECT_EQ(FindPresentedLayerById(frame, gameplayLayerId), nullptr);
|
||||
EXPECT_TRUE(DrawDataContainsText(frame.drawData, "Pause Modal"));
|
||||
EXPECT_FALSE(DrawDataContainsText(frame.drawData, "Blocked Gameplay"));
|
||||
}
|
||||
|
||||
TEST_F(SceneRuntimeTest, HiddenTopLayerDoesNotStealInputFromVisibleUnderlyingLayer) {
|
||||
Scene* runtimeScene = CreateScene("RuntimeScene");
|
||||
runtime.Start(runtimeScene);
|
||||
runtime.SetUIViewportRect(XCEngine::UI::UIRect(0.0f, 0.0f, 1280.0f, 720.0f));
|
||||
runtime.SetUIFocused(true);
|
||||
|
||||
TempFileScope gameplayView("xcui_scene_runtime_visible_gameplay", ".xcui", BuildViewMarkup("Visible Gameplay"));
|
||||
TempFileScope hiddenOverlayView("xcui_scene_runtime_hidden_overlay", ".xcui", BuildViewMarkup("Hidden Overlay"));
|
||||
|
||||
XCEngine::UI::Runtime::UIScreenLayerOptions gameplayOptions = {};
|
||||
gameplayOptions.debugName = "gameplay";
|
||||
gameplayOptions.acceptsInput = true;
|
||||
gameplayOptions.blocksLayersBelow = false;
|
||||
|
||||
XCEngine::UI::Runtime::UIScreenLayerOptions hiddenOverlayOptions = {};
|
||||
hiddenOverlayOptions.debugName = "hidden-overlay";
|
||||
hiddenOverlayOptions.visible = false;
|
||||
hiddenOverlayOptions.acceptsInput = true;
|
||||
hiddenOverlayOptions.blocksLayersBelow = false;
|
||||
|
||||
const auto gameplayLayerId = runtime.GetUIScreenStackController().PushScreen(
|
||||
BuildScreenAsset(gameplayView.Path(), "runtime.visible.gameplay"),
|
||||
gameplayOptions);
|
||||
const auto hiddenOverlayLayerId = runtime.GetUIScreenStackController().PushScreen(
|
||||
BuildScreenAsset(hiddenOverlayView.Path(), "runtime.hidden.overlay"),
|
||||
hiddenOverlayOptions);
|
||||
ASSERT_NE(gameplayLayerId, 0u);
|
||||
ASSERT_NE(hiddenOverlayLayerId, 0u);
|
||||
|
||||
XCEngine::UI::UIInputEvent textEvent = {};
|
||||
textEvent.type = XCEngine::UI::UIInputEventType::Character;
|
||||
textEvent.character = 'W';
|
||||
runtime.QueueUIInputEvent(textEvent);
|
||||
|
||||
runtime.Update(0.016f);
|
||||
|
||||
const auto& frame = runtime.GetLastUIFrame();
|
||||
ASSERT_EQ(frame.presentedLayerCount, 1u);
|
||||
ASSERT_EQ(frame.skippedLayerCount, 1u);
|
||||
ASSERT_EQ(frame.layers.size(), 1u);
|
||||
|
||||
const auto* gameplayLayer = FindPresentedLayerById(frame, gameplayLayerId);
|
||||
ASSERT_NE(gameplayLayer, nullptr);
|
||||
EXPECT_EQ(gameplayLayer->stats.inputEventCount, 1u);
|
||||
EXPECT_EQ(FindPresentedLayerById(frame, hiddenOverlayLayerId), nullptr);
|
||||
EXPECT_TRUE(DrawDataContainsText(frame.drawData, "Visible Gameplay"));
|
||||
EXPECT_FALSE(DrawDataContainsText(frame.drawData, "Hidden Overlay"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user