From 545aa62a53ce3ae14a840375eaa89d7c73a87bd3 Mon Sep 17 00:00:00 2001 From: pixar-oss Date: Mon, 15 May 2023 16:36:10 -0700 Subject: [PATCH] USD API schema strength order and composition changes: 1. Authored API schemas are no longer the strongest schemas and are now instead the weakest API schemas when a USD prim definition is constructed. Most importantly this means that an authored API schema can no longer override properties that are already declared from a prim's typed schema. 2. The "default" and "hidden" fields of properties can now be composed from a weaker API if a stronger schema with the property has no opinion for those fields. 3. API schema override properties are no longer rejected for a variability mismatch; the override's variability is just ignored. This is because we don't check attribute variability when determining if a default value from a weaker schema can be composed in, so it doesn't makes sense to require a variability match for API schema override properties. 4. The result from UsdPrim::GetAppliedSchemas will no longer contain duplicate schema names when there are authored API schemas that are the same as any of the prim's built-in API schemas. A little background context on why we're only allowing "default" and "hidden" to compose right now: Our team discussed schema property definition composition and the suggestion was made that we start limited in what fields we compose since there are open questions about what to do with certain fields (like the allowedTokens listOp which likely wants more than "stronegest opinion wins" composition). So, the choice was to start with only the fields we know we want now. Allowing "default" was one of the main reasons we wanted schema property composition in the first place. Default is also required for a GenerativeProcedural prim with an authored applied HydraGenerativeProceduralAPI to still work as it did previously after making authored API schemas weaker than the prim type schema. Allowing "hidden" came up because of a internal Pixar desire to hide the "productName" property of the RenderProduct schema when our internal renderman API schemas are auto-applied to it. The productName value is expected to be generated at some point in the render submission pipeline so being able to hide it in the schema via auto-apply is a user experience win. Fixes #2336 (Internal change: 2275114) --- pxr/usd/usd/primDefinition.cpp | 234 ++- pxr/usd/usd/primDefinition.h | 40 +- pxr/usd/usd/schemaRegistry.cpp | 61 +- pxr/usd/usd/schemaRegistry.h | 3 +- .../usd/testenv/testUsdAppliedAPISchemas.py | 1261 ++++++++++------- .../resources/generatedSchema.usda | 196 ++- .../resources/plugInfo.json | 30 +- .../resources/schema.usda | 206 ++- .../usd/testenv/testUsdSchemaVersioning.py | 6 +- pxr/usdImaging/usdImaging/adapterManager.cpp | 22 +- 10 files changed, 1238 insertions(+), 821 deletions(-) diff --git a/pxr/usd/usd/primDefinition.cpp b/pxr/usd/usd/primDefinition.cpp index 6f3e8fd5e1..724b64d64b 100644 --- a/pxr/usd/usd/primDefinition.cpp +++ b/pxr/usd/usd/primDefinition.cpp @@ -234,29 +234,14 @@ bool UsdPrimDefinition::_PropertyTypesMatch( return false; } - // Compare variability - SdfVariability strongVariability, weakVariability; - strongLayerAndPath.HasField(SdfFieldKeys->Variability, &strongVariability); - weakLayerAndPath.HasField(SdfFieldKeys->Variability, &weakVariability); - if (weakVariability != strongVariability) { - TF_WARN("Property at path '%s' from stronger schema failed to override " - "property at path '%s' from weaker schema during schema prim " - "definition composition because their variability does not " - "match.", - strongLayerAndPath.path.GetText(), - weakLayerAndPath.path.GetText()); - return false; - } - // Done comparing if it's not an attribute. if (!specIsAttribute) { return true; } // Compare the type name field of the attributes. - TfToken strongTypeName, weakTypeName; - strongLayerAndPath.HasField(SdfFieldKeys->TypeName, &strongTypeName); - weakLayerAndPath.HasField(SdfFieldKeys->TypeName, &weakTypeName); + const TfToken strongTypeName = strongLayerAndPath.GetTypeName(); + const TfToken weakTypeName = weakLayerAndPath.GetTypeName(); if (weakTypeName != strongTypeName) { TF_WARN("Attribute at path '%s' with type name '%s' from stronger " "schema failed to override attribute at path '%s' with type " @@ -273,34 +258,14 @@ bool UsdPrimDefinition::_PropertyTypesMatch( void UsdPrimDefinition::_ComposePropertiesFromPrimDef( - const UsdPrimDefinition &weakerPrimDef, - bool useWeakerPropertyForTypeConflict) + const UsdPrimDefinition &weakerPrimDef) { _properties.reserve(_properties.size() + weakerPrimDef._properties.size()); - // Copy over property to path mappings from the weaker prim definition that - // aren't already in this prim definition. + // Copy over property to path mappings from the weaker prim definition, + // possibly creating composed definitions for properties that already exist. for (const auto &it : weakerPrimDef._propLayerAndPathMap) { - // Note that the prop name may be empty as we use the empty path to - // map to the spec containing the prim level metadata. We need to - // make sure we don't add the empty name to properties list if - // we successfully insert a metadata mapping. - auto insertResult = _propLayerAndPathMap.insert(it); - if (insertResult.second){ - if (!it.first.IsEmpty()) { - _properties.push_back(it.first); - } - } else { - // The property exists already. If we need to use the weaker - // property in the event of a property type conflict, then we - // check if the weaker property's type matches the existing, and - // replace the existing with the weaker property if the types - // do not match. - if (useWeakerPropertyForTypeConflict && - !_PropertyTypesMatch(insertResult.first->second, it.second)) { - insertResult.first->second = it.second; - } - } + _AddOrComposeProperty(it.first, it.second); } } @@ -311,19 +276,172 @@ UsdPrimDefinition::_ComposePropertiesFromPrimDefInstance( { _properties.reserve(_properties.size() + weakerPrimDef._properties.size()); - // Copy over property to path mappings from the weaker prim definition that - // aren't already in this prim definition. + // Copy over property to path mappings from the weaker prim definition, + // possibly creating composed definitions for properties that already exist. for (const auto &it : weakerPrimDef._propLayerAndPathMap) { // Apply the prefix to each property name before adding it. const TfToken instancedPropName = UsdSchemaRegistry::MakeMultipleApplyNameInstance( it.first, instanceName); - auto insertResult = _propLayerAndPathMap.emplace( - instancedPropName, it.second); - if (insertResult.second) { - _properties.push_back(instancedPropName); + _AddOrComposeProperty(instancedPropName, it.second); + } +} + +void UsdPrimDefinition::_AddOrComposeProperty( + const TfToken &propName, + const _LayerAndPath &layerAndPath) +{ + // Note that the prop name may be empty as we use the empty path to + // map to the spec containing the prim level metadata. We need to + // make sure we don't add the empty name to properties list if + // we successfully insert a metadata mapping. + auto insertResult = _propLayerAndPathMap.emplace(propName, layerAndPath); + if (insertResult.second){ + if (!propName.IsEmpty()) { + _properties.push_back(propName); + } + } else { + // The property exists already. Some fields may be able to be + // composed in from the new weaker property definition so we try to + // do that here. + _LayerAndPath &existingProp = insertResult.first->second; + if (SdfPropertySpecHandle composedPropSpec = + _CreatedComposedPropertyIfNeeded( + propName, existingProp, layerAndPath)) { + // If a composed property was created, replace the existing + // property definition. Otherwise, we just leave the existing + // property as is. + existingProp = { + get_pointer(composedPropSpec->GetLayer()), + composedPropSpec->GetPath()}; + } + } +} + +// We limit which fields are allowed to be composed in from a property defined +// in a weaker prim definition when a prim definition already has a property +// with the same name. +static +const TfTokenVector &_GetAllowedComposeFromWeakerPropertyFields() +{ + // Right now we only allow the "default" value (of attributes) and the + // "hidden" field to be composed from a weaker property. We may selectively + // expand this set of fields if it becomes necessary. + static const TfTokenVector fields = { + SdfFieldKeys->Default, + SdfFieldKeys->Hidden + }; + return fields; +} + +SdfPropertySpecHandle +UsdPrimDefinition::_FindOrCreatePropertySpecForComposition( + const TfToken &propName, + const _LayerAndPath &srcLayerAndPath) +{ + // Arbitrary prim path for this definition's composed property specs. Only + // this prim definition will use the layer we find or create here so we + // don't need unique prim spec names/paths. + static const SdfPath primPath("/ComposedProperties"); + + SdfPropertySpecHandle destProp; + + // If we have a composed layer, we can check if we've already created + // a spec for the composed property and return it if we have. Otherwise, + // we create a new layer for this prim definition to write its composed + // properties. + if (_composedPropertyLayer) { + if (destProp = _composedPropertyLayer->GetPropertyAtPath( + primPath.AppendProperty(propName))) { + return destProp; } + } else { + _composedPropertyLayer = SdfLayer::CreateAnonymous( + "schema-composed-properties"); + } + + SdfChangeBlock block; + + // Find or create the prim spec that will hold the composed property specs. + SdfPrimSpecHandle destPrim = _composedPropertyLayer->GetPrimAtPath(primPath); + if (!destPrim) { + destPrim = SdfPrimSpec::New( + _composedPropertyLayer, primPath.GetName(), SdfSpecifierDef); + } + + // Create a copy of the source attribute or relationship spec. We do this + // manually as the copy utils for Sdf specs are more generalized than what + // we need here. + const SdfSpecType specType = srcLayerAndPath.GetSpecType(); + if (specType == SdfSpecTypeAttribute) { + destProp = SdfAttributeSpec::New( + destPrim, + propName, + _composedPropertyLayer->GetSchema().FindOrCreateType( + srcLayerAndPath.GetTypeName()), + srcLayerAndPath.GetVariability()); + } else if (specType == SdfSpecTypeRelationship) { + destProp = SdfRelationshipSpec::New( + destPrim, + propName, + srcLayerAndPath.GetVariability()); + } else { + TF_CODING_ERROR("Cannot create a property spec from spec at layer " + "'%s' and path '%s'. The spec type is not an attribute or " + "relationship.", + srcLayerAndPath.layer->GetIdentifier().c_str(), + srcLayerAndPath.path.GetText()); + return destProp; + } + + // Copy all the metadata fields from the source spec to the new spec. + for (const TfToken &field : srcLayerAndPath.ListMetadataFields()) { + VtValue value; + srcLayerAndPath.HasField(field, &value); + destProp->SetField(field, value); + } + + return destProp; +} + +SdfPropertySpecHandle +UsdPrimDefinition::_CreatedComposedPropertyIfNeeded( + const TfToken &propName, + const _LayerAndPath &strongProp, + const _LayerAndPath &weakProp) +{ + SdfPropertySpecHandle destProp; + + // If the property types don't match, then we can't compose the properties + // together. + if (!_PropertyTypesMatch(strongProp, weakProp)) { + return destProp; + } + + for (const TfToken &field : _GetAllowedComposeFromWeakerPropertyFields()) { + // If the stronger property already has the field, skip it. + if (strongProp.HasField(field, nullptr)) { + continue; + } + + // Get the field's value from the weaker property. If it doesn't have + // the field, we skip it too. + VtValue weakValue; + if (!weakProp.HasField(field, &weakValue)) { + continue; + } + + // If we get here we need to compose a property definition so create a + // a copy of the stronger property if we haven't already and add the + // field. + if (!destProp) { + destProp = _FindOrCreatePropertySpecForComposition( + propName, strongProp); + } + destProp->SetField(field, weakValue); } + + return destProp; } void @@ -362,6 +480,15 @@ UsdPrimDefinition::_ComposeOverAndReplaceExistingProperty( } } + // There's one exception to override fields being stonger; an override + // cannot change the defined property's variability. So we may have to + // set the variability to match the defined property. + SdfVariability variability = defLayerAndPath->GetVariability(); + if (overLayerAndPath.GetVariability() != variability) { + overLayer->SetField( + overLayerAndPath.path, SdfFieldKeys->Variability, variability); + } + // With the override spec composed, set the definition's path for the // property to the composed override spec path. *defLayerAndPath = std::move(overLayerAndPath); @@ -371,8 +498,7 @@ bool UsdPrimDefinition::_ComposeWeakerAPIPrimDefinition( const UsdPrimDefinition &apiPrimDef, const TfToken &instanceName, - _FamilyAndInstanceToVersionMap *alreadyAppliedSchemaFamilyVersions, - bool allowDupes) + _FamilyAndInstanceToVersionMap *alreadyAppliedSchemaFamilyVersions) { // Helper for appending the given schemas to our applied schemas list while // checking for version conflicts. Returns true if the schemas are appended @@ -415,15 +541,7 @@ UsdPrimDefinition::_ComposeWeakerAPIPrimDefinition( // can undo the addition if we have to. _appliedAPISchemas.push_back(std::move(apiSchemaName)); newlyAddedFamilies.push_back(std::move(familyAndInstance)); - } else if (result.first->second == schemaInfo->version) { - // The family and instance were already added but the versions - // are the same. This is allowed. If we allow the API schema - // name to show up in the list more than once, we add it. - // Otherwise we safely skip it. - if (allowDupes) { - _appliedAPISchemas.push_back(std::move(apiSchemaName)); - } - } else { + } else if (result.first->second != schemaInfo->version) { // If we get here, the family and instance name were already // added with a different version of the schema. This is a // conflict and we will not add ANY of the schemas that are diff --git a/pxr/usd/usd/primDefinition.h b/pxr/usd/usd/primDefinition.h index 318ea75edf..497263c4b1 100644 --- a/pxr/usd/usd/primDefinition.h +++ b/pxr/usd/usd/primDefinition.h @@ -292,6 +292,18 @@ class UsdPrimDefinition return layer->HasFieldDictKey(path, fieldName, keyPath, value); } + SdfVariability GetVariability() const { + SdfVariability variability; + HasField(SdfFieldKeys->Variability, &variability); + return variability; + } + + TfToken GetTypeName() const { + TfToken typeName; + HasField(SdfFieldKeys->TypeName, &typeName); + return typeName; + } + USD_API TfTokenVector ListMetadataFields() const; }; @@ -325,6 +337,7 @@ class UsdPrimDefinition } UsdPrimDefinition() = default; + UsdPrimDefinition(const UsdPrimDefinition &) = default; USD_API void _IntializeForTypedSchema( @@ -358,16 +371,26 @@ class UsdPrimDefinition TfTokenVector _ListMetadataFields(const TfToken &propName) const; // Helpers for constructing the prim definition. - USD_API void _ComposePropertiesFromPrimDef( - const UsdPrimDefinition &weakerPrimDef, - bool useWeakerPropertyForTypeConflict = false); + const UsdPrimDefinition &weakerPrimDef); - USD_API void _ComposePropertiesFromPrimDefInstance( const UsdPrimDefinition &weakerPrimDef, const std::string &instanceName); + void _AddOrComposeProperty( + const TfToken &propName, + const _LayerAndPath &layerAndPath); + + SdfPropertySpecHandle _FindOrCreatePropertySpecForComposition( + const TfToken &propName, + const _LayerAndPath &srcLayerAndPath); + + SdfPropertySpecHandle _CreatedComposedPropertyIfNeeded( + const TfToken &propName, + const _LayerAndPath &strongProp, + const _LayerAndPath &weakProp); + USD_API void _ComposeOverAndReplaceExistingProperty( const TfToken &propName, @@ -381,10 +404,8 @@ class UsdPrimDefinition bool _ComposeWeakerAPIPrimDefinition( const UsdPrimDefinition &apiPrimDef, const TfToken &instanceName, - _FamilyAndInstanceToVersionMap *alreadyAppliedSchemaFamilyVersions, - bool allowDupes = false); + _FamilyAndInstanceToVersionMap *alreadyAppliedSchemaFamilyVersions); - USD_API static bool _PropertyTypesMatch( const _LayerAndPath &strongerProp, const _LayerAndPath &weakerProp); @@ -401,6 +422,11 @@ class UsdPrimDefinition // Cached list of property names. TfTokenVector _properties; + + // Layer that may be created for this prim definition if it's necessary to + // compose any new property specs for this definition from multiple + // property specs from other definitions. + SdfLayerRefPtr _composedPropertyLayer; }; PXR_NAMESPACE_CLOSE_SCOPE diff --git a/pxr/usd/usd/schemaRegistry.cpp b/pxr/usd/usd/schemaRegistry.cpp index a401a4662f..f00bf02461 100644 --- a/pxr/usd/usd/schemaRegistry.cpp +++ b/pxr/usd/usd/schemaRegistry.cpp @@ -1784,34 +1784,23 @@ UsdSchemaRegistry::BuildComposedPrimDefinition( return nullptr; } - std::unique_ptr composedPrimDef(new UsdPrimDefinition()); - _FamilyAndInstanceToVersionMap seenSchemaFamilyVersions; // Find the existing concrete typed prim definition for the prim's type. const UsdPrimDefinition *primDef = FindConcretePrimDefinition(primType); - if (!primDef) { - // Its perfectly valid for there to be no prim definition for the - // given prim type, in which case we compose API schemas into an empty - // prim definition. - _ComposeAPISchemasIntoPrimDefinition( - composedPrimDef.get(), appliedAPISchemas, &seenSchemaFamilyVersions, - /* allowDupes = */ true); - return composedPrimDef; - } - - // We do not initialize the prim definition like normal as we need to add - // authored API schemas and their properties before adding of the prim - // definition's properties. So here we just manually copy prim spec layer - // and path to the composed definition. - composedPrimDef->_primLayerAndPath = primDef->_primLayerAndPath; + // Make a copy of the typed prim definition to start. + // Its perfectly valid for there to be no prim definition for the + // given prim type, in which case we compose API schemas into an empty + // prim definition. + std::unique_ptr composedPrimDef( + primDef ? new UsdPrimDefinition(*primDef) : new UsdPrimDefinition()); // We do not allow authored API schemas to cause a different version of an // API schema to be added if an API schema in that family is already // built in to the prim type's prim definition. Thus, we have to populate // the seen schema family versions with API schemas found in the prim type's // definition before trying to add any authored API schemas. - for (const TfToken &apiSchema : primDef->_appliedAPISchemas) { + for (const TfToken &apiSchema : composedPrimDef->_appliedAPISchemas) { // Applied schemas may be single or multiple apply so we have to parse // the full schema name into a type and possibly an instance name. std::pair typeNameAndInstance = @@ -1824,35 +1813,10 @@ UsdSchemaRegistry::BuildComposedPrimDefinition( std::move(typeNameAndInstance), schemaInfo->version); } - // We compose in the new API schemas first as these API schema property - // opinions need to be stronger than the prim type's prim definition's - // opinions. + // We compose in the weaker authored API schemas. _ComposeAPISchemasIntoPrimDefinition( - composedPrimDef.get(), appliedAPISchemas, &seenSchemaFamilyVersions, - /* allowDupes = */ true); - - // When building a definition from authored applied API schemas we - // don't want API schemas applied on top of a typed prim definition to - // change any of property types from the typed prim definition. That's - // why we compose in the weaker typed prim definition with - // useWeakerPropertyForTypeConflict set to true. - // - // Note that the strongest API schema wins for a property type conflict - // amongst the authored applied API schemas themselves. But this - // "winning" property will be ignored if it tries to changed the type - // of an existing property in the typed prim definition. - composedPrimDef->_ComposePropertiesFromPrimDef( - *primDef, /* useWeakerPropertyForTypeConflict = */ true); - - // The prim type's prim definition may have its own built-in API - // schemas (which were already composed into its definition). We need - // to append these to applied API schemas list for our composed prim - // definition. - composedPrimDef->_appliedAPISchemas.insert( - composedPrimDef->_appliedAPISchemas.end(), - primDef->_appliedAPISchemas.begin(), - primDef->_appliedAPISchemas.end()); - + composedPrimDef.get(), appliedAPISchemas, &seenSchemaFamilyVersions); + return composedPrimDef; } @@ -1860,8 +1824,7 @@ void UsdSchemaRegistry::_ComposeAPISchemasIntoPrimDefinition( UsdPrimDefinition *primDef, const TfTokenVector &appliedAPISchemas, - _FamilyAndInstanceToVersionMap *seenSchemaFamilyVersions, - bool allowDupes) const + _FamilyAndInstanceToVersionMap *seenSchemaFamilyVersions) const { // Add in properties from each new applied API schema. Applied API schemas // are ordered strongest to weakest so we compose, in order, each weaker @@ -1891,7 +1854,7 @@ UsdSchemaRegistry::_ComposeAPISchemasIntoPrimDefinition( primDef->_ComposeWeakerAPIPrimDefinition( *apiSchemaDefInfo->primDef, instanceName, - seenSchemaFamilyVersions, allowDupes); + seenSchemaFamilyVersions); } } } diff --git a/pxr/usd/usd/schemaRegistry.h b/pxr/usd/usd/schemaRegistry.h index 92bb0a742d..d6418900ac 100644 --- a/pxr/usd/usd/schemaRegistry.h +++ b/pxr/usd/usd/schemaRegistry.h @@ -569,8 +569,7 @@ class UsdSchemaRegistry : public TfWeakBase { void _ComposeAPISchemasIntoPrimDefinition( UsdPrimDefinition *primDef, const TfTokenVector &appliedAPISchemas, - _FamilyAndInstanceToVersionMap *seenSchemaFamilyVersions, - bool allowDupes = false) const; + _FamilyAndInstanceToVersionMap *seenSchemaFamilyVersions) const; // Private class for helping initialize the schema registry. Defined // entirely in the implementation. Declared here for private access to the diff --git a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas.py b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas.py index 34a5c37996..b17c708bcf 100644 --- a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas.py +++ b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas.py @@ -389,18 +389,19 @@ def test_TypedPrimsOnStageWithBuiltinAPISchemas(self): "testAttr", "testRel"]) - # Add a new api schemas to the prim's metadata. + # Add a new API schema to the prim's metadata. typedPrim.ApplyAPI(self.MultiApplyAPIType, "garply") # Prim has the same type and now has both its original API schemas and # the new one. Note that the new schema was added using an explicit - # list op but was still prepended to the original list. Built-in API + # list op but was still appended to the original list. Built-in API # schemas cannot be deleted and any authored API schemas will always be - # prepended to the built-ins. + # appended to the built-ins. self.assertEqual(typedPrim.GetTypeName(), 'TestWithBuiltinAppliedSchema') self.assertEqual(typedPrim.GetAppliedSchemas(), - ["TestMultiApplyAPI:garply", - "TestSingleApplyAPI", "TestMultiApplyAPI:builtin"]) + ["TestSingleApplyAPI", + "TestMultiApplyAPI:builtin", + "TestMultiApplyAPI:garply",]) self.assertEqual(typedPrim.GetPrimTypeInfo().GetTypeName(), 'TestWithBuiltinAppliedSchema') # Note that prim type info does NOT contain the built-in applied API @@ -409,173 +410,89 @@ def test_TypedPrimsOnStageWithBuiltinAPISchemas(self): self.assertEqual(typedPrim.GetPrimTypeInfo().GetAppliedAPISchemas(), ["TestMultiApplyAPI:garply"]) - self.assertTrue(typedPrim.HasAPI(self.SingleApplyAPIType)) - self.assertTrue(typedPrim.HasAPI(self.MultiApplyAPIType)) - - # Properties have been expanded to include the new API schema - self.assertEqual(typedPrim.GetPropertyNames(), [ - "multi:builtin:bool_attr", - "multi:builtin:relationship", - "multi:builtin:token_attr", - "multi:garply:bool_attr", - "multi:garply:relationship", - "multi:garply:token_attr", - "single:bool_attr", - "single:relationship", - "single:token_attr", - "testAttr", - "testRel"]) - - # Property fallback comes from TestSingleApplyAPI - attr = typedPrim.GetAttribute("single:token_attr") - self.assertEqual(attr.Get(), "bar") - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback comes from TestMultiApplyAPI - attr = typedPrim.GetAttribute("multi:garply:bool_attr") - self.assertEqual(attr.Get(), True) - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback actually comes from TestWithBuiltinAppliedSchema as - # the typed schema overrides this property from its built-in API schema. - attr = typedPrim.GetAttribute("multi:builtin:bool_attr") - self.assertEqual(attr.Get(), False) - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback comes from TestWithBuiltinAppliedSchema - attr = typedPrim.GetAttribute("testAttr") - self.assertEqual(attr.Get(), "foo") - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - - # Metadata "hidden" has a fallback value defined in - # TestWithBuiltinAppliedSchema. It will be returned by GetMetadata and - # GetAllMetadata but will return false for queries about whether it's - # authored - self.assertEqual(typedPrim.GetAllMetadata()["hidden"], False) - self.assertEqual(typedPrim.GetMetadata("hidden"), False) - self.assertFalse(typedPrim.HasAuthoredMetadata("hidden")) - self.assertFalse("hidden" in typedPrim.GetAllAuthoredMetadata()) - - # Documentation metadata comes from prim type definition even with API - # schemas applied. - self.assertEqual(typedPrim.GetMetadata("documentation"), - "Test with built-in API schemas") - - def test_TypedPrimsOnStageWithBuiltinReapply(self): - """ - Tests the fallback properties of typed prims on a stage when the same - API schemas are applied again to a prim whose type already has applied - API schemas. - """ - stage = Usd.Stage.CreateInMemory() - - # Add a typed prim. It has API schemas already from its prim definition - # and has properties from both its type and its APIs. - typedPrim = stage.DefinePrim("/TypedPrim", "TestWithBuiltinAppliedSchema") - self.assertEqual(typedPrim.GetTypeName(), 'TestWithBuiltinAppliedSchema') - self.assertEqual(typedPrim.GetAppliedSchemas(), - ["TestSingleApplyAPI", "TestMultiApplyAPI:builtin"]) - self.assertEqual(typedPrim.GetPrimTypeInfo().GetTypeName(), - 'TestWithBuiltinAppliedSchema') - # Note that prim type info does NOT contain the built-in applied API - # schemas from the concrete type's prim definition as these are not part - # of the type identity. - self.assertEqual(typedPrim.GetPrimTypeInfo().GetAppliedAPISchemas(), []) - - self.assertTrue(typedPrim.HasAPI(self.SingleApplyAPIType)) - self.assertTrue(typedPrim.HasAPI(self.MultiApplyAPIType)) - self.assertEqual(typedPrim.GetPropertyNames(), [ - "multi:builtin:bool_attr", - "multi:builtin:relationship", - "multi:builtin:token_attr", - "single:bool_attr", - "single:relationship", - "single:token_attr", - "testAttr", - "testRel"]) - # Property fallback comes from TestSingleApplyAPI - attr = typedPrim.GetAttribute("single:token_attr") - self.assertEqual(attr.Get(), "bar") - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback actually comes from TestTypedSchema as the typed - # schema overrides this property from its built-in API schema. - attr = typedPrim.GetAttribute("multi:builtin:bool_attr") - self.assertEqual(attr.Get(), False) - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback comes from TestTypedSchema - attr = typedPrim.GetAttribute("testAttr") - self.assertEqual(attr.Get(), "foo") - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - - # Add the built-in api schemas again to the prim's metadata. + # Helper for verifying the same expected prim data before and after + # applying redundant API schemas. + def _VerifyExpectedPrimData(prim): + self.assertTrue(prim.HasAPI(self.SingleApplyAPIType)) + self.assertTrue(prim.HasAPI(self.MultiApplyAPIType)) + + # Properties have been expanded to include the new API schema + self.assertEqual(prim.GetPropertyNames(), [ + "multi:builtin:bool_attr", + "multi:builtin:relationship", + "multi:builtin:token_attr", + "multi:garply:bool_attr", + "multi:garply:relationship", + "multi:garply:token_attr", + "single:bool_attr", + "single:relationship", + "single:token_attr", + "testAttr", + "testRel"]) + + # Property fallback comes from TestSingleApplyAPI + attr = prim.GetAttribute("single:token_attr") + self.assertEqual(attr.Get(), "bar") + self.assertEqual(attr.GetResolveInfo().GetSource(), + Usd.ResolveInfoSourceFallback) + # Property fallback comes from TestMultiApplyAPI + attr = prim.GetAttribute("multi:garply:bool_attr") + self.assertEqual(attr.Get(), True) + self.assertEqual(attr.GetResolveInfo().GetSource(), + Usd.ResolveInfoSourceFallback) + # Property fallback actually comes from TestWithBuiltinAppliedSchema as + # the typed schema overrides this property from its built-in API schema. + attr = prim.GetAttribute("multi:builtin:bool_attr") + self.assertEqual(attr.Get(), False) + self.assertEqual(attr.GetResolveInfo().GetSource(), + Usd.ResolveInfoSourceFallback) + # Property fallback comes from TestWithBuiltinAppliedSchema + attr = prim.GetAttribute("testAttr") + self.assertEqual(attr.Get(), "foo") + self.assertEqual(attr.GetResolveInfo().GetSource(), + Usd.ResolveInfoSourceFallback) + + # Metadata "hidden" has a fallback value defined in + # TestWithBuiltinAppliedSchema. It will be returned by GetMetadata and + # GetAllMetadata but will return false for queries about whether it's + # authored + self.assertEqual(prim.GetAllMetadata()["hidden"], False) + self.assertEqual(prim.GetMetadata("hidden"), False) + self.assertFalse(prim.HasAuthoredMetadata("hidden")) + self.assertFalse("hidden" in typedPrim.GetAllAuthoredMetadata()) + + # Documentation metadata comes from prim type definition even with API + # schemas applied. + self.assertEqual(prim.GetMetadata("documentation"), + "Test with built-in API schemas") + + # Verify the prim has all the data we expect. + _VerifyExpectedPrimData(typedPrim) + + # Now explicitly apply the same built-in API schemas again to the prim + # so they show up as authored schemas. typedPrim.ApplyAPI(self.MultiApplyAPIType, "builtin") typedPrim.ApplyAPI(self.SingleApplyAPIType) - # Prim has the same type and now has both its original API schemas and - # plus the same schemas again appended to the list (i.e. both schemas - # now show up twice). - self.assertEqual(typedPrim.GetTypeName(), 'TestWithBuiltinAppliedSchema') - self.assertEqual(typedPrim.GetAppliedSchemas(), - ["TestMultiApplyAPI:builtin", "TestSingleApplyAPI", - "TestSingleApplyAPI", "TestMultiApplyAPI:builtin"]) - self.assertEqual(typedPrim.GetPrimTypeInfo().GetTypeName(), - 'TestWithBuiltinAppliedSchema') - # Note that prim type info does NOT contain the built-in applied API - # schemas from the concrete type's prim definition as these are not part - # of the type identity. + # The prim type info now DOES contain the built-in applied API + # schemas in the order we applied them now that they are explicitly + # authored schemas. These schemas are now part of the prim's type ID. self.assertEqual(typedPrim.GetPrimTypeInfo().GetAppliedAPISchemas(), - ["TestMultiApplyAPI:builtin", "TestSingleApplyAPI"]) - - self.assertTrue(typedPrim.HasAPI(self.SingleApplyAPIType)) - self.assertTrue(typedPrim.HasAPI(self.MultiApplyAPIType)) - - # The list of properties hasn't changed as there are no "new" schemas, - # however the defaults may have changed. - self.assertEqual(typedPrim.GetPropertyNames(), [ - "multi:builtin:bool_attr", - "multi:builtin:relationship", - "multi:builtin:token_attr", - "single:bool_attr", - "single:relationship", - "single:token_attr", - "testAttr", - "testRel"]) - - # Property fallback comes from TestSingleApplyAPI - no change - attr = typedPrim.GetAttribute("single:token_attr") - self.assertEqual(attr.Get(), "bar") - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback has now changed from False to True as the - # TestTypedSchema originally overrode the fallback from - # TestMultiApplyAPI. But by applying TestMultiApplyAPI again with the - # same instance, we've re-overridden the attribute getting the default - # from the applied schema. - attr = typedPrim.GetAttribute("multi:builtin:bool_attr") - self.assertEqual(attr.Get(), True) - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - # Property fallback comes from TestTypedSchema - no change - attr = typedPrim.GetAttribute("testAttr") - self.assertEqual(attr.Get(), "foo") - self.assertEqual(attr.GetResolveInfo().GetSource(), - Usd.ResolveInfoSourceFallback) - - # Prim metadata is unchanged from the case above as there is still - # no way for applied API schemas to impart prim metadata defaults. - self.assertEqual(typedPrim.GetAllMetadata()["hidden"], False) - self.assertEqual(typedPrim.GetMetadata("hidden"), False) - self.assertFalse(typedPrim.HasAuthoredMetadata("hidden")) - self.assertFalse("hidden" in typedPrim.GetAllAuthoredMetadata()) - - # Documentation metadata comes from prim type definition even with API - # schemas applied. - self.assertEqual(typedPrim.GetMetadata("documentation"), - "Test with built-in API schemas") + ["TestMultiApplyAPI:garply", + "TestMultiApplyAPI:builtin", + "TestSingleApplyAPI"]) + + # However, the actual list of applied schemas on the prim has not + # changed at all because these two authored schemas are already applied + # as built-ins and don't get reapplied in the composed prim definition. + self.assertEqual(typedPrim.GetAppliedSchemas(), + ["TestSingleApplyAPI", + "TestMultiApplyAPI:builtin", + "TestMultiApplyAPI:garply",]) + + # Verify the prim has all the same expected data as before we reapplied + # the built-ins. + _VerifyExpectedPrimData(typedPrim) @unittest.skipIf(Tf.GetEnvSetting('USD_DISABLE_AUTO_APPLY_API_SCHEMAS'), "Auto apply API schemas are disabled") @@ -1423,10 +1340,9 @@ def _VerifyAttrValues(prim, expectedAttrValues): "TestNestedInnerSingleApplyAPI"]) # The composed applied API schemas are fully expanded from both authored - # APIs and will contain duplicates. We don't check for duplicates that - # occur because different authored APIs include the same applied schema - # even though we do remove duplicates when determining what API schemas - # a single API includes. + # APIs but will not contain duplicates. Thus, the authored + # TestNestedInnerSingleApplyAPI is redundant and doesn't add any schemas + # that weren't already added by expanding TestNestedOuterSingleApplyAPI self.assertEqual(outerSinglePrim.GetTypeName(), '') expectedAPISchemas = [ # API schemas from expanded TestNestedOuterSingleApplyAPI @@ -1434,12 +1350,8 @@ def _VerifyAttrValues(prim, expectedAttrValues): "TestMultiApplyAPI:foo", "TestNestedInnerSingleApplyAPI", "TestSingleApplyAPI", - "TestMultiApplyAPI:bar", - # API schemas from expanded TestNestedInnerSingleApplyAPI (even - # though they're already in the list) - "TestNestedInnerSingleApplyAPI", - "TestSingleApplyAPI", - "TestMultiApplyAPI:bar"] + "TestMultiApplyAPI:bar" + ] self.assertEqual(outerSinglePrim.GetAppliedSchemas(), expectedAPISchemas) @@ -1463,12 +1375,11 @@ def _VerifyAttrValues(prim, expectedAttrValues): "TestNestedInnerSingleApplyAPI", "TestSingleApplyAPI", "TestMultiApplyAPI:bar", - # API schemas from expanded TestNestedOuterSingleApplyAPI + # API schemas from expanded TestNestedOuterSingleApplyAPI excluding + # a re-expansion of TestNestedInnerSingleApplyAPI "TestNestedOuterSingleApplyAPI", - "TestMultiApplyAPI:foo", - "TestNestedInnerSingleApplyAPI", - "TestSingleApplyAPI", - "TestMultiApplyAPI:bar"] + "TestMultiApplyAPI:foo" + ] self.assertEqual(outerSinglePrim.GetAppliedSchemas(), expectedAPISchemas) @@ -2496,367 +2407,631 @@ def test_APISchemasAutoAppliedToAPISchemas_AutoApplyDisabled(self): @unittest.skipIf(Tf.GetEnvSetting('USD_DISABLE_AUTO_APPLY_API_SCHEMAS'), "Auto apply API schemas are disabled") - def test_PropertyTypeConflicts(self): + def test_PropertyComposition(self): """ - Test the resolution of property type conflicts between prim type and - API schema prim definitions when API schemas are applied to prims. + Test the composition of properties in a prim definition built from API + schemas that define properties with the same name. """ stage = Usd.Stage.CreateInMemory() - # Helper for verifying the attribute types and computed values of - # any arbitrary set of attributes on the prim. The arguments are the - # prim followed by any number of keyword arguments of the form: - # = (, , ) - # For each keyword arg, it verifies that the prim has an attribute - # named whose typeName computes to and - # computed valued computes to . Also verifies that the - # attribute's documentation matches - def _VerifyAttrTypes(prim, **kwargs): - for name, (attrTypeNameStr, attrValue, docStr) in kwargs.items(): - attr = prim.GetAttribute(name) - self.assertEqual(attr.GetTypeName(), attrTypeNameStr) - self.assertEqual(attr.Get(), attrValue) - self.assertEqual(attr.GetDocumentation(), docStr) - - # Helper for verifying that an arbitrary set of properties is or isn't - # a relationship. The arguments are the prim followed by any number of - # keyword arguments of the form: - # = (, ) - # For each keyword arg, it verifies that the prim has a property - # named that is a relationship iff is - # True. Also verifies that the property's documentation matches - def _VerifyIsRel(prim, **kwargs): - for name, (isRelationship, docStr) in kwargs.items(): - prop = prim.GetProperty(name) - self.assertTrue(prop) - if isRelationship: - self.assertTrue(prim.GetRelationship(name)) + # Helper for verifying the expected values field for an attribute named + # by attrName on the the given prim. + def _VerifyAttribute(prim, attrName, typeName, + doc = "", + default = None, + hidden = None, + variability = Sdf.VariabilityVarying, + **kwargs): + # Get the attribute by name + attr = prim.GetAttribute(attrName) + self.assertTrue(attr) + + # Verify type name, variability, and doc string. + self.assertEqual(attr.GetTypeName(), typeName) + self.assertEqual(attr.GetVariability(), variability) + self.assertEqual(attr.GetDocumentation(), doc) + + # The attribute may or may not be expected to have default value; + # verify the expected default or lack thereof. + if default is None: + self.assertIsNone(attr.Get()) + else: + self.assertEqual(attr.Get(), default) + + # The attribute may or may not be expected to have an opinion about + # hidden; verify the expected value of hidden. + if hidden is None: + self.assertIsNone(attr.GetMetadata("hidden")) + self.assertFalse(attr.IsHidden()) + else: + self.assertIsNotNone(attr.GetMetadata("hidden")) + self.assertEqual(attr.IsHidden(), hidden) + + # Test the presence (or lack thereof) of addtional metadata fields + # as need for test cases that provide them. + for key, value in kwargs.items(): + if value is None: + self.assertIsNone(attr.GetMetadata(key)) else: - self.assertFalse(prim.GetRelationship(name)) - self.assertEqual(prop.GetDocumentation(), docStr) + self.assertEqual(attr.GetMetadata(key), value) # We've defined 3 API schema types for applying directly to a prim - authoredOneAPIName = "TestPropTypeConflictAuthoredOneAPI" - authoredTwoAPIName = "TestPropTypeConflictAuthoredTwoAPI" - nestedAPIName = "TestPropTypeConflictNestedAuthoredAPI" - # We also typed prim type for this test case that includes a separate - # built-in API schema type. - conflictPrimTypeName = "TestPropTypeConflictsPrim" - builtinAPIName = "TestPropTypeConflictBuiltinAPI" + oneAPIName = "TestPropCompOneAPI" + twoAPIName = "TestPropCompTwoAPI" + nestedAPIName = "TestPropCompNestedAPI" + # We also defined a prim type for this test case that includes a + # separate built-in API schema type. + compPrimTypeName = "TestPropCompsPrim" # Each of the defined schema types above uses a single doc string for # all of it properties which we can use to help verify which schemas # the property definitions come from. - authoredOneAPIDocStr = "From TestPropTypeConflictAuthoredOneAPI" - authoredTwoAPIDocStr = "From TestPropTypeConflictAuthoredTwoAPI" - nestedAPIDocStr = "From TestPropTypeConflictNestedAuthoredAPI" - conflictPrimTypeDocStr = "From TestPropTypeConflictsPrim" - builtinAPIDocStr = "From TestPropTypeConflictBuiltinAPI" - - # Test 1: Prim with no type name; apply the authoredOneAPI and - # authoredTwoAPI schemas in that strength order. - untypedPrim = stage.DefinePrim("/UntypedPrim") - untypedPrim.AddAppliedSchema(authoredOneAPIName) - untypedPrim.AddAppliedSchema(authoredTwoAPIName) - self.assertEqual(untypedPrim.GetAppliedSchemas(), - [authoredOneAPIName, - authoredTwoAPIName]) - - # Only the authoredOneAPI defines attr1 and attr2 - # Only the authoredTwoAPI defines attr3 and attr4 - # Both define attr5 and attr6, so authoredOneAPI's version of those - # attributes are used since it's stronger. - _VerifyAttrTypes(untypedPrim, - attr1 = ("int", 0, authoredOneAPIDocStr), - attr2 = ("double", 0.0, authoredOneAPIDocStr), - attr3 = ("int", 10, authoredTwoAPIDocStr), - attr4 = ("string", "foo", authoredTwoAPIDocStr), - attr5 = ("point3f", Gf.Vec3f(0, 0, 0), authoredOneAPIDocStr), - attr6 = ("int", 20, authoredOneAPIDocStr)) - # Both define rel1 and rel2, but since authoredOneAPI is stronger, it wins - # and only rel2 is a relationship. - _VerifyIsRel(untypedPrim, - rel1 = (False, authoredOneAPIDocStr), - rel2 = (True, authoredOneAPIDocStr)) - - # Test 2: Prim with no type name; apply the authoredTwoAPI and builtAPI - # schemas in that strength order. This is the reverse order of Test 1 - untypedPrim = stage.DefinePrim("/UntypedPrim2") - untypedPrim.AddAppliedSchema(authoredTwoAPIName) - untypedPrim.AddAppliedSchema(authoredOneAPIName) - self.assertEqual(untypedPrim.GetAppliedSchemas(), - [authoredTwoAPIName, - authoredOneAPIName]) - - # Only the authoredOneAPI defines attr1 and attr2 (same as Test 1) - # Only the authoredTwoAPI defines attr3 and attr4 (same as Test 1) - # Both define attr5 and attr6, but now authoredTwoAPI is stronger so - # its version of those attributes are used. Note that this leads to a - # different type and default value for attr5 and just a different - # default value for attr6. - _VerifyAttrTypes(untypedPrim, - attr1 = ("int", 0, authoredOneAPIDocStr), - attr2 = ("double", 0.0, authoredOneAPIDocStr), - attr3 = ("int", 10, authoredTwoAPIDocStr), - attr4 = ("string", "foo", authoredTwoAPIDocStr), - attr5 = ("float3", Gf.Vec3f(1, 2, 3), authoredTwoAPIDocStr), - attr6 = ("int", 10, authoredTwoAPIDocStr)) - # Both define rel1 and rel2, but now since authoredTwoAPI is stronger, - # it wins and only rel1 is a relationship (opposite of Test 1). - _VerifyIsRel(untypedPrim, - rel1 = (True, authoredTwoAPIDocStr), - rel2 = (False, authoredTwoAPIDocStr)) - - # Test 3: Prim with type name set to the conflictPrimType; no authored - # applied API schemas. The conflictPrimType has a single built-in API - # schema builtinAPI. - prim = stage.DefinePrim("/TypedPrim", conflictPrimTypeName) + oneAPIDoc = "From TestPropCompOneAPI" + twoAPIDoc = "From TestPropCompTwoAPI" + nestedAPIDoc = "From TestPropCompNestedAPI" + primDoc = "From TestPropCompsPrim" + + # Test 1: Prim with no type name; apply the OneAPI schema. + prim = stage.DefinePrim("/UntypedPrim") + prim.AddAppliedSchema(oneAPIName) self.assertEqual(prim.GetAppliedSchemas(), - [builtinAPIName]) - - # The conflictPrimType schema defines all of attr1-6 attributes EXCEPT - # attr4. It also defines rel1 and rel2. So outside of attr4, the typed - # schema's version of these properties are used. - # For attr4, it is defined in the builtinAPI schema so that attribute's - # opinion comes from the builtinAPI. Note that builtinAPI does define - # attr2, rel1, and rel2 (all with different types than the - # conflictPrimType schema) but the stronger conflictPrimType still wins - # over its built-in APIs. - _VerifyAttrTypes(prim, - attr1 = ("int", 1, conflictPrimTypeDocStr), - attr2 = ("int", 2, conflictPrimTypeDocStr), - attr3 = ("int", 3, conflictPrimTypeDocStr), - attr4 = ("int", 4, builtinAPIDocStr), - attr5 = ("color3f", Gf.Vec3f(1, 1, 1), conflictPrimTypeDocStr), - attr6 = ("int", 6, conflictPrimTypeDocStr)) - _VerifyIsRel(prim, - rel1 = (True, conflictPrimTypeDocStr), - rel2 = (False, conflictPrimTypeDocStr)) - - # Test 4: Take the same prim from Test 3 above, with type name set to - # the conflictPrimType, and author authoredOneAPI and authoredTwoAPI - # applied schemas in that strength order (like in Test 1). - prim.AddAppliedSchema(authoredOneAPIName) - prim.AddAppliedSchema(authoredTwoAPIName) + [oneAPIName]) + + # Verify the expected attributes all match the attributes as defined in + # OneAPI schema. + _VerifyAttribute(prim, "oneAttr1", "int", doc = oneAPIDoc, + default = 1, + hidden = False) + _VerifyAttribute(prim, "oneAttr2", "double", doc = oneAPIDoc, + default = 1.0) + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = oneAPIDoc, + hidden = False) + _VerifyAttribute(prim, "oneAttr4", "token", doc = oneAPIDoc) + _VerifyAttribute(prim, "oneAttr5", "token", doc = oneAPIDoc) + + _VerifyAttribute(prim, "twoAttr1", "int", doc = oneAPIDoc, + default = 1, + hidden = True) + _VerifyAttribute(prim, "twoAttr2", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True) + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = oneAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = True) + _VerifyAttribute(prim, "twoAttr4", "token", doc = oneAPIDoc, + default = "one", + hidden = True) + _VerifyAttribute(prim, "twoAttr5", "float", doc = oneAPIDoc, + default = 1.0, + hidden = True) + + _VerifyAttribute(prim, "nestedAttr1", "string", doc = oneAPIDoc, + default = "one", + hidden = True) + _VerifyAttribute(prim, "nestedAttr2", "int", doc = oneAPIDoc, + hidden = True) + _VerifyAttribute(prim, "nestedAttr3", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True), + _VerifyAttribute(prim, "nestedAttr4", "point3f", doc = oneAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = False) + + # This attribute is to verify that only default value and hidden + # metadata is composed from a weaker property definition. With OneAPI + # applied the otherMetadataAttr is defined with just its type name; no + # other metadata like default, documentation, displayGroup, displayName, + # allowedTokens is defined. + _VerifyAttribute(prim, "otherMetadataAttr", "token", + displayGroup = None, + displayName = None, + allowedTokens = None) + + # Test 2: Apply the TwoAPI to test case 1 prim. The prim now has + # OneAPI and TwoAPI applied in that strength order. + prim.AddAppliedSchema(twoAPIName) self.assertEqual(prim.GetAppliedSchemas(), - [authoredOneAPIName, - authoredTwoAPIName, - builtinAPIName]) - - _VerifyAttrTypes(prim, - # attr1 is defined in authoredOneAPI which is now the strongest - # opinion. Since its type name matches attr1's type name in the prim - # type's definition, it can be used for attr1 in the composed prim - # definition. - attr1 = ("int", 0, authoredOneAPIDocStr), - # attr2 is defined in authoredOneAPI which would be the strongest - # opinion. However, its type name is "double" which doesn't match - # the existing prim type's definition of the attribute which has it - # as "int". We use the prim type's definition for this attribute - # ignoring the API schema. - attr2 = ("int", 2, conflictPrimTypeDocStr), - # attr3 is defined in authoredTwoAPI (and not authoredOneAPI) which - # makes it the strongest opinion. Since its type name matches - # attr3's type name in the prim type's definition, it can be used - # for attr3 in the composed prim definition. - attr3 = ("int", 10, authoredTwoAPIDocStr), - # attr4 is defined in authoredTwoAPI (and not authoredOneAPI) which - # would be the strongest opinion. However, its type name is "string" - # which doesn't match the existing prim type's definition of the - # attribute which has it as "int". We use the prim type's definition - # for this attribute ignoring the API schema. Note the prim type's - # definition actually gets its opinion on attr4 from the builtinAPI - # (as the typed schema itself doesn't define attr4). The builtinAPI - # attr4 opinion is part of the composed prim type definition which - # is type wins over any applied API schemas authored over the prim. - attr4 = ("int", 4, builtinAPIDocStr), - # attr5 is defined in both authoredOneAPI and authoredTwoAPI which - # makes authoredOneAPI the strongest opiniion. However its type of - # "point3f" doesn't match the prim type's opinion of the type name - # "color3f". Even though the default values for these types are - # stored as GfVec3f, the type name mismatch means we still used the - # prim type's version in the composed prim definition. - attr5 = ("color3f", Gf.Vec3f(1, 1, 1), conflictPrimTypeDocStr), - # attr6 is defined in both authoredOneAPI and authoredTwoAPI which - # makes authoredOneAPI the strongest opiniion. And since its type - # name matches the prim type definition's attr6 type name, we use - # the attr6 from authoredOneAPI. - attr6 = ("int", 20, authoredOneAPIDocStr)) - # For rel1 and rel2, authoredOneAPI, authoredTwoAPI and the prim type - # all define them both. Both authoredTwoAPI and the prim type definition - # define rel1 as a relationship and rel2 as an attribute, but - # authoredOneAPI defines the reverse with rel2 as the relationship. - # Since authoredOneAPI is stronger than authoredTwoAPI, its opinions for - # these properties override the ones from authoredTwoAPI. However, since - # the property types of these strongest opinions don't match match the - # property types from the prim type definition, they fall back to the - # prim type definition's opinions of these properties in the composed - # prim definition. - _VerifyIsRel(prim, - rel1 = (True, conflictPrimTypeDocStr), - rel2 = (False, conflictPrimTypeDocStr)) + [oneAPIName, + twoAPIName]) + + # Both API schemas define the same attributes but with different + # field values. Some of these properties will be composed from fields + # in both API schemas with OneAPI's opinions being stronger than + # TwoAPI's. + + # OneAPI has opinions for both "default" and "hidden", so TwoAPI will + # not contribute opinions to this attribute. + _VerifyAttribute(prim, "oneAttr1", "int", doc = oneAPIDoc, + default = 1, + hidden = False) + # OneAPI has no opinion about "hidden", but TwoAPI has hidden = true + # so hidden = true is composed in.. + _VerifyAttribute(prim, "oneAttr2", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True) + # OneAPI has no opinion about "default", but TwoAPI has it set to + # (2,2,2) so default = (2,2,2) is composed in. + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = oneAPIDoc, + default = (2.0, 2.0, 2.0), + hidden = False) + # OneAPI has no opinion about "default" or "hidden", but TwoAPI + # has default = "two" and hidden = true so both are composed in. + _VerifyAttribute(prim, "oneAttr4", "token", doc = oneAPIDoc, + default = "two", + hidden = True) + # OneAPI has no opinion about default or hidden, but TwoAPI has this + # attribute as typeName = "string". This is a typeName conflict with + # OneAPI's typeName = "token", so all of TwoAPI's opinions are ignored. + _VerifyAttribute(prim, "oneAttr5", "token", doc = oneAPIDoc) + + # OneAPI has opinions for both "default" and "hidden" for all of + # these attributes, so TwoAPI will not contribute opinions to any of + # these attributes. + _VerifyAttribute(prim, "twoAttr1", "int", doc = oneAPIDoc, + default = 1, + hidden = True) + _VerifyAttribute(prim, "twoAttr2", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True) + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = oneAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = True) + _VerifyAttribute(prim, "twoAttr4", "token", doc = oneAPIDoc, + default = "one", + hidden = True) + _VerifyAttribute(prim, "twoAttr5", "float", doc = oneAPIDoc, + default = 1.0, + hidden = True) + + # For these four attributes, OneAPI has opinions for both "default" + # and "hidden" with the exception of "nestedAttr2" (for which OneAPI + # has no opinion for "default"). Thus TwoAPI only contributes + # default = 2 to "nestedAttr2", otherwise everything else comes from + # OneAPI. + _VerifyAttribute(prim, "nestedAttr1", "string", doc = oneAPIDoc, + default = "one", + hidden = True) + _VerifyAttribute(prim, "nestedAttr2", "int", doc = oneAPIDoc, + default = 2, + hidden = True) + _VerifyAttribute(prim, "nestedAttr3", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True) + _VerifyAttribute(prim, "nestedAttr4", "point3f", doc = oneAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = False) + + # This attribute is to verify that only default value and hidden + # metadata is composed from a weaker property definition. With OneAPI + # and TwoAPI both applied in that order, the default value and value + # for hidden come through from TwoAPI since OneAPI. TwoAPI DOES define + # additional metadata, like displayName, documentation, allowedTokens, + # etc., that OneAPI does not define, however this metadata will not be + # composed. + _VerifyAttribute(prim, "otherMetadataAttr", "token", + default = "two", + hidden = False, + displayGroup = None, + displayName = None, + allowedTokens = None) + + # Test 3: New prim with no type name; apply only the TwoAPI schema. + prim = stage.DefinePrim("/UntypedPrim2") + prim.AddAppliedSchema(twoAPIName) + self.assertEqual(prim.GetAppliedSchemas(), + [twoAPIName]) + + # Verify the expected attributes all match the attributes as defined in + # TwoAPI schema. + _VerifyAttribute(prim, "oneAttr1", "int", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2, + hidden = True) + _VerifyAttribute(prim, "oneAttr2", "double", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2.0, + hidden = True) + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = (2.0, 2.0, 2.0), + hidden = True) + _VerifyAttribute(prim, "oneAttr4", "token", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + _VerifyAttribute(prim, "oneAttr5", "string", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + + _VerifyAttribute(prim, "twoAttr1", "int", doc = twoAPIDoc, + default = 2, + hidden = False) + _VerifyAttribute(prim, "twoAttr2", "double", doc = twoAPIDoc, + default = 2.0) + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = twoAPIDoc, + hidden = False) + _VerifyAttribute(prim, "twoAttr4", "token", doc = twoAPIDoc) + _VerifyAttribute(prim, "twoAttr5", "double", doc = twoAPIDoc) + + _VerifyAttribute(prim, "nestedAttr1", "string", doc = twoAPIDoc, + default = "two", + hidden = True) + _VerifyAttribute(prim, "nestedAttr2", "int", doc = twoAPIDoc, + default = 2) + _VerifyAttribute(prim, "nestedAttr3", "double", doc = twoAPIDoc, + default = 2.0, + hidden = True), + _VerifyAttribute(prim, "nestedAttr4", "color3f", doc = twoAPIDoc, + default = (2.0, 2.0, 2.0), + hidden = True) + + # This attribute is to verify that only default value and hidden + # metadata is composed from a weaker property definition. With only + # TwoAPI applied, all of the metadata from TwoAPI is present on the + # property. This contrasts with the case where OneAPI is applied before + # TwoAPI which prevents the metadata other than default and hidden from + # coming through. + _VerifyAttribute(prim, "otherMetadataAttr", "token", doc = twoAPIDoc, + default = "two", + hidden = False, + displayGroup = "Two Group", + displayName = "OtherTwoAttr", + allowedTokens = ["two", "2"]) + + # Test 4: Apply the OneAPI to test case 3 prim. The prim now has + # TwoAPI and OneAPI applied in that strength order. This + # is the reverse order of test case 2. + prim.AddAppliedSchema(oneAPIName) + self.assertEqual(prim.GetAppliedSchemas(), + [twoAPIName, + oneAPIName]) + + # Both API schemas define the same attributes but with different + # field values. Some of these properties will be composed from fields + # in both API schemas with TwoAPI's opinions being stronger than + # OneAPI's. + + # TwoAPI has opinions for both "default" and "hidden" for all of + # these attributes, so OneAPI will not contribute opinions to any of + # these attributes. + _VerifyAttribute(prim, "oneAttr1", "int", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2, + hidden = True) + _VerifyAttribute(prim, "oneAttr2", "double", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2.0, + hidden = True) + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = (2.0, 2.0, 2.0), + hidden = True) + _VerifyAttribute(prim, "oneAttr4", "token", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + _VerifyAttribute(prim, "oneAttr5", "string", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + + # TwoAPI has opinions for both "default" and "hidden", so OneAPI will + # not contribute opinions to this attribute. + _VerifyAttribute(prim, "twoAttr1", "int", doc = twoAPIDoc, + default = 2, + hidden = False) + # TwoAPI has no opinion about "hidden", but OneAPI has hidden = true + # so hidden = true is composed in.. + _VerifyAttribute(prim, "twoAttr2", "double", doc = twoAPIDoc, + default = 2.0, + hidden = True) + # TwoAPI has no opinion about "default", but OneAPI has + # default = (1.0, 1.0, 1.0), so default = (1.0, 1.0, 1.0) is composed in. + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = twoAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = False) + # TwoAPI has no opinion about "default" or "hidden", but OneAPI + # has default = "one" and hidden = true so both are composed in. + _VerifyAttribute(prim, "twoAttr4", "token", doc = twoAPIDoc, + default = "one", + hidden = True) + # TwoAPI has no opinion about default or hidden, but OneAPI has this + # attribute as typeName = "float". This is a typeName conflict with + # TwoAPI's typeName = "double", so all of OneAPI's opinions are ignored. + _VerifyAttribute(prim, "twoAttr5", "double", doc = twoAPIDoc) + + # For these four attributes, TwoAPI has opinions for both "default" + # and "hidden" with the exception of "nestedAttr2" (for which TwoAPI + # has no opinion for "hidden"). Thus OneAPI only contributes + # hidden = true to "nestedAttr2", otherwise everything else comes from + # TwoAPI. + _VerifyAttribute(prim, "nestedAttr1", "string", doc = twoAPIDoc, + default = "two", + hidden = True) + _VerifyAttribute(prim, "nestedAttr2", "int", doc = twoAPIDoc, + default = 2, + hidden = True) + _VerifyAttribute(prim, "nestedAttr3", "double", doc = twoAPIDoc, + default = 2.0, + hidden = True), + _VerifyAttribute(prim, "nestedAttr4", "color3f", doc = twoAPIDoc, + default = (2.0, 2.0, 2.0), + hidden = True) + + # This attribute is to verify that only default value and hidden + # metadata is composed from a weaker property definition. Here, TwoAPI + # and OneAPI are applied in that order. All of the metadata from TwoAPI + # is present on the property as OneAPI is weaker and doesn't prevent the + # metadata other than default and hidden from coming through like it + # does when OneAPI is applied first. + _VerifyAttribute(prim, "otherMetadataAttr", "token", doc = twoAPIDoc, + default = "two", + hidden = False, + displayGroup = "Two Group", + displayName = "OtherTwoAttr", + allowedTokens = ["two", "2"]) # Test 5: Prim with no type name; apply the nestedAPI schema only to - # the prim. The nestedAPI has authoredOneAPI included as a built-in and - # authoredTwoAPI auto-applied to it. So all three schemas end up as + # the prim. The nestedAPI has OneAPI included as a built-in and + # TwoAPI auto-applied to it. So all three schemas end up as # applied schemas on the prim. - nestedAPIPrim = stage.DefinePrim("/NestedAPIPrim") - nestedAPIPrim.AddAppliedSchema(nestedAPIName) - self.assertEqual(nestedAPIPrim.GetAppliedSchemas(), - [nestedAPIName, - authoredOneAPIName, - authoredTwoAPIName]) - - # The nestedAPI schema defines its own opinions for all of attr1-6 - # attributes as well as rel1 and rel2. Since it is stronger than all its - # built-in API schemas, its version of all these properties win for this - # prim, regardless of the property and attributes types. - _VerifyAttrTypes(nestedAPIPrim, - attr1 = ("int", 1, nestedAPIDocStr), - attr2 = ("int", 2, nestedAPIDocStr), - attr3 = ("int", 3, nestedAPIDocStr), - attr4 = ("int", 4, nestedAPIDocStr), - attr5 = ("color3f", Gf.Vec3f(1, 1, 1), nestedAPIDocStr), - attr6 = ("token", "bar", nestedAPIDocStr)) - _VerifyIsRel(nestedAPIPrim, - rel1 = (True, nestedAPIDocStr), - rel2 = (False, nestedAPIDocStr)) - - # Test 6: Prim with no type name; apply the bultinAPI, authoredTwoAPI, - # and nestedAPI schemas to the prim in that strength order. The same - # three schemas are applied to the prim as in Test 5, but now the - # strength order is different. - nestedAPIPrim2 = stage.DefinePrim("/NestedAPIPrim2") - nestedAPIPrim2.AddAppliedSchema(authoredOneAPIName) - nestedAPIPrim2.AddAppliedSchema(authoredTwoAPIName) - nestedAPIPrim2.AddAppliedSchema(nestedAPIName) - self.assertEqual(nestedAPIPrim2.GetAppliedSchemas(), - [authoredOneAPIName, - authoredTwoAPIName, - nestedAPIName, - authoredOneAPIName, - authoredTwoAPIName]) - - # Only the authoredOneAPI and nestedAPI define attr1 and attr2; - # authoredOneAPI is stronger and wins - # Only the authoredTwoAPI and nestedAPI define attr3 and attr4; - # authoredTwoAPI is stronger and wins - # All define attr5 and attr6, so authoredOneAPI's version of those - # attributes are used since it's strongest. - _VerifyAttrTypes(nestedAPIPrim2, - attr1 = ("int", 0, authoredOneAPIDocStr), - attr2 = ("double", 0.0, authoredOneAPIDocStr), - attr3 = ("int", 10, authoredTwoAPIDocStr), - attr4 = ("string", "foo", authoredTwoAPIDocStr), - attr5 = ("point3f", Gf.Vec3f(0, 0, 0), authoredOneAPIDocStr), - attr6 = ("int", 20, authoredOneAPIDocStr)) - # All define rel1 and rel2, but since authoredOneAPI is strongest, it - # wins and only rel2 is a relationship. - _VerifyIsRel(nestedAPIPrim2, - rel1 = (False, authoredOneAPIDocStr), - rel2 = (True, authoredOneAPIDocStr)) - - # Test 7: Prim with type name set to the conflictPrimType; author the - # nestedAPI schema on this prim. nestedAPI still brings in the - # authoredOneAPI and authoredTwoAPI as its own built-ins to the applied - # API schemas which will be stronger than the prim type definition - # itself. - prim = stage.DefinePrim("/TypedPrim2", conflictPrimTypeName) + prim = stage.DefinePrim("/NestedAPIPrim") prim.AddAppliedSchema(nestedAPIName) self.assertEqual(prim.GetAppliedSchemas(), [nestedAPIName, - authoredOneAPIName, - authoredTwoAPIName, - builtinAPIName]) - - # nestedAPI defines all same properties as the prim type definition, - # is the strongest opinion, and, with the exception of attr6, uses the - # same property types and type names as the prim type definition. So - # all properties except attr6 in the composed definition use property - # definitions from nestedAPI. - # For attr6, the strongest opinion from nestedAPI has the type name - # "token" which doesn't match the type name "int" in the prim type - # definition. So, we have to use the opinion from the prim type - # definition. Note that both authoredOneAPI and authoredTwoAPI are - # technically stronger than prim type definition in this case AND have - # the attribute type of "int" for attr6. However, we still fall back to - # the prim type definition's opinion as we only consider the strongest - # opinion from the authored applied API schemas. - _VerifyAttrTypes(prim, - attr1 = ("int", 1, nestedAPIDocStr), - attr2 = ("int", 2, nestedAPIDocStr), - attr3 = ("int", 3, nestedAPIDocStr), - attr4 = ("int", 4, nestedAPIDocStr), - attr5 = ("color3f", Gf.Vec3f(1, 1, 1), nestedAPIDocStr), - attr6 = ("int", 6, conflictPrimTypeDocStr)) - _VerifyIsRel(prim, - rel1 = (True, nestedAPIDocStr), - rel2 = (False, nestedAPIDocStr)) - - # Now also apply authoredOneAPI and authoredTwoAPI directly to the same - # prim (previously they were included as built-ins under nestedAPI). - # These are still weaker than nestedAPI but this means they're also now - # siblings of nestedAPI in the composed definition as opposed to - # built-in to nestedAPI's own prim definition. - prim.AddAppliedSchema(authoredOneAPIName) - prim.AddAppliedSchema(authoredTwoAPIName) + oneAPIName, + twoAPIName]) + + # NestedAPI has no opinions about these attributes so they will + # be identical to test case 2 where OneAPI and TwoAPI are applied + # in the same order. + _VerifyAttribute(prim, "oneAttr1", "int", doc = oneAPIDoc, + default = 1, + hidden = False) + _VerifyAttribute(prim, "oneAttr2", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True) + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = oneAPIDoc, + default = (2.0, 2.0, 2.0), + hidden = False) + _VerifyAttribute(prim, "oneAttr4", "token", doc = oneAPIDoc, + default = "two", + hidden = True) + _VerifyAttribute(prim, "oneAttr5", "token", doc = oneAPIDoc) + + # Same for these attributes, NestedAPI has no opinions and they + # match test case 2. + _VerifyAttribute(prim, "twoAttr1", "int", doc = oneAPIDoc, + default = 1, + hidden = True) + _VerifyAttribute(prim, "twoAttr2", "double", doc = oneAPIDoc, + default = 1.0, + hidden = True) + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = oneAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = True) + _VerifyAttribute(prim, "twoAttr4", "token", doc = oneAPIDoc, + default = "one", + hidden = True) + _VerifyAttribute(prim, "twoAttr5", "float", doc = oneAPIDoc, + default = 1.0, + hidden = True) + + # NestedAPI has opinions for both "default" and "hidden", so OneAPI and + # TwoAPI will not contribute opinions to this attribute. + _VerifyAttribute(prim, "nestedAttr1", "string", doc = nestedAPIDoc, + default = "nested", + hidden = False) + # NestedAPI has no opinion about "default" or "hidden". + # OneAPI has hidden = true, but no opinion about "default". + # TwoAPI has default = 2. + # Thus we get the following attribute composed with fields from all 3 + # API schemas. + _VerifyAttribute(prim, "nestedAttr2", "int", doc = nestedAPIDoc, + default = 2, + hidden = True) + # NestedAPI has no opinion for "default" but does have hidden = false. + # OneAPI has default = 1.0 so its default value is composed in. + # No opinions from TwoAPI are used as the stronger API schemas have + # opinions for the composable fields. + _VerifyAttribute(prim, "nestedAttr3", "double", doc = nestedAPIDoc, + default = 1.0, + hidden = False) + # NestedAPI has no opinion about "default" or "hidden". + # OneAPI has this attribute with typeName = "point3f" which is a type + # conflict with typeName = "color3f" so all of its opinions are ignored. + # TwoAPI has default = (2.0, 2.0, 2.0) and hidden = true so both of + # these opinions are composed in. + _VerifyAttribute(prim, "nestedAttr4", "color3f", doc = nestedAPIDoc, + default = (2.0, 2.0, 2.0), + hidden = True) + + # Test 6: Prim with type name set to the compPrimType; no authored + # applied API schemas. The compPrimType has a single built-in API + # schema TwoAPI. + prim = stage.DefinePrim("/TypedPrim", compPrimTypeName) self.assertEqual(prim.GetAppliedSchemas(), - [nestedAPIName, - authoredOneAPIName, - authoredTwoAPIName, - authoredOneAPIName, - authoredTwoAPIName, - builtinAPIName]) - - # This extra condition changes nothing about the composed prim - # definition but is here to verify that the same behavior for attr6 - # above (where only the strongest authored API schema opinion for an - # attribute is considered) still hold for sibling applied API schemas. - _VerifyAttrTypes(prim, - attr1 = ("int", 1, nestedAPIDocStr), - attr2 = ("int", 2, nestedAPIDocStr), - attr3 = ("int", 3, nestedAPIDocStr), - attr4 = ("int", 4, nestedAPIDocStr), - attr5 = ("color3f", Gf.Vec3f(1, 1, 1), nestedAPIDocStr), - attr6 = ("int", 6, conflictPrimTypeDocStr)) - _VerifyIsRel(prim, - rel1 = (True, nestedAPIDocStr), - rel2 = (False, nestedAPIDocStr)) - - # Test 8: Prim with type name set to the conflictPrimType; author the - # authoredOneAPI, authoredTwoAPI, and nestedAPI schemas on this prim in - # that strength order. This brings in the same 3 applied API schemas as - # Test 7, but now authoredOneAPI and authoredTwoAPI are stronger than - # when they were just brought in as built-ins of nestedAPI. - prim = stage.DefinePrim("/TypedPrim3", conflictPrimTypeName) - prim.AddAppliedSchema(authoredOneAPIName) - prim.AddAppliedSchema(authoredTwoAPIName) + [twoAPIName]) + + # The prim type schema has no opinions about the following attributes + # so they get all their values from TwoAPI. + _VerifyAttribute(prim, "oneAttr1", "int", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2, + hidden = True) + _VerifyAttribute(prim, "oneAttr2", "double", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2.0, + hidden = True) + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = (2.0, 2.0, 2.0), + hidden = True) + _VerifyAttribute(prim, "oneAttr4", "token", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + _VerifyAttribute(prim, "oneAttr5", "string", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + + _VerifyAttribute(prim, "twoAttr1", "int", doc = twoAPIDoc, + default = 2, + hidden = False) + _VerifyAttribute(prim, "twoAttr2", "double", doc = twoAPIDoc, + default = 2.0) + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = twoAPIDoc, + hidden = False) + _VerifyAttribute(prim, "twoAttr4", "token", doc = twoAPIDoc) + _VerifyAttribute(prim, "twoAttr5", "double", doc = twoAPIDoc) + + # PrimType schema has opinions for both "default" and "hidden", so + # TwoAPI will not contribute opinions to this attribute. + _VerifyAttribute(prim, "nestedAttr1", "string", doc = primDoc, + default = "prim", + hidden = False) + # PrimType schema has no opinion about "default" or "hidden". + # TwoAPI has default = 2, but still no opinion about "hidden", so the + # attribute composes in default = 2 but remains with no opinion about + # "hidden". + _VerifyAttribute(prim, "nestedAttr2", "int", doc = primDoc, + default = 2) + # PrimType schema has no opinion for "default" but does have + # hidden = false. + # TwoAPI has default = 2.0 so its default value is composed in. + _VerifyAttribute(prim, "nestedAttr3", "double", doc = primDoc, + default = 2.0, + hidden = False) + # PrimType schema has no opinion about "default" or "hidden". + # TwoAPI has this attribute with typeName = "color3f" which is a type + # conflict with typeName = "point3f" so all of its opinions are ignored. + _VerifyAttribute(prim, "nestedAttr4", "point3f", doc = primDoc) + + # Test 7: Take the same prim from Test 6 above, with type name set to + # the compPrimType, and author nestedAPI. This gives us a prim with + # API schema order TwoAPI, NestedAPI, OneAPI. Note that NestedAPI doesn't + # bring in TwoAPI again as TwoAPI is already present as a built-in of the + # prim type and therefore is stronger than the authored API schemas. prim.AddAppliedSchema(nestedAPIName) + self.assertEqual(prim.GetPrimTypeInfo().GetAppliedAPISchemas(), + [nestedAPIName]) + self.assertEqual(prim.GetAppliedSchemas(), + [twoAPIName, + nestedAPIName, + oneAPIName]) + + # The following attributes do not have definitions "directly" in + # NestedAPI (though they are include through its built-ins). These + # attributes match test case 2 where TwoAPI is applied followed by + # OneAPI. + _VerifyAttribute(prim, "oneAttr1", "int", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2, + hidden = True) + _VerifyAttribute(prim, "oneAttr2", "double", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = 2.0, + hidden = True) + _VerifyAttribute(prim, "oneAttr3", "color3f", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = (2.0, 2.0, 2.0), + hidden = True) + _VerifyAttribute(prim, "oneAttr4", "token", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + _VerifyAttribute(prim, "oneAttr5", "string", doc = twoAPIDoc, + variability = Sdf.VariabilityUniform, + default = "two", + hidden = True) + + _VerifyAttribute(prim, "twoAttr1", "int", doc = twoAPIDoc, + default = 2, + hidden = False) + _VerifyAttribute(prim, "twoAttr2", "double", doc = twoAPIDoc, + default = 2.0, + hidden = True) + _VerifyAttribute(prim, "twoAttr3", "color3f", doc = twoAPIDoc, + default = (1.0, 1.0, 1.0), + hidden = False) + _VerifyAttribute(prim, "twoAttr4", "token", doc = twoAPIDoc, + default = "one", + hidden = True) + _VerifyAttribute(prim, "twoAttr5", "double", doc = twoAPIDoc) + + # PrimType schema has opinions for both "default" and "hidden", so none + # of the API schemas contribute opinions to this attribute. + _VerifyAttribute(prim, "nestedAttr1", "string", doc = primDoc, + default = "prim", + hidden = False) + # PrimType schema has no opinion about "default" or "hidden". + # TwoAPI has default = 2, but no opinion about hidden. + # NestedAPI has no opinion about "default" or "hidden". + # OneAPI has hidden = true. + # Thus we get the following PrimType's attribute composed with fields + # from TwoAPI (default) and OneAPI (hidden). + _VerifyAttribute(prim, "nestedAttr2", "int", doc = primDoc, + default = 2, + hidden = True) + # PrimType schema has no opinion for "default" but does have + # hidden = false. + # TwoAPI has default = 2.0 so its default value is composed in. + # No opinions from NestedAPI and OneAPI are used as the stronger API + # schemas have opinions for the composable fields. + _VerifyAttribute(prim, "nestedAttr3", "double", doc = primDoc, + default = 2.0, + hidden = False) + # PrimType schema has no opinion about "default" or "hidden". + # TwoAPI has this attribute with typeName = "color3f" which is a type + # conflict with typeName = "point3f" so all of its opinions are ignored. + # + # NestedAPI has a composed set of opinions that come from itself and its + # built-ins, OneAPI and TwoAPI. But since NestedAPI defines this + # attribute as typeName = "color3f", which is a type conflict with + # typeName = "point3f", all its opinions are ignored. + # + # And while OneAPI has a compatible typeName of "point3f" and opinions + # for default = (1.0, 1.0, 1.0) and hidden = false, its existence as a + # built-in of NestedAPI means it is only used to compose into NestedAPI's + # definition of the property and is not considered on its own. (See the + # next test case.) + _VerifyAttribute(prim, "nestedAttr4", "point3f", doc = primDoc) + + # Test 8: This is purely to test an edge case with nested API schemas + # and property type conflicts. Take the same prim from the previous + # case and now apply OneAPI to it. The prim's type signature will + # change (both NestedAPI and OneAPI are now authored API schemas), but + # composed list of API schemas does NOT change from from the previous + # example since NestedAPI already included OneAPI. However, the composed + # property definition for "nestedAttr4" will be different. + prim.AddAppliedSchema(oneAPIName) + self.assertEqual(prim.GetPrimTypeInfo().GetAppliedAPISchemas(), + [nestedAPIName, + oneAPIName]) self.assertEqual(prim.GetAppliedSchemas(), - [authoredOneAPIName, - authoredTwoAPIName, + [twoAPIName, nestedAPIName, - authoredOneAPIName, - authoredTwoAPIName, - builtinAPIName]) - - # The results of this test case are identical to Test 4 above as - # builtAPI is the strongest opinion and authoredTwoAPI is next and the - # same property type conflicts exist. Even though nestedAPI is stronger - # than the prim type definition and has opinions for attr2, attr4, - # attr5, rel1, and rel2 of the matching property/attribute type, these - # are never the strongest API schema property opinion and are not - # considered. - _VerifyAttrTypes(prim, - attr1 = ("int", 0, authoredOneAPIDocStr), - attr2 = ("int", 2, conflictPrimTypeDocStr), - attr3 = ("int", 10, authoredTwoAPIDocStr), - attr4 = ("int", 4, builtinAPIDocStr), - attr5 = ("color3f", Gf.Vec3f(1, 1, 1), conflictPrimTypeDocStr), - attr6 = ("int", 20, authoredOneAPIDocStr)) - _VerifyIsRel(prim, - rel1 = (True, conflictPrimTypeDocStr), - rel2 = (False, conflictPrimTypeDocStr)) + oneAPIName]) + + # PrimType schema has no opinion about "default" or "hidden". + # TwoAPI has this attribute with typeName = "color3f" which is a type + # conflict with typeName = "point3f" so all of its opinions are ignored. + # + # NestedAPI has a composed set of opinions that come from itself and its + # built-ins, OneAPI and TwoAPI. But since NestedAPI defines this + # attribute as typeName = "color3f", which is a type conflict with + # typeName = "point3f", all its opinions are ignored. + # + # But now, since OneAPI is itself an authored API schema, it is also + # composed in even though it is technically already included by + # NestedAPI. And since OneAPI has a compatible typeName of "point3f" and + # opinions for default = (1.0, 1.0, 1.0) and hidden = false these + # opinions are composed into the property definition. + _VerifyAttribute(prim, "nestedAttr4", "point3f", doc = primDoc, + default = (1.0, 1.0, 1.0), + hidden = False) @unittest.skipIf(Tf.GetEnvSetting('USD_DISABLE_AUTO_APPLY_API_SCHEMAS'), "Auto apply API schemas are disabled") @@ -3492,31 +3667,34 @@ def _VerifyAttribute(prim, name, typeName, # variability = uniform # allowedTokens = "uni_four", "uni_4" # doc = "Uniform token defined in Four" - # Override in PropertyOversThreeAPI tries to override the default value - # and allowed token but declares the attribute as a non-uniform token - # attribute. + # Override in PropertyOversThreeAPI overrides the default value and + # allowed tokens. The override attribute is declared as a non-uniform + # token attribute, but the attempt to override variability is ignored. # Override in PropertyOversOneAPI overrides the default value on a # properly uniform attribute. - # Override in PropertyOversTypedPrimDerived tries to override the - # default value but declares the attribute as a non-uniform token - # attribute. + # Override in PropertyOversTypedPrimDerived overrides the + # default value. The override attribute is declared as a non-uniform + # token attribute, but the attempt to override variability is ignored. propName = "uniform_token_defined_in_four" # OversOneAPI includes OversThreeAPI which includes OversFourAPI. - # The OversThreeAPI's override is a variability mismatch which causes - # it to be ignored but that doesn't prevent the correctly matched - # override from OversOneAPI from overriding the default value. + # OversThreeAPI overrides the allowed tokens and is the strongest + # opinion on that field. + # OversOneAPI and OversThreeAPI both override the default value but the + # stronger OversOneAPI wins. + # OversThreeAPI tries to override variabilty to "varying" but the + # variability field is always ignored. _VerifyAttribute(prim_1, propName, 'token', variability = Sdf.VariabilityUniform, - allowedTokens = Vt.TokenArray(["uni_four", "uni_4"]), + allowedTokens = Vt.TokenArray(["uni_three", "uni_3"]), default = "uni_1", documentation = "Uniform token defined in Four") self.assertFalse(prim_2.GetAttribute(propName)) - # The OversThreeAPI override variability mismatch causes it to be - # ignored. + # OversThreeAPI overrides default and allowedTokens. The variability + # of the override is always ignored. _VerifyAttribute(prim_3, propName, 'token', variability = Sdf.VariabilityUniform, - allowedTokens = Vt.TokenArray(["uni_four", "uni_4"]), - default = "uni_four", + allowedTokens = Vt.TokenArray(["uni_three", "uni_3"]), + default = "uni_3", documentation = "Uniform token defined in Four") _VerifyAttribute(prim_4, propName, 'token', variability = Sdf.VariabilityUniform, @@ -3524,13 +3702,18 @@ def _VerifyAttribute(prim, name, typeName, default = "uni_four", documentation = "Uniform token defined in Four") - # TypedPrimBase does not include the property. TypedPrimDerived's - # override is a variability mismatch and is ignored. + # TypedPrimBase does not include the property. + # OversThreeAPI overrides the allowed tokens and is the strongest + # opinion on that field. + # TypedPrimDerived and OversThreeAPI both override the default value but + # the stronger TypedPrimDerived wins. + # The variability of the overrides from TypedPrimDerived and + # OversThreeAPI are always ignored. self.assertFalse(primBase.GetAttribute(propName)) _VerifyAttribute(primDerived, propName, 'token', variability = Sdf.VariabilityUniform, - allowedTokens = Vt.TokenArray(["uni_four", "uni_4"]), - default = "uni_four", + allowedTokens = Vt.TokenArray(["uni_three", "uni_3"]), + default = "uni_derived", documentation = "Uniform token defined in Four") # Property: defined_in_auto diff --git a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/generatedSchema.usda b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/generatedSchema.usda index 645538cc06..7714a29ca0 100644 --- a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/generatedSchema.usda +++ b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/generatedSchema.usda @@ -393,120 +393,164 @@ class "TestNestedMultiApplyCycle3API" ( ) } -class TestPropTypeConflictsPrim "TestPropTypeConflictsPrim" ( - apiSchemas = ["TestPropTypeConflictBuiltinAPI"] -) +class "TestPropCompOneAPI" { - int attr1 = 1 ( - doc = "From TestPropTypeConflictsPrim" + string nestedAttr1 = "one" ( + doc = "From TestPropCompOneAPI" + hidden = true ) - int attr2 = 2 ( - doc = "From TestPropTypeConflictsPrim" + int nestedAttr2 ( + doc = "From TestPropCompOneAPI" + hidden = true ) - int attr3 = 3 ( - doc = "From TestPropTypeConflictsPrim" + double nestedAttr3 = 1 ( + doc = "From TestPropCompOneAPI" + hidden = true ) - color3f attr5 = (1, 1, 1) ( - doc = "From TestPropTypeConflictsPrim" + point3f nestedAttr4 = (1, 1, 1) ( + doc = "From TestPropCompOneAPI" + hidden = false ) - int attr6 = 6 ( - doc = "From TestPropTypeConflictsPrim" + int oneAttr1 = 1 ( + doc = "From TestPropCompOneAPI" + hidden = false ) - rel rel1 ( - doc = "From TestPropTypeConflictsPrim" + double oneAttr2 = 1 ( + doc = "From TestPropCompOneAPI" ) - int rel2 ( - doc = "From TestPropTypeConflictsPrim" + color3f oneAttr3 ( + doc = "From TestPropCompOneAPI" + hidden = false ) -} - -class "TestPropTypeConflictBuiltinAPI" -{ - double attr2 = 0 ( - doc = "From TestPropTypeConflictBuiltinAPI" + token oneAttr4 ( + doc = "From TestPropCompOneAPI" + ) + token oneAttr5 ( + doc = "From TestPropCompOneAPI" ) - int attr4 = 4 ( - doc = "From TestPropTypeConflictBuiltinAPI" + token otherMetadataAttr + int twoAttr1 = 1 ( + doc = "From TestPropCompOneAPI" + hidden = true ) - int rel1 ( - doc = "From TestPropTypeConflictBuiltinAPI" + double twoAttr2 = 1 ( + doc = "From TestPropCompOneAPI" + hidden = true ) - rel rel2 ( - doc = "From TestPropTypeConflictBuiltinAPI" + color3f twoAttr3 = (1, 1, 1) ( + doc = "From TestPropCompOneAPI" + hidden = true + ) + token twoAttr4 = "one" ( + doc = "From TestPropCompOneAPI" + hidden = true + ) + float twoAttr5 = 1 ( + doc = "From TestPropCompOneAPI" + hidden = true ) } -class "TestPropTypeConflictAuthoredOneAPI" +class "TestPropCompTwoAPI" { - int attr1 = 0 ( - doc = "From TestPropTypeConflictAuthoredOneAPI" + string nestedAttr1 = "two" ( + doc = "From TestPropCompTwoAPI" + hidden = true ) - double attr2 = 0 ( - doc = "From TestPropTypeConflictAuthoredOneAPI" + int nestedAttr2 = 2 ( + doc = "From TestPropCompTwoAPI" ) - point3f attr5 = (0, 0, 0) ( - doc = "From TestPropTypeConflictAuthoredOneAPI" + double nestedAttr3 = 2 ( + doc = "From TestPropCompTwoAPI" + hidden = true ) - int attr6 = 20 ( - doc = "From TestPropTypeConflictAuthoredOneAPI" + color3f nestedAttr4 = (2, 2, 2) ( + doc = "From TestPropCompTwoAPI" + hidden = true ) - int rel1 ( - doc = "From TestPropTypeConflictAuthoredOneAPI" + uniform int oneAttr1 = 2 ( + doc = "From TestPropCompTwoAPI" + hidden = true ) - rel rel2 ( - doc = "From TestPropTypeConflictAuthoredOneAPI" + uniform double oneAttr2 = 2 ( + doc = "From TestPropCompTwoAPI" + hidden = true ) -} - -class "TestPropTypeConflictAuthoredTwoAPI" -{ - int attr3 = 10 ( - doc = "From TestPropTypeConflictAuthoredTwoAPI" + uniform color3f oneAttr3 = (2, 2, 2) ( + doc = "From TestPropCompTwoAPI" + hidden = true + ) + uniform token oneAttr4 = "two" ( + doc = "From TestPropCompTwoAPI" + hidden = true + ) + uniform string oneAttr5 = "two" ( + doc = "From TestPropCompTwoAPI" + hidden = true + ) + token otherMetadataAttr = "two" ( + allowedTokens = ["two", "2"] + displayGroup = "Two Group" + displayName = "OtherTwoAttr" + doc = "From TestPropCompTwoAPI" + hidden = false ) - string attr4 = "foo" ( - doc = "From TestPropTypeConflictAuthoredTwoAPI" + int twoAttr1 = 2 ( + doc = "From TestPropCompTwoAPI" + hidden = false ) - float3 attr5 = (1, 2, 3) ( - doc = "From TestPropTypeConflictAuthoredTwoAPI" + double twoAttr2 = 2 ( + doc = "From TestPropCompTwoAPI" ) - int attr6 = 10 ( - doc = "From TestPropTypeConflictAuthoredTwoAPI" + color3f twoAttr3 ( + doc = "From TestPropCompTwoAPI" + hidden = false ) - rel rel1 ( - doc = "From TestPropTypeConflictAuthoredTwoAPI" + token twoAttr4 ( + doc = "From TestPropCompTwoAPI" ) - int rel2 ( - doc = "From TestPropTypeConflictAuthoredTwoAPI" + double twoAttr5 ( + doc = "From TestPropCompTwoAPI" ) } -class "TestPropTypeConflictNestedAuthoredAPI" ( - apiSchemas = ["TestPropTypeConflictAuthoredOneAPI"] +class "TestPropCompNestedAPI" ( + apiSchemas = ["TestPropCompOneAPI"] ) { - int attr1 = 1 ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + string nestedAttr1 = "nested" ( + doc = "From TestPropCompNestedAPI" + hidden = false ) - int attr2 = 2 ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + int nestedAttr2 ( + doc = "From TestPropCompNestedAPI" ) - int attr3 = 3 ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + double nestedAttr3 ( + doc = "From TestPropCompNestedAPI" + hidden = false ) - int attr4 = 4 ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + color3f nestedAttr4 ( + doc = "From TestPropCompNestedAPI" ) - color3f attr5 = (1, 1, 1) ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" +} + +class TestPropCompsPrim "TestPropCompsPrim" ( + apiSchemas = ["TestPropCompTwoAPI"] +) +{ + string nestedAttr1 = "prim" ( + doc = "From TestPropCompsPrim" + hidden = false ) - token attr6 = "bar" ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + int nestedAttr2 ( + doc = "From TestPropCompsPrim" ) - rel rel1 ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + double nestedAttr3 ( + doc = "From TestPropCompsPrim" + hidden = false ) - int rel2 ( - doc = "From TestPropTypeConflictNestedAuthoredAPI" + point3f nestedAttr4 ( + doc = "From TestPropCompsPrim" ) } diff --git a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/plugInfo.json b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/plugInfo.json index b17f88b9c3..e5c8762e44 100644 --- a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/plugInfo.json +++ b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/plugInfo.json @@ -267,9 +267,9 @@ ], "schemaKind": "concreteTyped" }, - "TestUsdAppliedAPISchemasTestPropTypeConflictAuthoredOneAPI": { + "TestUsdAppliedAPISchemasTestPropCompNestedAPI": { "alias": { - "UsdSchemaBase": "TestPropTypeConflictAuthoredOneAPI" + "UsdSchemaBase": "TestPropCompNestedAPI" }, "autoGenerated": true, "bases": [ @@ -277,42 +277,32 @@ ], "schemaKind": "singleApplyAPI" }, - "TestUsdAppliedAPISchemasTestPropTypeConflictAuthoredTwoAPI": { + "TestUsdAppliedAPISchemasTestPropCompOneAPI": { "alias": { - "UsdSchemaBase": "TestPropTypeConflictAuthoredTwoAPI" + "UsdSchemaBase": "TestPropCompOneAPI" }, - "apiSchemaAutoApplyTo": [ - "TestPropTypeConflictNestedAuthoredAPI" - ], "autoGenerated": true, "bases": [ "UsdAPISchemaBase" ], "schemaKind": "singleApplyAPI" }, - "TestUsdAppliedAPISchemasTestPropTypeConflictBuiltinAPI": { + "TestUsdAppliedAPISchemasTestPropCompTwoAPI": { "alias": { - "UsdSchemaBase": "TestPropTypeConflictBuiltinAPI" + "UsdSchemaBase": "TestPropCompTwoAPI" }, - "autoGenerated": true, - "bases": [ - "UsdAPISchemaBase" + "apiSchemaAutoApplyTo": [ + "TestPropCompNestedAPI" ], - "schemaKind": "singleApplyAPI" - }, - "TestUsdAppliedAPISchemasTestPropTypeConflictNestedAuthoredAPI": { - "alias": { - "UsdSchemaBase": "TestPropTypeConflictNestedAuthoredAPI" - }, "autoGenerated": true, "bases": [ "UsdAPISchemaBase" ], "schemaKind": "singleApplyAPI" }, - "TestUsdAppliedAPISchemasTestPropTypeConflictsPrim": { + "TestUsdAppliedAPISchemasTestPropCompsPrim": { "alias": { - "UsdSchemaBase": "TestPropTypeConflictsPrim" + "UsdSchemaBase": "TestPropCompsPrim" }, "autoGenerated": true, "bases": [ diff --git a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/schema.usda b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/schema.usda index 32f2a4f9e8..83bd76bdec 100644 --- a/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/schema.usda +++ b/pxr/usd/usd/testenv/testUsdAppliedAPISchemas/resources/schema.usda @@ -547,71 +547,181 @@ class "TestNestedMultiApplyCycle3API" ) } -class TestPropTypeConflictsPrim "TestPropTypeConflictsPrim" ( - inherits = - prepend apiSchemas = ["TestPropTypeConflictBuiltinAPI"] -) -{ - int attr1 = 1 ( doc = "From TestPropTypeConflictsPrim" ) - int attr2 = 2 ( doc = "From TestPropTypeConflictsPrim" ) - int attr3 = 3 ( doc = "From TestPropTypeConflictsPrim" ) - color3f attr5 = (1, 1, 1) ( doc = "From TestPropTypeConflictsPrim" ) - int attr6 = 6 ( doc = "From TestPropTypeConflictsPrim" ) - rel rel1 ( doc = "From TestPropTypeConflictsPrim" ) - int rel2 ( doc = "From TestPropTypeConflictsPrim" ) -} - -class "TestPropTypeConflictBuiltinAPI" ( +class "TestPropCompOneAPI" ( inherits = ) { - double attr2 = 0.0 ( doc = "From TestPropTypeConflictBuiltinAPI" ) - int attr4 = 4 ( doc = "From TestPropTypeConflictBuiltinAPI" ) - int rel1 ( doc = "From TestPropTypeConflictBuiltinAPI" ) - rel rel2 ( doc = "From TestPropTypeConflictBuiltinAPI" ) -} + int oneAttr1 = 1 ( + hidden = false + doc = "From TestPropCompOneAPI" + ) + double oneAttr2 = 1.0 ( + doc = "From TestPropCompOneAPI" + ) + color3f oneAttr3 ( + hidden = false + doc = "From TestPropCompOneAPI" + ) + token oneAttr4 ( + doc = "From TestPropCompOneAPI" + ) + token oneAttr5 ( + doc = "From TestPropCompOneAPI" + ) -class "TestPropTypeConflictAuthoredOneAPI" ( - inherits = -) -{ - int attr1 = 0 ( doc = "From TestPropTypeConflictAuthoredOneAPI" ) - double attr2 = 0.0 ( doc = "From TestPropTypeConflictAuthoredOneAPI" ) - point3f attr5 = (0, 0, 0) ( doc = "From TestPropTypeConflictAuthoredOneAPI" ) - int attr6 = 20 ( doc = "From TestPropTypeConflictAuthoredOneAPI" ) - int rel1 ( doc = "From TestPropTypeConflictAuthoredOneAPI" ) - rel rel2 ( doc = "From TestPropTypeConflictAuthoredOneAPI" ) + int twoAttr1 = 1 ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + double twoAttr2 = 1.0 ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + color3f twoAttr3 = (1.0, 1.0, 1.0) ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + token twoAttr4 = "one" ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + float twoAttr5 = 1.0 ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + + string nestedAttr1 = "one" ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + int nestedAttr2 ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + double nestedAttr3 = 1.0 ( + hidden = true + doc = "From TestPropCompOneAPI" + ) + point3f nestedAttr4 = (1.0, 1.0, 1.0) ( + hidden = false + doc = "From TestPropCompOneAPI" + ) + + token otherMetadataAttr } -class "TestPropTypeConflictAuthoredTwoAPI" ( +class "TestPropCompTwoAPI" ( inherits = customData = { token[] apiSchemaAutoApplyTo = [ - "TestPropTypeConflictNestedAuthoredAPI"] + "TestPropCompNestedAPI"] } ) { - int attr3 = 10 ( doc = "From TestPropTypeConflictAuthoredTwoAPI" ) - string attr4 = "foo" ( doc = "From TestPropTypeConflictAuthoredTwoAPI" ) - float3 attr5 = (1, 2, 3) ( doc = "From TestPropTypeConflictAuthoredTwoAPI" ) - int attr6 = 10 ( doc = "From TestPropTypeConflictAuthoredTwoAPI" ) - rel rel1 ( doc = "From TestPropTypeConflictAuthoredTwoAPI" ) - int rel2 ( doc = "From TestPropTypeConflictAuthoredTwoAPI" ) + uniform int oneAttr1 = 2 ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + uniform double oneAttr2 = 2.0 ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + uniform color3f oneAttr3 = (2.0, 2.0, 2.0) ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + uniform token oneAttr4 = "two" ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + uniform string oneAttr5 = "two" ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + + int twoAttr1 = 2 ( + hidden = false + doc = "From TestPropCompTwoAPI" + ) + double twoAttr2 = 2.0 ( + doc = "From TestPropCompTwoAPI" + ) + color3f twoAttr3 ( + hidden = false + doc = "From TestPropCompTwoAPI" + ) + token twoAttr4 ( + doc = "From TestPropCompTwoAPI" + ) + double twoAttr5 ( + doc = "From TestPropCompTwoAPI" + ) + + string nestedAttr1 = "two" ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + int nestedAttr2 = 2 ( + doc = "From TestPropCompTwoAPI" + ) + double nestedAttr3 = 2.0 ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + color3f nestedAttr4 = (2.0, 2.0, 2.0) ( + hidden = true + doc = "From TestPropCompTwoAPI" + ) + + token otherMetadataAttr = "two" ( + hidden = false + doc = "From TestPropCompTwoAPI" + displayGroup = "Two Group" + displayName = "OtherTwoAttr" + allowedTokens = ["two", "2"] + ) } -class "TestPropTypeConflictNestedAuthoredAPI" ( +class "TestPropCompNestedAPI" ( inherits = - prepend apiSchemas = ["TestPropTypeConflictAuthoredOneAPI"] + prepend apiSchemas = ["TestPropCompOneAPI"] ) { - int attr1 = 1 ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - int attr2 = 2 ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - int attr3 = 3 ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - int attr4 = 4 ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - color3f attr5 = (1, 1, 1) ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - token attr6 = "bar" ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - rel rel1 ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) - int rel2 ( doc = "From TestPropTypeConflictNestedAuthoredAPI" ) + string nestedAttr1 = "nested" ( + hidden = false + doc = "From TestPropCompNestedAPI" + ) + int nestedAttr2 ( + doc = "From TestPropCompNestedAPI" + ) + double nestedAttr3 ( + hidden = false + doc = "From TestPropCompNestedAPI" + ) + color3f nestedAttr4 ( + doc = "From TestPropCompNestedAPI" + ) +} + +class TestPropCompsPrim "TestPropCompsPrim" ( + inherits = + prepend apiSchemas = ["TestPropCompTwoAPI"] +) +{ + string nestedAttr1 = "prim" ( + hidden = false + doc = "From TestPropCompsPrim" + ) + int nestedAttr2 ( + doc = "From TestPropCompsPrim" + ) + double nestedAttr3 ( + hidden = false + doc = "From TestPropCompsPrim" + ) + point3f nestedAttr4 ( + doc = "From TestPropCompsPrim" + ) } class "TestPropertyOversOneAPI" ( diff --git a/pxr/usd/usd/testenv/testUsdSchemaVersioning.py b/pxr/usd/usd/testenv/testUsdSchemaVersioning.py index c79b4ed90c..d05e34359f 100644 --- a/pxr/usd/usd/testenv/testUsdSchemaVersioning.py +++ b/pxr/usd/usd/testenv/testUsdSchemaVersioning.py @@ -1666,9 +1666,9 @@ def _MakeNewPrimPath() : "TestVersionedMultiApplyAPI:foo", "TestVersionedMultiApplyAPI:bar"]) self.assertEqual(prim.GetAppliedSchemas(), - ["TestVersionedMultiApplyAPI:bar", - "TestVersionedSingleApplyAPI_1", - "TestVersionedMultiApplyAPI_2:foo"]) + ["TestVersionedSingleApplyAPI_1", + "TestVersionedMultiApplyAPI_2:foo", + "TestVersionedMultiApplyAPI:bar"]) self.assertEqual(prim.GetPropertyNames(), ["multi:bar:m_attr", "multi:foo:m_attr2", diff --git a/pxr/usdImaging/usdImaging/adapterManager.cpp b/pxr/usdImaging/usdImaging/adapterManager.cpp index b4dec05173..232b995056 100644 --- a/pxr/usdImaging/usdImaging/adapterManager.cpp +++ b/pxr/usdImaging/usdImaging/adapterManager.cpp @@ -158,8 +158,6 @@ UsdImaging_AdapterManager::AdapterSetLookup( // contains both auto-applied and manually applied schemas const TfTokenVector allAppliedSchemas = prim.GetAppliedSchemas(); - // contains only the manually applied API schemas - const TfTokenVector appliedAPISchemas = typeInfo.GetAppliedAPISchemas(); result.allAdapters.reserve(allAppliedSchemas.size() + 1 + _keylessAdapters.size()); @@ -169,17 +167,6 @@ UsdImaging_AdapterManager::AdapterSetLookup( result.allAdapters.insert(result.allAdapters.end(), _keylessAdapters.begin(), _keylessAdapters.end()); - // then add the manually applied API schemas as they have the strongest - // opinion of the keyed adapters - for (const TfToken &schemaToken : appliedAPISchemas) { - std::pair tokenPair = - UsdSchemaRegistry::GetTypeNameAndInstance(schemaToken); - if (UsdImagingAPISchemaAdapterSharedPtr a = - _APIAdapterLookup(tokenPair.first)) { - result.allAdapters.emplace_back(a, tokenPair.second); - } - } - // then any prim-type schema const TfToken adapterKey = typeInfo.GetSchemaTypeName(); // If there is an adapter for the type name, include it. @@ -207,12 +194,9 @@ UsdImaging_AdapterManager::AdapterSetLookup( result.allAdapters.emplace_back(basePrimAdapter, TfToken()); } - // then the auto-applied/built-in schemas which will start after the entries - // which are (also) found (in isolation) within allAppliedSchemas - for (size_t i = appliedAPISchemas.size(); i < allAppliedSchemas.size(); - ++i) { - - const TfToken &schemaToken = allAppliedSchemas[i]; + // then the applied API schemas which are already in their strength order + for (const TfToken &schemaToken: allAppliedSchemas) { + std::pair tokenPair = UsdSchemaRegistry::GetTypeNameAndInstance(schemaToken);