Extract XCUI selection model and layout lab click selection
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <XCEngine/UI/Style/Theme.h>
|
||||
#include <XCEngine/UI/Types.h>
|
||||
#include <XCEngine/UI/Widgets/UIEditorCollectionPrimitives.h>
|
||||
#include <XCEngine/UI/Widgets/UISelectionModel.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
@@ -77,6 +78,7 @@ struct RuntimeBuildContext {
|
||||
std::vector<LayoutNode> nodes = {};
|
||||
std::unordered_map<std::string, std::size_t> nodeIndexById = {};
|
||||
std::unordered_map<std::string, UIRect> rectsById = {};
|
||||
UIWidgets::UISelectionModel selectionModel = {};
|
||||
bool documentsReady = false;
|
||||
std::string statusMessage = {};
|
||||
XCUIAssetDocumentSource documentSource = XCUIAssetDocumentSource(
|
||||
@@ -752,6 +754,7 @@ void DrawNode(
|
||||
bodyFont);
|
||||
}
|
||||
} else if (node.tagName == "Card") {
|
||||
const bool selected = state.selectionModel.IsSelected(node.id);
|
||||
const Color cardColor = ResolveColorToken(
|
||||
state.theme,
|
||||
node.tone == "accent"
|
||||
@@ -799,17 +802,25 @@ void DrawNode(
|
||||
UIColor(1.0f, 0.82f, 0.45f, 1.0f),
|
||||
2.0f,
|
||||
rounding);
|
||||
} else if (selected) {
|
||||
drawList.AddRectOutline(
|
||||
node.rect,
|
||||
ToUIColor(ResolveColorToken(state.theme, "color.accent", Color(0.30f, 0.46f, 0.58f, 1.0f))),
|
||||
2.0f,
|
||||
rounding);
|
||||
}
|
||||
} else if (primitiveKind == UIWidgets::UIEditorCollectionPrimitiveKind::TreeItem ||
|
||||
primitiveKind == UIWidgets::UIEditorCollectionPrimitiveKind::ListItem) {
|
||||
const bool hovered = node.id == hoveredId;
|
||||
const Color rowColor = hovered
|
||||
? ResolveColorToken(state.theme, "color.card.alt", Color(0.20f, 0.27f, 0.34f, 1.0f))
|
||||
: ResolveColorToken(state.theme, "color.card", Color(0.12f, 0.17f, 0.23f, 1.0f));
|
||||
const Color borderColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.border",
|
||||
Color(0.24f, 0.34f, 0.43f, 1.0f));
|
||||
const bool selected = state.selectionModel.IsSelected(node.id);
|
||||
const Color rowColor = selected
|
||||
? ResolveColorToken(state.theme, "color.accent", Color(0.30f, 0.46f, 0.58f, 1.0f))
|
||||
: (hovered
|
||||
? ResolveColorToken(state.theme, "color.card.alt", Color(0.20f, 0.27f, 0.34f, 1.0f))
|
||||
: ResolveColorToken(state.theme, "color.card", Color(0.12f, 0.17f, 0.23f, 1.0f)));
|
||||
const Color borderColor = selected
|
||||
? ResolveColorToken(state.theme, "color.accent", Color(0.30f, 0.46f, 0.58f, 1.0f))
|
||||
: ResolveColorToken(state.theme, "color.border", Color(0.24f, 0.34f, 0.43f, 1.0f));
|
||||
const Color textColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text",
|
||||
@@ -848,6 +859,7 @@ void DrawNode(
|
||||
}
|
||||
} else if (primitiveKind == UIWidgets::UIEditorCollectionPrimitiveKind::FieldRow) {
|
||||
const bool hovered = node.id == hoveredId;
|
||||
const bool selected = state.selectionModel.IsSelected(node.id);
|
||||
const Color textColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text",
|
||||
@@ -856,7 +868,7 @@ void DrawNode(
|
||||
state.theme,
|
||||
"color.text.muted",
|
||||
Color(0.72f, 0.79f, 0.86f, 1.0f));
|
||||
const Color lineColor = hovered
|
||||
const Color lineColor = selected || hovered
|
||||
? ResolveColorToken(state.theme, "color.accent", Color(0.30f, 0.46f, 0.58f, 1.0f))
|
||||
: ResolveColorToken(state.theme, "color.border", Color(0.24f, 0.34f, 0.43f, 1.0f));
|
||||
const float inset = ResolveFloatToken(state.theme, "space.cardInset", 12.0f);
|
||||
@@ -955,6 +967,7 @@ bool XCUILayoutLabRuntime::ReloadDocuments() {
|
||||
state.nodes.clear();
|
||||
state.nodeIndexById.clear();
|
||||
state.rectsById.clear();
|
||||
state.selectionModel.ClearSelection();
|
||||
|
||||
state.documentSource.SetPathSet(XCUIAssetDocumentSource::MakeLayoutLabPathSet());
|
||||
if (!state.documentSource.Reload()) {
|
||||
@@ -1027,13 +1040,24 @@ const XCUILayoutLabFrameResult& XCUILayoutLabRuntime::Update(const XCUILayoutLab
|
||||
state.rectsById[state.nodes[0].id] = state.nodes[0].rect;
|
||||
}
|
||||
|
||||
std::size_t hoveredIndex = kInvalidIndex;
|
||||
if (input.pointerInside) {
|
||||
const std::size_t hoveredIndex = HitTest(state, input.pointerPosition);
|
||||
hoveredIndex = HitTest(state, input.pointerPosition);
|
||||
if (hoveredIndex != kInvalidIndex) {
|
||||
state.frameResult.stats.hoveredElementId = state.nodes[hoveredIndex].id;
|
||||
}
|
||||
}
|
||||
|
||||
if (input.pointerPressed) {
|
||||
if (hoveredIndex != kInvalidIndex) {
|
||||
state.selectionModel.SetSelection(state.nodes[hoveredIndex].id);
|
||||
} else {
|
||||
state.selectionModel.ClearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
state.frameResult.stats.selectedElementId = state.selectionModel.GetSelectedId();
|
||||
|
||||
UIDrawList drawList("XCUI Layout Lab");
|
||||
drawList.PushClipRect(input.canvasRect);
|
||||
DrawNode(state, 0u, drawList, state.frameResult.stats.hoveredElementId);
|
||||
|
||||
@@ -17,6 +17,7 @@ struct XCUILayoutLabInputState {
|
||||
UI::UIRect canvasRect = {};
|
||||
UI::UIPoint pointerPosition = {};
|
||||
bool pointerInside = false;
|
||||
bool pointerPressed = false;
|
||||
};
|
||||
|
||||
struct XCUILayoutLabFrameStats {
|
||||
@@ -47,6 +48,7 @@ struct XCUILayoutLabFrameStats {
|
||||
std::size_t propertySectionCount = 0;
|
||||
std::size_t fieldRowCount = 0;
|
||||
std::string hoveredElementId = {};
|
||||
std::string selectedElementId = {};
|
||||
};
|
||||
|
||||
struct XCUILayoutLabFrameResult {
|
||||
|
||||
@@ -241,6 +241,7 @@ void XCUILayoutLabPanel::Render() {
|
||||
input.pointerPosition = UI::UIPoint(ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
|
||||
input.pointerInside = validCanvas && ImGui::IsItemHovered();
|
||||
}
|
||||
input.pointerPressed = input.pointerInside && ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUILayoutLabFrameResult& frame = m_runtime.Update(input);
|
||||
|
||||
@@ -337,17 +338,19 @@ void XCUILayoutLabPanel::Render() {
|
||||
"Native note: %s",
|
||||
stats.nativeOverlayStatusMessage.empty() ? "none" : stats.nativeOverlayStatusMessage.c_str());
|
||||
ImGui::Text(
|
||||
"Hovered: %s | canvas: %.0f x %.0f",
|
||||
"Hovered: %s | Selected: %s | canvas: %.0f x %.0f",
|
||||
stats.hoveredElementId.empty() ? "none" : stats.hoveredElementId.c_str(),
|
||||
stats.selectedElementId.empty() ? "none" : stats.selectedElementId.c_str(),
|
||||
input.canvasRect.width,
|
||||
input.canvasRect.height);
|
||||
|
||||
ImGui::SeparatorText("Input");
|
||||
ImGui::Text(
|
||||
"Pointer: %.0f, %.0f | inside %s",
|
||||
"Pointer: %.0f, %.0f | inside %s | pressed %s",
|
||||
input.pointerPosition.x,
|
||||
input.pointerPosition.y,
|
||||
input.pointerInside ? "yes" : "no");
|
||||
input.pointerInside ? "yes" : "no",
|
||||
input.pointerPressed ? "yes" : "no");
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
Reference in New Issue
Block a user