Replace new_editor with native XCUI shell sandbox
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -88,6 +89,70 @@ bool DrawDataContainsText(
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<XCEngine::UI::UIRect> CollectFilledRects(
|
||||
const XCEngine::UI::UIDrawData& drawData) {
|
||||
std::vector<XCEngine::UI::UIRect> rects = {};
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
for (const XCEngine::UI::UIDrawCommand& command : drawList.GetCommands()) {
|
||||
if (command.type == XCEngine::UI::UIDrawCommandType::FilledRect) {
|
||||
rects.push_back(command.rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rects;
|
||||
}
|
||||
|
||||
const XCEngine::UI::UIDrawCommand* FindTextCommand(
|
||||
const XCEngine::UI::UIDrawData& drawData,
|
||||
const std::string& text) {
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
for (const XCEngine::UI::UIDrawCommand& command : drawList.GetCommands()) {
|
||||
if (command.type == XCEngine::UI::UIDrawCommandType::Text &&
|
||||
command.text == text) {
|
||||
return &command;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RectContainsPoint(
|
||||
const XCEngine::UI::UIRect& rect,
|
||||
const XCEngine::UI::UIPoint& point) {
|
||||
return point.x >= rect.x &&
|
||||
point.x <= rect.x + rect.width &&
|
||||
point.y >= rect.y &&
|
||||
point.y <= rect.y + rect.height;
|
||||
}
|
||||
|
||||
bool TryFindSmallestFilledRectContainingPoint(
|
||||
const XCEngine::UI::UIDrawData& drawData,
|
||||
const XCEngine::UI::UIPoint& point,
|
||||
XCEngine::UI::UIRect& outRect) {
|
||||
bool found = false;
|
||||
float bestArea = (std::numeric_limits<float>::max)();
|
||||
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
for (const XCEngine::UI::UIDrawCommand& command : drawList.GetCommands()) {
|
||||
if (command.type != XCEngine::UI::UIDrawCommandType::FilledRect ||
|
||||
!RectContainsPoint(command.rect, point)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const float area = command.rect.width * command.rect.height;
|
||||
if (!found || area < bestArea) {
|
||||
outRect = command.rect;
|
||||
bestArea = area;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
UIScreenFrameInput BuildInputState(std::uint64_t frameIndex = 1u) {
|
||||
UIScreenFrameInput input = {};
|
||||
input.viewportRect = XCEngine::UI::UIRect(0.0f, 0.0f, 800.0f, 480.0f);
|
||||
@@ -181,6 +246,68 @@ TEST(UIRuntimeTest, ScreenPlayerBuildsDrawDataFromDocumentTree) {
|
||||
EXPECT_EQ(player.GetPresentedFrameCount(), 1u);
|
||||
}
|
||||
|
||||
TEST(UIRuntimeTest, DocumentHostStretchesColumnChildrenAcrossCrossAxis) {
|
||||
TempFileScope viewFile(
|
||||
"xcui_runtime_stretch_column",
|
||||
".xcui",
|
||||
"<View name=\"Stretch Column\">\n"
|
||||
" <Column padding=\"18\" gap=\"10\">\n"
|
||||
" <Button text=\"Wide Button\" />\n"
|
||||
" </Column>\n"
|
||||
"</View>\n");
|
||||
UIDocumentScreenHost host = {};
|
||||
UIScreenPlayer player(host);
|
||||
|
||||
ASSERT_TRUE(player.Load(BuildScreenAsset(viewFile.Path(), "runtime.stretch.column")));
|
||||
|
||||
UIScreenFrameInput input = BuildInputState();
|
||||
input.viewportRect = XCEngine::UI::UIRect(0.0f, 0.0f, 400.0f, 220.0f);
|
||||
const auto& frame = player.Update(input);
|
||||
const auto* buttonText = FindTextCommand(frame.drawData, "Wide Button");
|
||||
ASSERT_NE(buttonText, nullptr);
|
||||
|
||||
XCEngine::UI::UIRect buttonRect = {};
|
||||
ASSERT_TRUE(TryFindSmallestFilledRectContainingPoint(frame.drawData, buttonText->position, buttonRect));
|
||||
EXPECT_FLOAT_EQ(buttonRect.x, 34.0f);
|
||||
EXPECT_FLOAT_EQ(buttonRect.width, 332.0f);
|
||||
}
|
||||
|
||||
TEST(UIRuntimeTest, DocumentHostDoesNotLetExplicitHeightCrushCardContent) {
|
||||
TempFileScope viewFile(
|
||||
"xcui_runtime_card_height_floor",
|
||||
".xcui",
|
||||
"<View name=\"Card Height Floor\">\n"
|
||||
" <Column padding=\"18\" gap=\"10\">\n"
|
||||
" <Card title=\"Hero\" subtitle=\"Subtitle\" height=\"32\">\n"
|
||||
" <Row gap=\"10\">\n"
|
||||
" <Button text=\"Action\" />\n"
|
||||
" </Row>\n"
|
||||
" </Card>\n"
|
||||
" </Column>\n"
|
||||
"</View>\n");
|
||||
UIDocumentScreenHost host = {};
|
||||
UIScreenPlayer player(host);
|
||||
|
||||
ASSERT_TRUE(player.Load(BuildScreenAsset(viewFile.Path(), "runtime.card.height.floor")));
|
||||
|
||||
UIScreenFrameInput input = BuildInputState();
|
||||
input.viewportRect = XCEngine::UI::UIRect(0.0f, 0.0f, 500.0f, 300.0f);
|
||||
const auto& frame = player.Update(input);
|
||||
const auto* heroTitle = FindTextCommand(frame.drawData, "Hero");
|
||||
const auto* actionText = FindTextCommand(frame.drawData, "Action");
|
||||
ASSERT_NE(heroTitle, nullptr);
|
||||
ASSERT_NE(actionText, nullptr);
|
||||
|
||||
XCEngine::UI::UIRect cardRect = {};
|
||||
XCEngine::UI::UIRect buttonRect = {};
|
||||
ASSERT_TRUE(TryFindSmallestFilledRectContainingPoint(frame.drawData, heroTitle->position, cardRect));
|
||||
ASSERT_TRUE(TryFindSmallestFilledRectContainingPoint(frame.drawData, actionText->position, buttonRect));
|
||||
|
||||
EXPECT_GT(cardRect.height, 32.0f);
|
||||
EXPECT_GE(buttonRect.y, cardRect.y + 50.0f);
|
||||
EXPECT_LE(buttonRect.y + buttonRect.height, cardRect.y + cardRect.height - 8.0f);
|
||||
}
|
||||
|
||||
TEST(UIRuntimeTest, ScreenPlayerConsumeLastFrameReturnsDetachedPacketAndClearsBorrowedState) {
|
||||
TempFileScope viewFile("xcui_runtime_consume_player", ".xcui", BuildViewMarkup("Runtime Consume"));
|
||||
UIDocumentScreenHost host = {};
|
||||
|
||||
Reference in New Issue
Block a user