载入中...
搜索中...
未找到
UiPreview.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5#include <functional>
6#include <map>
7
8namespace eve::ui_editing {
9
11 UiPreviewSnapshot result;
12 result.documentRevision = document.revision();
13 result.viewportWidth = width;
14 result.viewportHeight = height;
15 if (!std::isfinite(width) || !std::isfinite(height) || width <= 0.0 || height <= 0.0) {
17 eve::DiagnosticCode::InvalidArgument, RuleId("editor.ui.invalid-preview-viewport"),
18 DiagnosticSeverity::Error, "UI preview viewport must have finite positive dimensions"));
19 return result;
20 }
21 result.diagnostics = document.validate();
22 std::map<ObjectId, UiPreviewWidget> computed;
23 std::function<void(const ObjectId&, const UiPreviewWidget&, int)> visit;
24 visit = [&](const ObjectId& id, const UiPreviewWidget& parent, int depth) {
25 auto value = document.widget(id);
26 if (!value.ok()) return;
27 const UiWidgetSnapshot& widget = value.value();
28 const double contentX = parent.x + widget.style.marginLeft + (depth == 0 ? 0.0 : 0.0);
29 const double contentY = parent.y + widget.style.marginTop;
30 const double parentWidth = std::max(0.0, parent.width - widget.style.marginLeft - widget.style.marginRight);
31 const double parentHeight = std::max(0.0, parent.height - widget.style.marginTop - widget.style.marginBottom);
32 UiPreviewWidget preview;
33 preview.id = widget.id;
34 preview.parent = widget.parent;
35 preview.depth = depth;
36 preview.width = widget.layout.width;
37 preview.height = widget.layout.height;
38 preview.x =
39 contentX + parentWidth * widget.layout.anchorX + widget.layout.x - preview.width * widget.layout.pivotX;
40 preview.y =
41 contentY + parentHeight * widget.layout.anchorY + widget.layout.y - preview.height * widget.layout.pivotY;
42 preview.visible = widget.visible && parent.visible;
43 computed[id] = preview;
44 result.widgets.push_back(preview);
45 UiPreviewWidget childParent = preview;
46 childParent.x += widget.style.paddingLeft;
47 childParent.y += widget.style.paddingTop;
48 childParent.width = std::max(0.0, childParent.width - widget.style.paddingLeft - widget.style.paddingRight);
49 childParent.height = std::max(0.0, childParent.height - widget.style.paddingTop - widget.style.paddingBottom);
50 for (const ObjectId& child : document.children(id)) visit(child, childParent, depth + 1);
51 };
52 const UiPreviewWidget viewport{ObjectId(), ObjectId(), 0.0, 0.0, width, height, -1, true};
53 for (const ObjectId& root : document.children(ObjectId())) visit(root, viewport, 0);
54 const bool hasError = std::any_of(
55 result.diagnostics.begin(), result.diagnostics.end(),
56 [](const EditorDiagnostic& diagnostic) { return diagnostic.severity() == DiagnosticSeverity::Error; });
57 result.status = hasError ? EditorStatus::Failed : EditorStatus::Applied;
58 return result;
59}
60
62 if (!std::isfinite(x) || !std::isfinite(y))
63 return eve::editing::failed<ObjectId>(EditorStatus::Rejected, RuleId("editor.ui.invalid-pick-point"),
64 "UI pick coordinates must be finite");
65 const UiPreviewWidget* best = nullptr;
66 for (const UiPreviewWidget& widget : preview.widgets) {
67 if (!widget.visible || x < widget.x || y < widget.y || x > widget.x + widget.width ||
68 y > widget.y + widget.height)
69 continue;
70 if (!best || widget.depth > best->depth || (widget.depth == best->depth && widget.id > best->id))
71 best = &widget;
72 }
73 if (!best)
74 return eve::editing::failed<ObjectId>(EditorStatus::NotFound, RuleId("editor.ui.pick-miss"),
75 "No visible widget contains the preview point");
76 return eve::editing::applied<ObjectId>(best->id);
77}
78
80 const UiPreviewSnapshot& preview,
81 const ObjectId& id) const {
82 if (preview.documentRevision != document.revision())
83 return eve::editing::failed<EditorValue>(EditorStatus::Conflict, RuleId("editor.ui.stale-preview"),
84 "UI preview revision no longer matches the document");
85 auto widget = document.widget(id);
86 if (!widget.ok())
87 return eve::editing::failed<EditorValue>(EditorStatus::NotFound, RuleId("editor.ui.widget-not-found"),
88 "UI widget does not exist");
89 double parentX = 0.0, parentY = 0.0, parentW = preview.viewportWidth, parentH = preview.viewportHeight;
90 if (!widget.value().parent.empty()) {
91 const auto parent =
92 std::find_if(preview.widgets.begin(), preview.widgets.end(),
93 [&](const UiPreviewWidget& value) { return value.id == widget.value().parent; });
94 if (parent == preview.widgets.end())
95 return eve::editing::failed<EditorValue>(EditorStatus::NotFound,
96 RuleId("editor.ui.preview-parent-not-found"),
97 "Parent is absent from UI preview");
98 auto parentWidget = document.widget(parent->id);
99 parentX = parent->x + parentWidget.value().style.paddingLeft;
100 parentY = parent->y + parentWidget.value().style.paddingTop;
101 parentW = std::max(
102 0.0, parent->width - parentWidget.value().style.paddingLeft - parentWidget.value().style.paddingRight);
103 parentH = std::max(
104 0.0, parent->height - parentWidget.value().style.paddingTop - parentWidget.value().style.paddingBottom);
105 }
106 const auto previewWidget = std::find_if(preview.widgets.begin(), preview.widgets.end(),
107 [&](const UiPreviewWidget& value) { return value.id == id; });
108 if (previewWidget == preview.widgets.end())
109 return eve::editing::failed<EditorValue>(EditorStatus::NotFound, RuleId("editor.ui.preview-widget-not-found"),
110 "Widget is absent from UI preview");
111 const double anchorX = parentX + parentW * widget.value().layout.anchorX;
112 const double anchorY = parentY + parentH * widget.value().layout.anchorY;
113 const double pivotX = previewWidget->x + previewWidget->width * widget.value().layout.pivotX;
114 const double pivotY = previewWidget->y + previewWidget->height * widget.value().layout.pivotY;
115 return eve::editing::applied<EditorValue>(
116 EditorValue::Object{{"anchor", EditorValue::Array{anchorX, anchorY}},
117 {"pivot", EditorValue::Array{pivotX, pivotY}},
118 {"line", EditorValue::Array{anchorX, anchorY, pivotX, pivotY}}});
119}
120
121} // namespace eve::ui_editing
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
int root
Definition AnimSmr.cpp:119
std::string widget
std::uint32_t height
std::uint32_t width
std::int32_t parent
std::string id
Definition PlayHost.cpp:108
std::map< Cell, int > best
std::uint32_t depth
A structured explanation of a failed, degraded, or noteworthy result.
Definition Diagnostic.h:94
Move-only operation result carrying either a value or Status.
Definition Result.h:155
std::uint64_t revision() const override
Return the current revision.
std::vector< Value > Array
std::map< std::string, Value > Object
Result< EditorValue > anchorGizmo(const UiDocumentTarget &document, const UiPreviewSnapshot &preview, const ObjectId &widget) const
Return anchor point, pivot point and connecting line as numeric pairs.
Definition UiPreview.cpp:79
UiPreviewSnapshot build(const UiDocumentTarget &document, double width, double height) const
Compute absolute rectangles for a viewport without mutating runtime UI.
Definition UiPreview.cpp:10
Result< ObjectId > pick(const UiPreviewSnapshot &preview, double x, double y) const
Pick the deepest visible widget under a preview-space point.
Definition UiPreview.cpp:61
Serializable UI authoring document with hierarchy and inspector capabilities.
Definition UiDocument.h:149
std::vector< EditorDiagnostic > validate() const
Validate style, hierarchy and viewport layout constraints.
std::vector< ObjectId > children(const ObjectId &parent) const override
Children.
Result< UiWidgetSnapshot > widget(const ObjectId &id) const override
Widget.
Diagnostic ruleDiagnostic(eve::DiagnosticCode code, RuleId rule, DiagnosticSeverity severity, std::string message)
Build a common diagnostic carrying an open editing rule identity.
Deterministic UI layout preview used by canvas rendering and picking.
Definition UiDocument.h:246
std::vector< UiPreviewWidget > widgets
Definition UiDocument.h:250
std::vector< EditorDiagnostic > diagnostics
Definition UiDocument.h:251
Computed widget rectangle in a revision-bound UI preview.
Definition UiDocument.h:237
Immutable widget snapshot used across editor/runtime boundaries.
Definition UiDocument.h:94