1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef PXR_USD_USD_SCHEMA_REGISTRY_H 25 #define PXR_USD_USD_SCHEMA_REGISTRY_H 26 27 #include "pxr/pxr.h" 28 #include "pxr/usd/usd/api.h" 29 #include "pxr/usd/usd/common.h" 30 31 #include "pxr/usd/sdf/layer.h" 32 #include "pxr/usd/sdf/primSpec.h" 33 34 #include "pxr/base/tf/hash.h" 35 #include "pxr/base/tf/singleton.h" 36 37 #include <unordered_map> 38 39 PXR_NAMESPACE_OPEN_SCOPE 40 41 SDF_DECLARE_HANDLES(SdfAttributeSpec); 42 SDF_DECLARE_HANDLES(SdfRelationshipSpec); 43 44 class UsdPrimDefinition; 45 46 /// \class UsdSchemaRegistry 47 /// 48 /// Singleton registry that provides access to schema type information and 49 /// the prim definitions for registered Usd "IsA" and applied API schema 50 /// types. It also contains the data from the generated schemas that is used 51 /// by prim definitions to provide properties and fallbacks. 52 /// 53 /// The data contained herein comes from the generatedSchema.usda file 54 /// (generated when a schema.usda file is processed by \em usdGenSchema) 55 /// of each schema-defining module. The registry expects each schema type to 56 /// be represented as a single prim spec with its inheritance flattened, i.e. 57 /// the prim spec contains a union of all its local and class inherited property 58 /// specs and metadata fields. 59 /// 60 /// It is used by the Usd core, via UsdPrimDefinition, to determine how to 61 /// create scene description for unauthored "built-in" properties of schema 62 /// classes, to enumerate all properties for a given schema class, and finally 63 /// to provide fallback values for unauthored built-in properties. 64 /// 65 class UsdSchemaRegistry : public TfWeakBase, boost::noncopyable { 66 public: 67 USD_API GetInstance()68 static UsdSchemaRegistry& GetInstance() { 69 return TfSingleton<UsdSchemaRegistry>::GetInstance(); 70 } 71 72 /// Return the type name in the USD schema for prims or API schemas of the 73 /// given registered \p schemaType. 74 USD_API 75 static TfToken GetSchemaTypeName(const TfType &schemaType); 76 77 /// Return the type name in the USD schema for prims or API schemas of the 78 /// given registered \p SchemaType. 79 template <class SchemaType> 80 static GetSchemaTypeName()81 TfToken GetSchemaTypeName() { 82 return GetSchemaTypeName(SchemaType::_GetStaticTfType()); 83 } 84 85 /// Return the type name in the USD schema for concrete prim types only from 86 /// the given registered \p schemaType. 87 USD_API 88 static TfToken GetConcreteSchemaTypeName(const TfType &schemaType); 89 90 /// Return the type name in the USD schema for API schema types only from 91 /// the given registered \p schemaType. 92 USD_API 93 static TfToken GetAPISchemaTypeName(const TfType &schemaType); 94 95 /// Return the TfType of the schema corresponding to the given prim or API 96 /// schema name \p typeName. This the inverse of GetSchemaTypeName. 97 USD_API 98 static TfType GetTypeFromSchemaTypeName(const TfToken &typeName); 99 100 /// Return the TfType of the schema corresponding to the given concrete prim 101 /// type name \p typeName. This the inverse of GetConcreteSchemaTypeName. 102 USD_API 103 static TfType GetConcreteTypeFromSchemaTypeName(const TfToken &typeName); 104 105 /// Return the TfType of the schema corresponding to the given API schema 106 /// type name \p typeName. This the inverse of GetAPISchemaTypeNAme. 107 USD_API 108 static TfType GetAPITypeFromSchemaTypeName(const TfToken &typeName); 109 110 /// Returns true if the field \p fieldName cannot have fallback values 111 /// specified in schemas. 112 /// 113 /// Fields are generally disallowed because their fallback values 114 /// aren't used. For instance, fallback values for composition arcs 115 /// aren't used during composition, so allowing them to be set in 116 /// schemas would be misleading. 117 USD_API 118 static bool IsDisallowedField(const TfToken &fieldName); 119 120 /// Returns true if the prim type \p primType inherits from \ref UsdTyped. 121 USD_API 122 static bool IsTyped(const TfType& primType); 123 124 /// Returns the kind of the schema the given \p schemaType represents. 125 /// 126 /// This returns UsdSchemaKind::Invalid if \p schemaType is not a valid 127 /// schema type or if the kind cannot be determined from type's plugin 128 /// information. 129 USD_API 130 static UsdSchemaKind GetSchemaKind(const TfType &schemaType); 131 132 /// Returns the kind of the schema the given \p typeName represents. 133 /// 134 /// This returns UsdSchemaKind::Invalid if \p typeName is not a valid 135 /// schema type name or if the kind cannot be determined from type's plugin 136 /// information. 137 USD_API 138 static UsdSchemaKind GetSchemaKind(const TfToken &typeName); 139 140 /// Returns true if the prim type \p primType is instantiable 141 /// in scene description. 142 USD_API 143 static bool IsConcrete(const TfType& primType); 144 145 /// Returns true if the prim type \p primType is instantiable 146 /// in scene description. 147 USD_API 148 static bool IsConcrete(const TfToken& primType); 149 150 /// Returns true if \p apiSchemaType is an applied API schema type. 151 USD_API 152 static bool IsAppliedAPISchema(const TfType& apiSchemaType); 153 154 /// Returns true if \p apiSchemaType is an applied API schema type. 155 USD_API 156 static bool IsAppliedAPISchema(const TfToken& apiSchemaType); 157 158 /// Returns true if \p apiSchemaType is a multiple-apply API schema type. 159 USD_API 160 static bool IsMultipleApplyAPISchema(const TfType& apiSchemaType); 161 162 /// Returns true if \p apiSchemaType is a multiple-apply API schema type. 163 USD_API 164 static bool IsMultipleApplyAPISchema(const TfToken& apiSchemaType); 165 166 /// Finds the TfType of a schema with \p typeName 167 /// 168 /// This is primarily for when you have been provided Schema typeName 169 /// (perhaps from a User Interface or Script) and need to identify 170 /// if a prim's type inherits/is that typeName. If the type name IS known, 171 /// then using the schema class is preferred. 172 /// 173 /// \code{.py} 174 /// # This code attempts to match all prims on a stage to a given 175 /// # user specified type, making the traditional schema based idioms not 176 /// # applicable. 177 /// data = parser.parse_args() 178 /// tfType = UsdSchemaRegistry.GetTypeFromName(data.type) 179 /// matchedPrims = [p for p in stage.Traverse() if p.IsA(tfType)] 180 /// \endcode 181 /// 182 /// \note It's worth noting that 183 /// GetTypeFromName("Sphere") == GetTypeFromName("UsdGeomSphere"), as 184 /// this function resolves both the Schema's C++ class name and any 185 /// registered aliases from a libraries plugInfo.json file. However, 186 /// GetTypeFromName("Boundable") != GetTypeFromName("UsdGeomBoundable") 187 /// because type aliases don't get registered for abstract schema types. 188 USD_API 189 static TfType GetTypeFromName(const TfToken& typeName); 190 191 /// Returns the schema type name and the instance name parsed from the 192 /// given \p apiSchemaName 193 /// 194 /// \p apiSchemaName is the name of an applied schema as it appears in 195 /// the list of applied schemas on a prim. For single-apply API schemas 196 /// the name will just be the schema type name. For multiple-apply schemas 197 /// the name should include the schema type name and the applied instance 198 /// name separated by a namespace delimiter, for example 199 /// 'CollectionAPI:plasticStuff'. 200 /// 201 /// This function returns the separated schema type name and instance name 202 /// component tokens if possible, otherwise it returns the \p apiSchemaName 203 /// as the type name and an empty instance name. 204 /// 205 /// Note that no validation is done on the returned tokens. Clients are 206 /// advised to use GetTypeFromSchemaTypeName() to validate the typeName 207 /// token. 208 /// 209 /// \sa UsdPrim::AddAppliedSchema(const TfToken&) const 210 /// \sa UsdPrim::GetAppliedSchemas() const 211 USD_API 212 static std::pair<TfToken, TfToken> GetTypeNameAndInstance( 213 const TfToken &apiSchemaName); 214 215 /// Returns true if the given \p instanceName is an allowed instance name 216 /// for the multiple apply API schema named \p apiSchemaName. 217 /// 218 /// Any instance name that matches the name of a property provided by the 219 /// API schema is disallowed and will return false. If the schema type 220 /// has plugin metadata that specifies allowed instance names, then only 221 /// those specified names are allowed for the schema type. 222 /// If the instance name is empty or the API is not a multiple apply schema, 223 /// this will return false. 224 USD_API 225 static bool IsAllowedAPISchemaInstanceName( 226 const TfToken &apiSchemaName, 227 const TfToken &instanceName); 228 229 /// Returns a list of prim type names that the given \p apiSchemaName can 230 /// only be applied to. 231 /// 232 /// A non-empty list indicates that the API schema can only be applied to 233 /// prim that are or derive from prim type names in the list. If the list 234 /// is empty, the API schema can be applied to prims of any type. 235 /// 236 /// If a non-empty \p instanceName is provided, this will first look for 237 /// a list of "can only apply to" names specific to that instance of the API 238 /// schema and return that if found. If a list is not found for the specific 239 /// instance, it will fall back to looking for a "can only apply to" list 240 /// for just the schema name itself. 241 USD_API 242 static const TfTokenVector &GetAPISchemaCanOnlyApplyToTypeNames( 243 const TfToken &apiSchemaName, 244 const TfToken &instanceName = TfToken()); 245 246 /// Returns a map of the names of all registered auto apply API schemas 247 /// to the list of type names each is registered to be auto applied to. 248 /// 249 /// The list of type names to apply to will directly match what is specified 250 /// in the plugin metadata for each schema type. While auto apply schemas do 251 /// account for the existence and validity of the type names and expand to 252 /// include derived types of the listed types, the type lists returned by 253 /// this function do not. 254 USD_API 255 static const std::map<TfToken, TfTokenVector> &GetAutoApplyAPISchemas(); 256 257 /// Collects all the additional auto apply schemas that can be defined in 258 /// a plugin through "AutoApplyAPISchemas" metadata and adds the mappings 259 /// to \p autoApplyAPISchemas. 260 /// 261 /// These are separate from the auto-apply schemas that are built in to the 262 /// applied API schema types themselves and can be defined in any plugin to 263 /// map any applied API schema to any concrete prim type. 264 /// 265 /// Note that GetAutoApplyAPISchemas will already include API schemas 266 /// collected from this method; this function is provided for clients that 267 /// may want to collect just these plugin API schema mappings. 268 USD_API 269 static void CollectAddtionalAutoApplyAPISchemasFromPlugins( 270 std::map<TfToken, TfTokenVector> *autoApplyAPISchemas); 271 272 /// Returns the namespace prefix that is prepended to all properties of 273 /// the given \p multiApplyAPISchemaName. 274 USD_API 275 TfToken GetPropertyNamespacePrefix( 276 const TfToken &multiApplyAPISchemaName) const; 277 278 /// Finds the prim definition for the given \p typeName token if 279 /// \p typeName is a registered concrete typed schema type. Returns null if 280 /// it is not. FindConcretePrimDefinition(const TfToken & typeName)281 const UsdPrimDefinition* FindConcretePrimDefinition( 282 const TfToken &typeName) const { 283 const auto it = _concreteTypedPrimDefinitions.find(typeName); 284 return it != _concreteTypedPrimDefinitions.end() ? it->second : nullptr; 285 } 286 287 /// Finds the prim definition for the given \p typeName token if 288 /// \p typeName is a registered applied API schema type. Returns null if 289 /// it is not. FindAppliedAPIPrimDefinition(const TfToken & typeName)290 const UsdPrimDefinition *FindAppliedAPIPrimDefinition( 291 const TfToken &typeName) const { 292 // Check the single apply API schemas first then check for multiple 293 // apply schemas. This function will most often be used to find a 294 // single apply schema's prim definition as the prim definitions for 295 // multiple apply schemas aren't generally useful. 296 const auto it = _singleApplyAPIPrimDefinitions.find(typeName); 297 if (it != _singleApplyAPIPrimDefinitions.end()) { 298 return it->second; 299 } 300 const auto multiIt = _multiApplyAPIPrimDefinitions.find(typeName); 301 return multiIt != _multiApplyAPIPrimDefinitions.end() ? 302 multiIt->second.primDef : nullptr; 303 } 304 305 /// Returns the empty prim definition. GetEmptyPrimDefinition()306 const UsdPrimDefinition *GetEmptyPrimDefinition() const { 307 return _emptyPrimDefinition; 308 } 309 310 /// Composes and returns a new UsdPrimDefinition from the given \p primType 311 /// and list of \p appliedSchemas. This prim definition will contain a union 312 /// of properties from the registered prim definitions of each of the 313 /// provided types. 314 USD_API 315 std::unique_ptr<UsdPrimDefinition> 316 BuildComposedPrimDefinition( 317 const TfToken &primType, const TfTokenVector &appliedAPISchemas) const; 318 319 /// Returns a dictionary mapping concrete schema prim type names to a 320 /// VtTokenArray of fallback prim type names if fallback types are defined 321 /// for the schema type in its registered schema. 322 /// 323 /// The standard use case for this to provide schema defined metadata that 324 /// can be saved with a stage to inform an older version of USD - that 325 /// may not have some schema types - as to which types it can used instead 326 /// when encountering a prim of one these types. 327 /// 328 /// \sa UsdStage::WriteFallbackPrimTypes 329 /// \sa \ref Usd_OM_FallbackPrimTypes GetFallbackPrimTypes()330 const VtDictionary &GetFallbackPrimTypes() const { 331 return _fallbackPrimTypes; 332 } 333 334 private: 335 friend class TfSingleton<UsdSchemaRegistry>; 336 337 UsdSchemaRegistry(); 338 339 // For the given full API schema name (which may be "type:instance" for 340 // multiple apply API schemas), finds and returns the prim definition for 341 // the API schema type. If the API schema is an instance of a multiple 342 // apply API, the full prefix that will be prepended to all properties 343 // when the schema is applied will be set in propertyPrefix. 344 const UsdPrimDefinition *_FindAPIPrimDefinitionByFullName( 345 const TfToken &apiSchemaName, std::string *propertyPrefix) const; 346 347 void _ComposeAPISchemasIntoPrimDefinition( 348 UsdPrimDefinition *primDef, 349 const TfTokenVector &appliedAPISchemas) const; 350 351 // Private class for helping initialize the schema registry. Defined 352 // entirely in the implementation. Declared here for private access to the 353 // registry. 354 class _SchemaDefInitHelper; 355 356 // Multiple apply API schema definitions want to be stored along with the 357 // their schema's property namespace prefix which is required to correctly 358 // apply them. 359 struct _MultipleApplyAPIDefinition { 360 UsdPrimDefinition *primDef = nullptr; 361 TfToken propertyNamespace; 362 }; 363 using _TypeNameToMultipleApplyAPIDefinitionMap = std::unordered_map< 364 TfToken, _MultipleApplyAPIDefinition, TfToken::HashFunctor>; 365 366 using _TypeNameToPrimDefinitionMap = std::unordered_map< 367 TfToken, UsdPrimDefinition *, TfToken::HashFunctor>; 368 369 SdfLayerRefPtr _schematics; 370 371 _TypeNameToPrimDefinitionMap _concreteTypedPrimDefinitions; 372 _TypeNameToPrimDefinitionMap _singleApplyAPIPrimDefinitions; 373 _TypeNameToMultipleApplyAPIDefinitionMap _multiApplyAPIPrimDefinitions; 374 UsdPrimDefinition *_emptyPrimDefinition; 375 376 VtDictionary _fallbackPrimTypes; 377 378 friend class UsdPrimDefinition; 379 }; 380 381 USD_API_TEMPLATE_CLASS(TfSingleton<UsdSchemaRegistry>); 382 383 // Utility function for extracting the metadata about applying API schemas from 384 // the plugin metadata for the schema's type. It is useful for certain clients 385 // to be able to access this plugin data in the same way that the 386 // UsdSchemaRegistry does. 387 void Usd_GetAPISchemaPluginApplyToInfoForType( 388 const TfType &apiSchemaType, 389 const TfToken &apiSchemaName, 390 std::map<TfToken, TfTokenVector> *autoApplyAPISchemasMap, 391 TfHashMap<TfToken, TfTokenVector, TfHash> *canOnlyApplyAPISchemasMap, 392 TfHashMap<TfToken, TfToken::Set, TfHash> *allowedInstanceNamesMap); 393 394 PXR_NAMESPACE_CLOSE_SCOPE 395 396 #endif //PXR_USD_USD_SCHEMA_REGISTRY_H 397