#pragma once #include #include #include #include #include #include #include #include #include #include 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 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 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