219 lines
7.8 KiB
C++
219 lines
7.8 KiB
C++
#pragma once
|
|
|
|
#include <XCEngine/Core/Containers/String.h>
|
|
#include <XCEngine/Core/Math/Color.h>
|
|
#include <XCEngine/Resources/UI/UIDocumentCompiler.h>
|
|
#include <XCEngine/UI/DrawData.h>
|
|
#include <XCEngine/UI/Style/DocumentStyleCompiler.h>
|
|
#include <XCEngine/UI/Style/Theme.h>
|
|
|
|
#include <filesystem>
|
|
#include <initializer_list>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace XCEngine::Tests::EditorUI {
|
|
|
|
struct EditorValidationThemeLoadResult {
|
|
::XCEngine::UI::Style::UITheme theme = {};
|
|
std::string error = {};
|
|
bool succeeded = false;
|
|
};
|
|
|
|
struct EditorValidationShellPalette {
|
|
::XCEngine::UI::UIColor windowBackground = ::XCEngine::UI::UIColor(0.13f, 0.13f, 0.13f, 1.0f);
|
|
::XCEngine::UI::UIColor cardBackground = ::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
|
|
::XCEngine::UI::UIColor cardBorder = ::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
|
|
::XCEngine::UI::UIColor textPrimary = ::XCEngine::UI::UIColor(0.94f, 0.94f, 0.94f, 1.0f);
|
|
::XCEngine::UI::UIColor textMuted = ::XCEngine::UI::UIColor(0.72f, 0.72f, 0.72f, 1.0f);
|
|
::XCEngine::UI::UIColor textWeak = ::XCEngine::UI::UIColor(0.56f, 0.56f, 0.56f, 1.0f);
|
|
::XCEngine::UI::UIColor textSuccess = ::XCEngine::UI::UIColor(0.63f, 0.76f, 0.63f, 1.0f);
|
|
::XCEngine::UI::UIColor buttonBackground = ::XCEngine::UI::UIColor(0.25f, 0.25f, 0.25f, 1.0f);
|
|
::XCEngine::UI::UIColor buttonHoverBackground = ::XCEngine::UI::UIColor(0.32f, 0.32f, 0.32f, 1.0f);
|
|
};
|
|
|
|
struct EditorValidationShellMetrics {
|
|
float margin = 20.0f;
|
|
float gap = 16.0f;
|
|
float cardRadius = 10.0f;
|
|
float buttonRadius = 8.0f;
|
|
float titleFontSize = 17.0f;
|
|
float bodyFontSize = 12.0f;
|
|
};
|
|
|
|
inline ::XCEngine::UI::UIColor ToUIColor(const ::XCEngine::Math::Color& color) {
|
|
return ::XCEngine::UI::UIColor(color.r, color.g, color.b, color.a);
|
|
}
|
|
|
|
inline bool TryResolveThemeFloat(
|
|
const ::XCEngine::UI::Style::UITheme& theme,
|
|
std::string_view tokenName,
|
|
float& outValue) {
|
|
const auto resolution =
|
|
theme.ResolveToken(std::string(tokenName), ::XCEngine::UI::Style::UIStyleValueType::Float);
|
|
if (resolution.status != ::XCEngine::UI::Style::UITokenResolveStatus::Resolved) {
|
|
return false;
|
|
}
|
|
|
|
const float* value = resolution.value.TryGetFloat();
|
|
if (value == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
outValue = *value;
|
|
return true;
|
|
}
|
|
|
|
inline bool TryResolveThemeColor(
|
|
const ::XCEngine::UI::Style::UITheme& theme,
|
|
std::string_view tokenName,
|
|
::XCEngine::UI::UIColor& outColor) {
|
|
const auto resolution =
|
|
theme.ResolveToken(std::string(tokenName), ::XCEngine::UI::Style::UIStyleValueType::Color);
|
|
if (resolution.status != ::XCEngine::UI::Style::UITokenResolveStatus::Resolved) {
|
|
return false;
|
|
}
|
|
|
|
const ::XCEngine::Math::Color* value = resolution.value.TryGetColor();
|
|
if (value == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
outColor = ToUIColor(*value);
|
|
return true;
|
|
}
|
|
|
|
inline float ResolveThemeFloatAliases(
|
|
const ::XCEngine::UI::Style::UITheme& theme,
|
|
std::initializer_list<std::string_view> tokenNames,
|
|
float fallbackValue) {
|
|
float resolvedValue = fallbackValue;
|
|
for (std::string_view tokenName : tokenNames) {
|
|
if (TryResolveThemeFloat(theme, tokenName, resolvedValue)) {
|
|
return resolvedValue;
|
|
}
|
|
}
|
|
|
|
return fallbackValue;
|
|
}
|
|
|
|
inline ::XCEngine::UI::UIColor ResolveThemeColorAliases(
|
|
const ::XCEngine::UI::Style::UITheme& theme,
|
|
std::initializer_list<std::string_view> tokenNames,
|
|
const ::XCEngine::UI::UIColor& fallbackValue) {
|
|
::XCEngine::UI::UIColor resolvedValue = fallbackValue;
|
|
for (std::string_view tokenName : tokenNames) {
|
|
if (TryResolveThemeColor(theme, tokenName, resolvedValue)) {
|
|
return resolvedValue;
|
|
}
|
|
}
|
|
|
|
return fallbackValue;
|
|
}
|
|
|
|
inline EditorValidationThemeLoadResult LoadEditorValidationTheme(
|
|
const std::filesystem::path& themePath) {
|
|
EditorValidationThemeLoadResult result = {};
|
|
|
|
::XCEngine::Resources::UIDocumentCompileResult compileResult = {};
|
|
const ::XCEngine::Containers::String pathString(themePath.generic_string().c_str());
|
|
if (!::XCEngine::Resources::CompileUIDocument(
|
|
::XCEngine::Resources::UIDocumentCompileRequest {
|
|
::XCEngine::Resources::UIDocumentKind::Theme,
|
|
pathString,
|
|
::XCEngine::Resources::GetUIDocumentDefaultRootTag(
|
|
::XCEngine::Resources::UIDocumentKind::Theme)
|
|
},
|
|
compileResult)) {
|
|
result.error = compileResult.errorMessage.Empty()
|
|
? std::string("Failed to compile editor validation theme document.")
|
|
: std::string(compileResult.errorMessage.CStr());
|
|
return result;
|
|
}
|
|
|
|
const auto styleCompileResult =
|
|
::XCEngine::UI::Style::CompileDocumentStyle(compileResult.document);
|
|
if (!styleCompileResult.succeeded) {
|
|
result.error = styleCompileResult.errorMessage;
|
|
return result;
|
|
}
|
|
|
|
result.theme = styleCompileResult.theme;
|
|
result.succeeded = true;
|
|
return result;
|
|
}
|
|
|
|
inline EditorValidationShellPalette ResolveEditorValidationShellPalette(
|
|
const ::XCEngine::UI::Style::UITheme& theme) {
|
|
EditorValidationShellPalette palette = {};
|
|
palette.windowBackground = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.window", "color.bg.workspace" },
|
|
palette.windowBackground);
|
|
palette.cardBackground = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.card", "color.bg.panel" },
|
|
palette.cardBackground);
|
|
palette.cardBorder = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.card_border", "editor.color.menu_popup.border" },
|
|
palette.cardBorder);
|
|
palette.textPrimary = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.text_primary", "color.text.primary" },
|
|
palette.textPrimary);
|
|
palette.textMuted = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.text_muted", "color.text.muted" },
|
|
palette.textMuted);
|
|
palette.textWeak = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.text_weak", "color.text.muted" },
|
|
palette.textWeak);
|
|
palette.textSuccess = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.text_success" },
|
|
palette.textSuccess);
|
|
palette.buttonBackground = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.button", "color.bg.selection" },
|
|
palette.buttonBackground);
|
|
palette.buttonHoverBackground = ResolveThemeColorAliases(
|
|
theme,
|
|
{ "editor.color.validation.button_hover", "editor.color.validation.button", "color.bg.selection" },
|
|
palette.buttonHoverBackground);
|
|
return palette;
|
|
}
|
|
|
|
inline EditorValidationShellMetrics ResolveEditorValidationShellMetrics(
|
|
const ::XCEngine::UI::Style::UITheme& theme) {
|
|
EditorValidationShellMetrics metrics = {};
|
|
metrics.margin = ResolveThemeFloatAliases(
|
|
theme,
|
|
{ "editor.space.validation.margin", "space.shell" },
|
|
metrics.margin);
|
|
metrics.gap = ResolveThemeFloatAliases(
|
|
theme,
|
|
{ "editor.space.validation.gap" },
|
|
metrics.gap);
|
|
metrics.cardRadius = ResolveThemeFloatAliases(
|
|
theme,
|
|
{ "editor.radius.validation.card", "radius.panel" },
|
|
metrics.cardRadius);
|
|
metrics.buttonRadius = ResolveThemeFloatAliases(
|
|
theme,
|
|
{ "editor.radius.validation.button", "radius.control" },
|
|
metrics.buttonRadius);
|
|
metrics.titleFontSize = ResolveThemeFloatAliases(
|
|
theme,
|
|
{ "editor.font.validation.title" },
|
|
metrics.titleFontSize);
|
|
metrics.bodyFontSize = ResolveThemeFloatAliases(
|
|
theme,
|
|
{ "editor.font.validation.body", "editor.font.field.value" },
|
|
metrics.bodyFontSize);
|
|
return metrics;
|
|
}
|
|
|
|
} // namespace XCEngine::Tests::EditorUI
|