Tighten material schema-driven binding path

This commit is contained in:
2026-04-04 17:02:56 +08:00
parent 672f25f9b7
commit a74c25b5ae
3 changed files with 185 additions and 6 deletions

View File

@@ -620,6 +620,93 @@ bool TryParseFloatListText(const std::string& text,
return outCount > 0;
}
Containers::String NormalizeMaterialLookupToken(const Containers::String& value) {
std::string normalized;
normalized.reserve(value.Length());
for (size_t index = 0; index < value.Length(); ++index) {
const unsigned char ch = static_cast<unsigned char>(value[index]);
if (std::isalnum(ch) != 0) {
normalized.push_back(static_cast<char>(std::tolower(ch)));
}
}
return Containers::String(normalized.c_str());
}
const ShaderPropertyDesc* FindShaderPropertyBySemantic(
const Shader* shader,
const Containers::String& semantic) {
if (shader == nullptr || semantic.Empty()) {
return nullptr;
}
const Containers::String normalizedSemantic = NormalizeMaterialLookupToken(semantic);
for (const ShaderPropertyDesc& property : shader->GetProperties()) {
if (NormalizeMaterialLookupToken(property.semantic) == normalizedSemantic) {
return &property;
}
}
return nullptr;
}
Containers::String ResolveLegacyMaterialSemanticAlias(
const Containers::String& propertyName,
JsonRawValueType rawType) {
const Containers::String normalizedName = NormalizeMaterialLookupToken(propertyName);
if (rawType == JsonRawValueType::Array ||
rawType == JsonRawValueType::Number) {
if (normalizedName == "basecolor" ||
normalizedName == "color") {
return Containers::String("BaseColor");
}
}
if (rawType == JsonRawValueType::String) {
if (normalizedName == "basecolortexture" ||
normalizedName == "maintex" ||
normalizedName == "maintexture" ||
normalizedName == "albedotexture" ||
normalizedName == "texture") {
return Containers::String("BaseColorTexture");
}
}
return Containers::String();
}
const ShaderPropertyDesc* ResolveShaderPropertyForMaterialKey(
const Shader* shader,
const Containers::String& propertyName,
JsonRawValueType rawType) {
if (shader == nullptr || propertyName.Empty()) {
return nullptr;
}
if (const ShaderPropertyDesc* property = shader->FindProperty(propertyName)) {
return property;
}
const Containers::String normalizedName = NormalizeMaterialLookupToken(propertyName);
for (const ShaderPropertyDesc& property : shader->GetProperties()) {
if (NormalizeMaterialLookupToken(property.name) == normalizedName) {
return &property;
}
}
if (const ShaderPropertyDesc* property = FindShaderPropertyBySemantic(shader, propertyName)) {
return property;
}
const Containers::String semanticAlias = ResolveLegacyMaterialSemanticAlias(propertyName, rawType);
if (!semanticAlias.Empty()) {
return FindShaderPropertyBySemantic(shader, semanticAlias);
}
return nullptr;
}
bool TryApplySchemaMaterialProperty(Material* material,
const ShaderPropertyDesc& shaderProperty,
const std::string& rawValue,
@@ -767,7 +854,7 @@ bool TryParseMaterialPropertiesObject(const std::string& objectText, Material* m
const Shader* shader = material->GetShader();
const ShaderPropertyDesc* shaderProperty =
shader != nullptr ? shader->FindProperty(propertyName) : nullptr;
ResolveShaderPropertyForMaterialKey(shader, propertyName, rawType);
if (shader != nullptr && shaderProperty == nullptr) {
return false;
}
@@ -943,8 +1030,17 @@ bool TryApplyTexturePath(Material* material,
return false;
}
const Shader* shader = material->GetShader();
const ShaderPropertyDesc* shaderProperty =
ResolveShaderPropertyForMaterialKey(shader, textureName, JsonRawValueType::String);
if (shader != nullptr && shaderProperty == nullptr) {
return false;
}
const Containers::String resolvedPropertyName =
shaderProperty != nullptr ? shaderProperty->name : textureName;
material->SetTexturePath(
textureName,
resolvedPropertyName,
ResolveSourceDependencyPath(texturePath, material->GetPath()));
return true;
}
@@ -978,7 +1074,9 @@ bool TryParseMaterialTextureBindings(const std::string& jsonText, Material* mate
return false;
}
TryApplyTexturePath(material, Containers::String(key), texturePath);
if (!TryApplyTexturePath(material, Containers::String(key), texturePath)) {
return false;
}
}
if (HasKey(jsonText, "textures")) {
@@ -987,13 +1085,19 @@ bool TryParseMaterialTextureBindings(const std::string& jsonText, Material* mate
return false;
}
bool appliedAllBindings = true;
if (!TryParseStringMapObject(
texturesObject,
[material](const Containers::String& name, const Containers::String& value) {
TryApplyTexturePath(material, name, value);
[material, &appliedAllBindings](const Containers::String& name, const Containers::String& value) {
if (appliedAllBindings) {
appliedAllBindings = TryApplyTexturePath(material, name, value);
}
})) {
return false;
}
if (!appliedAllBindings) {
return false;
}
}
return true;