Implement XCUI markup import loader support

This commit is contained in:
2026-04-04 19:51:02 +08:00
parent bcef1f145b
commit 781c3b9a78
9 changed files with 320 additions and 14 deletions

View File

@@ -0,0 +1,167 @@
#include <XCEngine/Resources/UI/UIDocumentLoaders.h>
#include <filesystem>
namespace XCEngine {
namespace Resources {
namespace {
Containers::String GetPathExtension(const Containers::String& path) {
const std::filesystem::path fsPath(path.CStr());
const std::string extension = fsPath.has_extension()
? fsPath.extension().generic_string()
: std::string();
if (!extension.empty() && extension.front() == '.') {
return Containers::String(extension.substr(1).c_str());
}
return Containers::String(extension.c_str());
}
Containers::Array<Containers::String> BuildSingleExtensionList(
const char* sourceExtension,
const char* artifactExtension) {
Containers::Array<Containers::String> extensions;
extensions.PushBack(sourceExtension);
extensions.PushBack(artifactExtension);
return extensions;
}
bool MatchesAnyExtension(
const Containers::String& path,
const char* sourceExtension,
const char* artifactExtension) {
const Containers::String extension = GetPathExtension(path).ToLower();
return extension == sourceExtension || extension == artifactExtension;
}
Containers::String BuildDocumentDisplayName(
const Containers::String& path,
const UIDocumentModel& document) {
if (!document.displayName.Empty()) {
return document.displayName;
}
const std::filesystem::path fsPath(path.CStr());
const std::string stem = fsPath.stem().generic_string();
return stem.empty() ? path : Containers::String(stem.c_str());
}
template <typename TDocumentResource>
LoadResult BuildDocumentLoadResult(
const Containers::String& path,
UIDocumentCompileResult& compileResult) {
if (!compileResult.succeeded || !compileResult.document.valid) {
return LoadResult(compileResult.errorMessage);
}
auto* resource = new TDocumentResource();
IResource::ConstructParams params = {};
params.name = BuildDocumentDisplayName(path, compileResult.document);
params.path = compileResult.document.sourcePath.Empty() ? path : compileResult.document.sourcePath;
params.guid = ResourceGUID::Generate(params.path);
resource->Initialize(params);
resource->SetDocumentModel(std::move(compileResult.document));
return LoadResult(resource);
}
bool LoadDocumentWithKind(
const Containers::String& path,
UIDocumentKind kind,
const char* artifactExtension,
UIDocumentCompileResult& compileResult) {
const Containers::String extension = GetPathExtension(path).ToLower();
if (extension == artifactExtension) {
if (!LoadUIDocumentArtifact(path, kind, compileResult)) {
return false;
}
return true;
}
if (!CompileUIDocument(
UIDocumentCompileRequest{kind, path, GetUIDocumentDefaultRootTag(kind)},
compileResult)) {
return false;
}
return true;
}
} // namespace
Containers::Array<Containers::String> UIViewLoader::GetSupportedExtensions() const {
return BuildSingleExtensionList("xcui", "xcuiasset");
}
bool UIViewLoader::CanLoad(const Containers::String& path) const {
return MatchesAnyExtension(path, "xcui", "xcuiasset");
}
bool UIViewLoader::CompileDocument(const Containers::String& path, UIDocumentCompileResult& outResult) const {
return CompileUIDocument(
UIDocumentCompileRequest{UIDocumentKind::View, path, GetUIDocumentDefaultRootTag(UIDocumentKind::View)},
outResult);
}
LoadResult UIViewLoader::Load(const Containers::String& path, const ImportSettings* settings) {
(void)settings;
UIDocumentCompileResult compileResult = {};
if (!LoadDocumentWithKind(path, UIDocumentKind::View, "xcuiasset", compileResult)) {
return LoadResult(compileResult.errorMessage);
}
return BuildDocumentLoadResult<UIView>(path, compileResult);
}
Containers::Array<Containers::String> UIThemeLoader::GetSupportedExtensions() const {
return BuildSingleExtensionList("xctheme", "xcthemeasset");
}
bool UIThemeLoader::CanLoad(const Containers::String& path) const {
return MatchesAnyExtension(path, "xctheme", "xcthemeasset");
}
bool UIThemeLoader::CompileDocument(const Containers::String& path, UIDocumentCompileResult& outResult) const {
return CompileUIDocument(
UIDocumentCompileRequest{UIDocumentKind::Theme, path, GetUIDocumentDefaultRootTag(UIDocumentKind::Theme)},
outResult);
}
LoadResult UIThemeLoader::Load(const Containers::String& path, const ImportSettings* settings) {
(void)settings;
UIDocumentCompileResult compileResult = {};
if (!LoadDocumentWithKind(path, UIDocumentKind::Theme, "xcthemeasset", compileResult)) {
return LoadResult(compileResult.errorMessage);
}
return BuildDocumentLoadResult<UITheme>(path, compileResult);
}
Containers::Array<Containers::String> UISchemaLoader::GetSupportedExtensions() const {
return BuildSingleExtensionList("xcschema", "xcschemaasset");
}
bool UISchemaLoader::CanLoad(const Containers::String& path) const {
return MatchesAnyExtension(path, "xcschema", "xcschemaasset");
}
bool UISchemaLoader::CompileDocument(const Containers::String& path, UIDocumentCompileResult& outResult) const {
return CompileUIDocument(
UIDocumentCompileRequest{UIDocumentKind::Schema, path, GetUIDocumentDefaultRootTag(UIDocumentKind::Schema)},
outResult);
}
LoadResult UISchemaLoader::Load(const Containers::String& path, const ImportSettings* settings) {
(void)settings;
UIDocumentCompileResult compileResult = {};
if (!LoadDocumentWithKind(path, UIDocumentKind::Schema, "xcschemaasset", compileResult)) {
return LoadResult(compileResult.errorMessage);
}
return BuildDocumentLoadResult<UISchema>(path, compileResult);
}
} // namespace Resources
} // namespace XCEngine