Implement custom attribute flag handling for USD Crate writer

Add proper handling of the 'custom' attribute keyword in USDC format:
- Update ConvertAttributeToFields signature to accept is_custom parameter
- Extract custom flag from Property object before passing to conversion function
- Add 'custom' field to attribute spec when attribute is declared as custom
- Update both direct attribute conversion and variant property conversion
- Add debug output for custom flag handling

This resolves the TODO at stage-converter.cc:4786. Custom attributes are now
properly exported to the USDC crate format with the custom field indicator,
ensuring round-trip fidelity for custom attributes marked with the 'custom'
keyword in USD.

All 84 unit tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Syoyo Fujita
2025-11-20 02:43:34 +09:00
parent a155902c71
commit e741d71111
2 changed files with 13 additions and 8 deletions

View File

@@ -472,7 +472,7 @@ private:
/// Convert an Attribute to separate spec (proper USD format)
/// Creates a spec with SpecType::Attribute at parent_path.AppendProperty(attr_name)
bool ConvertAttributeToFields(const std::string& attr_name, const Attribute& attr,
const Path& parent_path, std::string* err);
const Path& parent_path, bool is_custom, std::string* err);
/// Convert a Relationship to separate spec (proper USD format)
/// Creates a spec with SpecType::Relationship at parent_path.AppendProperty(rel_name)

View File

@@ -4781,12 +4781,8 @@ bool CrateWriter::ConvertPropertyToFields(
return true;
} else if (prop.is_attribute()) {
// Convert attribute - creates separate spec, doesn't add to fields
bool success = ConvertAttributeToFields(prop_name, prop.get_attribute(), parent_path, err);
// TODO: Handle custom flag - needs to be added to the attribute spec, not parent prim
// For now, custom flag handling is deferred
return success;
// Pass the custom flag to be added to the attribute spec
return ConvertAttributeToFields(prop_name, prop.get_attribute(), parent_path, prop.has_custom(), err);
} else if (prop.is_relationship()) {
// Convert relationship - creates separate spec, doesn't add to fields
return ConvertRelationshipToFields(prop_name, prop.get_relationship(), parent_path, err);
@@ -4803,6 +4799,7 @@ bool CrateWriter::ConvertAttributeToFields(
const std::string& attr_name,
const Attribute& attr,
const Path& parent_path,
bool is_custom,
std::string* err) {
// Create separate spec for this attribute (proper USD Crate format)
@@ -4899,6 +4896,14 @@ bool CrateWriter::ConvertAttributeToFields(
<< " with " << metas.customData.value().size() << " entries\n";
}
// Add custom flag if attribute is custom
if (is_custom) {
crate::CrateValue custom_value;
custom_value.Set(true); // The field name "custom" with value true indicates custom attribute
attr_fields.push_back({"custom", custom_value});
std::cerr << "[ConvertAttributeToFields] Added custom flag for " << attr_name << "\n";
}
// Create the attribute spec
if (!AddSpec(attr_path, SpecType::Attribute, attr_fields, err)) {
if (err) *err = "Failed to add attribute spec: " + attr_path.full_path_name() + ": " + *err;
@@ -5190,7 +5195,7 @@ bool CrateWriter::ConvertVariantToFields(
// Handle variant properties based on their type
if (prop.is_attribute()) {
if (!ConvertAttributeToFields(prop_name, prop.get_attribute(), v_path, err)) {
if (!ConvertAttributeToFields(prop_name, prop.get_attribute(), v_path, prop.has_custom(), err)) {
if (err) *err = "Failed to convert variant attribute: " + prop_name;
return false;
}