Replace new_editor with native XCUI shell sandbox
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
#include <XCEngine/Rendering/ObjectIdEncoding.h>
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderResourceCache.h>
|
||||
#include <XCEngine/Core/Asset/ResourceHandle.h>
|
||||
#include <XCEngine/Core/Asset/ResourceManager.h>
|
||||
#include <XCEngine/RHI/RHIPipelineState.h>
|
||||
#include <XCEngine/Resources/Shader/Shader.h>
|
||||
|
||||
|
||||
@@ -32,7 +32,10 @@ namespace Layout = XCEngine::UI::Layout;
|
||||
|
||||
constexpr float kDefaultFontSize = 16.0f;
|
||||
constexpr float kSmallFontSize = 13.0f;
|
||||
constexpr float kButtonFontSize = 14.0f;
|
||||
constexpr float kApproximateGlyphWidth = 0.56f;
|
||||
constexpr float kHeaderTextInset = 12.0f;
|
||||
constexpr float kHeaderTextGap = 2.0f;
|
||||
|
||||
struct RuntimeLayoutNode {
|
||||
const UIDocumentNode* source = nullptr;
|
||||
@@ -71,6 +74,10 @@ float MeasureTextHeight(float fontSize) {
|
||||
return fontSize + 6.0f;
|
||||
}
|
||||
|
||||
float ComputeCenteredTextTop(const UIRect& rect, float fontSize) {
|
||||
return rect.y + (std::max)(0.0f, std::floor((rect.height - fontSize) * 0.5f));
|
||||
}
|
||||
|
||||
const UIDocumentAttribute* FindAttribute(const UIDocumentNode& node, const char* name) {
|
||||
for (const UIDocumentAttribute& attribute : node.attributes) {
|
||||
if (attribute.name == name) {
|
||||
@@ -89,6 +96,43 @@ std::string GetAttribute(
|
||||
return attribute != nullptr ? ToStdString(attribute->value) : fallback;
|
||||
}
|
||||
|
||||
float MeasureHeaderTextWidth(const UIDocumentNode& node) {
|
||||
float width = 0.0f;
|
||||
|
||||
const std::string title = GetAttribute(node, "title");
|
||||
if (!title.empty()) {
|
||||
width = (std::max)(width, MeasureTextWidth(title, kDefaultFontSize));
|
||||
}
|
||||
|
||||
const std::string subtitle = GetAttribute(node, "subtitle");
|
||||
if (!subtitle.empty()) {
|
||||
width = (std::max)(width, MeasureTextWidth(subtitle, kSmallFontSize));
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
float MeasureHeaderHeight(const UIDocumentNode& node) {
|
||||
const std::string title = GetAttribute(node, "title");
|
||||
const std::string subtitle = GetAttribute(node, "subtitle");
|
||||
if (title.empty() && subtitle.empty()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float headerHeight = kHeaderTextInset;
|
||||
if (!title.empty()) {
|
||||
headerHeight += MeasureTextHeight(kDefaultFontSize);
|
||||
}
|
||||
if (!subtitle.empty()) {
|
||||
if (!title.empty()) {
|
||||
headerHeight += kHeaderTextGap;
|
||||
}
|
||||
headerHeight += MeasureTextHeight(kSmallFontSize);
|
||||
}
|
||||
|
||||
return headerHeight;
|
||||
}
|
||||
|
||||
bool TryParseFloat(const std::string& text, float& outValue) {
|
||||
if (text.empty()) {
|
||||
return false;
|
||||
@@ -139,6 +183,38 @@ Layout::UILayoutThickness ParsePadding(
|
||||
return Layout::UILayoutThickness::Uniform(ParseFloatAttribute(node, "padding", fallback));
|
||||
}
|
||||
|
||||
Layout::UILayoutItem BuildLayoutItem(
|
||||
const RuntimeLayoutNode& child,
|
||||
Layout::UILayoutAxis parentAxis) {
|
||||
Layout::UILayoutItem item = {};
|
||||
item.desiredContentSize = child.desiredSize;
|
||||
item.width = ParseLengthAttribute(*child.source, "width");
|
||||
item.height = ParseLengthAttribute(*child.source, "height");
|
||||
|
||||
// Pixel-authored lengths act as requested extents, but never below the measured content floor.
|
||||
if (item.width.unit == Layout::UILayoutLengthUnit::Pixels &&
|
||||
item.width.value < child.desiredSize.width) {
|
||||
item.minSize.width = child.desiredSize.width;
|
||||
}
|
||||
|
||||
if (item.height.unit == Layout::UILayoutLengthUnit::Pixels &&
|
||||
item.height.value < child.desiredSize.height) {
|
||||
item.minSize.height = child.desiredSize.height;
|
||||
}
|
||||
|
||||
if (parentAxis == Layout::UILayoutAxis::Vertical &&
|
||||
item.width.unit == Layout::UILayoutLengthUnit::Auto) {
|
||||
item.horizontalAlignment = Layout::UILayoutAlignment::Stretch;
|
||||
}
|
||||
|
||||
if (parentAxis == Layout::UILayoutAxis::Horizontal &&
|
||||
item.height.unit == Layout::UILayoutLengthUnit::Auto) {
|
||||
item.verticalAlignment = Layout::UILayoutAlignment::Stretch;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
std::string ResolveNodeText(const UIDocumentNode& node) {
|
||||
const std::string text = GetAttribute(node, "text");
|
||||
if (!text.empty()) {
|
||||
@@ -175,31 +251,31 @@ Color ResolveBackgroundColor(const UIDocumentNode& node) {
|
||||
const std::string tagName = ToStdString(node.tagName);
|
||||
|
||||
if (tagName == "View") {
|
||||
return Color(0.08f, 0.09f, 0.11f, 1.0f);
|
||||
return Color(0.11f, 0.11f, 0.11f, 1.0f);
|
||||
}
|
||||
if (tone == "accent") {
|
||||
return Color(0.19f, 0.31f, 0.52f, 1.0f);
|
||||
return Color(0.25f, 0.25f, 0.25f, 1.0f);
|
||||
}
|
||||
if (tone == "accent-alt") {
|
||||
return Color(0.24f, 0.26f, 0.39f, 1.0f);
|
||||
return Color(0.22f, 0.22f, 0.22f, 1.0f);
|
||||
}
|
||||
if (tagName == "Button") {
|
||||
return Color(0.20f, 0.23f, 0.29f, 1.0f);
|
||||
return Color(0.24f, 0.24f, 0.24f, 1.0f);
|
||||
}
|
||||
|
||||
return Color(0.13f, 0.15f, 0.18f, 1.0f);
|
||||
return Color(0.16f, 0.16f, 0.16f, 1.0f);
|
||||
}
|
||||
|
||||
Color ResolveBorderColor(const UIDocumentNode& node) {
|
||||
const std::string tone = GetAttribute(node, "tone");
|
||||
if (tone == "accent") {
|
||||
return Color(0.31f, 0.56f, 0.90f, 1.0f);
|
||||
return Color(0.42f, 0.42f, 0.42f, 1.0f);
|
||||
}
|
||||
if (tone == "accent-alt") {
|
||||
return Color(0.47f, 0.51f, 0.76f, 1.0f);
|
||||
return Color(0.34f, 0.34f, 0.34f, 1.0f);
|
||||
}
|
||||
|
||||
return Color(0.25f, 0.28f, 0.33f, 1.0f);
|
||||
return Color(0.30f, 0.30f, 0.30f, 1.0f);
|
||||
}
|
||||
|
||||
RuntimeLayoutNode BuildLayoutTree(const UIDocumentNode& source) {
|
||||
@@ -246,42 +322,32 @@ UISize MeasureNode(RuntimeLayoutNode& node) {
|
||||
std::vector<Layout::UILayoutItem> items = {};
|
||||
items.reserve(node.children.size());
|
||||
for (RuntimeLayoutNode& child : node.children) {
|
||||
Layout::UILayoutItem item = {};
|
||||
item.desiredContentSize = MeasureNode(child);
|
||||
item.width = ParseLengthAttribute(*child.source, "width");
|
||||
item.height = ParseLengthAttribute(*child.source, "height");
|
||||
MeasureNode(child);
|
||||
Layout::UILayoutItem item = BuildLayoutItem(child, options.axis);
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
const auto measured = Layout::MeasureStackLayout(options, items);
|
||||
node.desiredSize = measured.desiredSize;
|
||||
|
||||
const std::string title = GetAttribute(source, "title");
|
||||
const std::string subtitle = GetAttribute(source, "subtitle");
|
||||
float headerHeight = 0.0f;
|
||||
if (!title.empty()) {
|
||||
headerHeight += MeasureTextHeight(kDefaultFontSize);
|
||||
}
|
||||
if (!subtitle.empty()) {
|
||||
if (headerHeight > 0.0f) {
|
||||
headerHeight += 4.0f;
|
||||
}
|
||||
headerHeight += MeasureTextHeight(kSmallFontSize);
|
||||
}
|
||||
const float headerHeight = MeasureHeaderHeight(source);
|
||||
const float headerTextWidth = MeasureHeaderTextWidth(source);
|
||||
|
||||
node.desiredSize.width = (std::max)(
|
||||
node.desiredSize.width,
|
||||
MeasureTextWidth(ResolveNodeText(source), kDefaultFontSize) + options.padding.Horizontal());
|
||||
headerTextWidth > 0.0f
|
||||
? headerTextWidth + options.padding.Horizontal()
|
||||
: MeasureTextWidth(ResolveNodeText(source), kDefaultFontSize) + options.padding.Horizontal());
|
||||
node.desiredSize.height += headerHeight;
|
||||
|
||||
float explicitWidth = 0.0f;
|
||||
if (TryParseFloat(GetAttribute(source, "width"), explicitWidth)) {
|
||||
node.desiredSize.width = explicitWidth;
|
||||
node.desiredSize.width = (std::max)(node.desiredSize.width, explicitWidth);
|
||||
}
|
||||
|
||||
float explicitHeight = 0.0f;
|
||||
if (TryParseFloat(GetAttribute(source, "height"), explicitHeight)) {
|
||||
node.desiredSize.height = explicitHeight;
|
||||
node.desiredSize.height = (std::max)(node.desiredSize.height, explicitHeight);
|
||||
}
|
||||
|
||||
return node.desiredSize;
|
||||
@@ -308,16 +374,7 @@ void ArrangeNode(RuntimeLayoutNode& node, const UIRect& rect) {
|
||||
source,
|
||||
tagName == "View" ? 16.0f : 12.0f);
|
||||
|
||||
float headerHeight = 0.0f;
|
||||
if (!GetAttribute(source, "title").empty()) {
|
||||
headerHeight += MeasureTextHeight(kDefaultFontSize);
|
||||
}
|
||||
if (!GetAttribute(source, "subtitle").empty()) {
|
||||
if (headerHeight > 0.0f) {
|
||||
headerHeight += 4.0f;
|
||||
}
|
||||
headerHeight += MeasureTextHeight(kSmallFontSize);
|
||||
}
|
||||
const float headerHeight = MeasureHeaderHeight(source);
|
||||
|
||||
UIRect contentRect = rect;
|
||||
contentRect.y += headerHeight;
|
||||
@@ -326,10 +383,7 @@ void ArrangeNode(RuntimeLayoutNode& node, const UIRect& rect) {
|
||||
std::vector<Layout::UILayoutItem> items = {};
|
||||
items.reserve(node.children.size());
|
||||
for (RuntimeLayoutNode& child : node.children) {
|
||||
Layout::UILayoutItem item = {};
|
||||
item.desiredContentSize = child.desiredSize;
|
||||
item.width = ParseLengthAttribute(*child.source, "width");
|
||||
item.height = ParseLengthAttribute(*child.source, "height");
|
||||
Layout::UILayoutItem item = BuildLayoutItem(child, options.axis);
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
@@ -359,7 +413,7 @@ void EmitNode(
|
||||
|
||||
const std::string title = GetAttribute(source, "title");
|
||||
const std::string subtitle = GetAttribute(source, "subtitle");
|
||||
float textY = node.rect.y + 12.0f;
|
||||
float textY = node.rect.y + kHeaderTextInset;
|
||||
if (!title.empty()) {
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + 12.0f, textY),
|
||||
@@ -367,7 +421,7 @@ void EmitNode(
|
||||
ToUIColor(Color(0.94f, 0.95f, 0.97f, 1.0f)),
|
||||
kDefaultFontSize);
|
||||
++stats.textCommandCount;
|
||||
textY += MeasureTextHeight(kDefaultFontSize) + 2.0f;
|
||||
textY += MeasureTextHeight(kDefaultFontSize) + kHeaderTextGap;
|
||||
}
|
||||
|
||||
if (!subtitle.empty()) {
|
||||
@@ -390,10 +444,10 @@ void EmitNode(
|
||||
|
||||
if (tagName == "Button" && title.empty() && subtitle.empty()) {
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + 12.0f, node.rect.y + 12.0f),
|
||||
UIPoint(node.rect.x + 12.0f, ComputeCenteredTextTop(node.rect, kButtonFontSize)),
|
||||
ResolveNodeText(source),
|
||||
ToUIColor(Color(0.95f, 0.97f, 1.0f, 1.0f)),
|
||||
kDefaultFontSize);
|
||||
kButtonFontSize);
|
||||
++stats.textCommandCount;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user