载入中...
搜索中...
未找到
UiRuntime.cpp
浏览该文件的文档.
2
3#include "ui/UIHost.h"
4#include "ui/Widget.h"
5
6#include <map>
7
8namespace eve::ui_editing {
9namespace {
10
11Result<ui::NodeType> nodeType(const std::string& type) {
12 static const std::map<std::string, ui::NodeType> types{
13 {"window", ui::NodeType::Window}, {"text", ui::NodeType::Text},
14 {"button", ui::NodeType::Button}, {"group", ui::NodeType::Group},
15 {"checkbox", ui::NodeType::Checkbox}, {"slider", ui::NodeType::Slider},
16 {"input", ui::NodeType::InputText}, {"flex", ui::NodeType::Flex},
17 {"image", ui::NodeType::Image}, {"image-button", ui::NodeType::ImageButton},
18 {"viewport", ui::NodeType::Viewport}, {"card", ui::NodeType::Card},
19 {"toolbar", ui::NodeType::Toolbar}, {"sidebar", ui::NodeType::Sidebar},
20 {"split-pane", ui::NodeType::SplitPane}, {"nine-patch", ui::NodeType::NinePatchPanel}};
21 const auto found = types.find(type);
22 if (found == types.end())
23 return eve::editing::failed<ui::NodeType>(EditorStatus::Unsupported,
24 RuleId("editor.ui.unsupported-runtime-widget"),
25 "Runtime UI does not support widget type: " + type);
26 return eve::editing::applied<ui::NodeType>(found->second);
27}
28
29Result<ui::WidgetDesc> buildWidget(const UiDocumentTarget& document, const ObjectId& id) {
30 auto value = document.widget(id);
31 if (!value.ok())
32 return eve::editing::failed<ui::WidgetDesc>(EditorStatus::NotFound, RuleId("editor.ui.widget-not-found"),
33 "UI widget does not exist: " + id.value());
34 auto type = nodeType(value.value().type);
35 if (!type.ok()) return Result<ui::WidgetDesc>::failure(type.status());
36 const UiWidgetSnapshot& widget = value.value();
37 ui::WidgetDesc result;
38 result.type = type.value();
39 result.withId(widget.id.value())
40 .withKey(widget.id.value())
41 .withText(widget.text)
42 .withVisible(widget.visible)
43 .withEnabled(widget.enabled)
44 .withSize(static_cast<float>(widget.layout.width), static_cast<float>(widget.layout.height))
45 .withAbsolute(static_cast<float>(widget.layout.anchorX), static_cast<float>(widget.layout.anchorY),
46 static_cast<float>(widget.layout.x - widget.layout.width * widget.layout.pivotX),
47 static_cast<float>(widget.layout.y - widget.layout.height * widget.layout.pivotY))
48 .withMargin(static_cast<float>(widget.style.marginLeft), static_cast<float>(widget.style.marginTop),
49 static_cast<float>(widget.style.marginRight), static_cast<float>(widget.style.marginBottom))
50 .withPadding(static_cast<float>(widget.style.paddingLeft), static_cast<float>(widget.style.paddingTop),
51 static_cast<float>(widget.style.paddingRight), static_cast<float>(widget.style.paddingBottom))
52 .withTint(static_cast<float>(widget.style.tintR), static_cast<float>(widget.style.tintG),
53 static_cast<float>(widget.style.tintB), static_cast<float>(widget.style.tintA))
54 .withCornerRadius(static_cast<float>(widget.style.cornerRadius))
55 .withGap(static_cast<float>(widget.style.gap))
56 .withFlexGrow(static_cast<float>(widget.style.flexGrow));
57 result.flexDirection = widget.style.direction == "column" ? ui::FlexDirection::Column : ui::FlexDirection::Row;
58 const std::map<std::string, ui::FlexAlign> aligns{{"start", ui::FlexAlign::Start},
59 {"center", ui::FlexAlign::Center},
60 {"end", ui::FlexAlign::End},
61 {"stretch", ui::FlexAlign::Stretch}};
62 const std::map<std::string, ui::FlexJustify> justifies{{"start", ui::FlexJustify::Start},
63 {"center", ui::FlexJustify::Center},
64 {"end", ui::FlexJustify::End},
65 {"space-between", ui::FlexJustify::SpaceBetween},
66 {"space-around", ui::FlexJustify::SpaceAround}};
67 result.alignItems = aligns.at(widget.style.align);
68 result.justifyContent = justifies.at(widget.style.justify);
69 for (const ObjectId& child : document.children(id)) {
70 auto built = buildWidget(document, child);
71 if (!built.ok()) return Result<ui::WidgetDesc>::failure(built.status());
72 result.children.push_back(std::move(built).value());
73 }
74 return eve::editing::applied<ui::WidgetDesc>(std::move(result));
75}
76
77} // namespace
78
80 ui::UIHost* host) const {
81 if (!host)
82 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.ui.runtime-host-required"),
83 "Runtime UI publishing requires a live UIHost");
84 auto built = buildWidget(document, root);
85 if (!built.ok()) return Result<void>::failure(built.status());
86 host->setTreeReconcile(std::move(built).value());
87 return eve::editing::applied<void>();
88}
89
90} // namespace eve::ui_editing
double value
int root
Definition AnimSmr.cpp:119
std::string widget
std::string id
Definition PlayHost.cpp:108
bool found
int children
Definition TreeMesh.cpp:295
UIHostHandle host
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
ECS mount point for one UI panel/screen. Subclass to attach UI to game entities, e....
Definition UIHost.h:243
Result< void > publish(const UiDocumentTarget &document, const ObjectId &root, ui::UIHost *host) const
Reconcile a document subtree into a runtime host.
Definition UiRuntime.cpp:79
Serializable UI authoring document with hierarchy and inspector capabilities.
Definition UiDocument.h:149
ui_editing::UiWidgetSnapshot UiWidgetSnapshot