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_SDF_SCHEMA_H 25 #define PXR_USD_SDF_SCHEMA_H 26 27 #include "pxr/pxr.h" 28 #include "pxr/usd/sdf/api.h" 29 #include "pxr/usd/sdf/allowed.h" 30 #include "pxr/usd/sdf/types.h" 31 #include "pxr/usd/sdf/valueTypeName.h" 32 33 #include "pxr/base/plug/notice.h" 34 #include "pxr/base/tf/hash.h" 35 #include "pxr/base/tf/hashmap.h" 36 #include "pxr/base/tf/singleton.h" 37 #include "pxr/base/tf/staticTokens.h" 38 #include "pxr/base/tf/token.h" 39 #include "pxr/base/tf/type.h" 40 #include "pxr/base/tf/weakBase.h" 41 #include "pxr/base/vt/value.h" 42 43 #include <memory> 44 #include <string> 45 #include <vector> 46 47 PXR_NAMESPACE_OPEN_SCOPE 48 49 class JsValue; 50 class SdfPath; 51 class SdfPayload; 52 class SdfReference; 53 class Sdf_ValueTypeRegistry; 54 55 TF_DECLARE_WEAK_PTRS(PlugPlugin); 56 57 /// \class SdfSchemaBase 58 /// 59 /// Generic class that provides information about scene description fields 60 /// but doesn't actually provide any fields. 61 /// 62 class SdfSchemaBase : public TfWeakBase, public boost::noncopyable { 63 64 protected: 65 class _SpecDefiner; 66 67 public: 68 /// \class FieldDefinition 69 /// 70 /// Class defining various attributes for a field. 71 /// 72 class FieldDefinition { 73 public: 74 FieldDefinition( 75 const SdfSchemaBase& schema, 76 const TfToken& name, 77 const VtValue& fallbackValue); 78 79 typedef std::vector< std::pair<TfToken, JsValue> > InfoVec; 80 81 SDF_API const TfToken& GetName() const; 82 SDF_API const VtValue& GetFallbackValue() const; 83 SDF_API const InfoVec& GetInfo() const; 84 85 SDF_API bool IsPlugin() const; 86 SDF_API bool IsReadOnly() const; 87 SDF_API bool HoldsChildren() const; 88 89 /// Validation functions that return true if a given value passes 90 /// the registered validator or if no validator has been set. 91 /// @{ 92 93 template <class T> IsValidValue(const T & value)94 SdfAllowed IsValidValue(const T& value) const 95 { 96 return (_valueValidator ? 97 _valueValidator(_schema, VtValue(value)) : 98 SdfAllowed(true)); 99 } 100 101 template <class T> IsValidListValue(const T & value)102 SdfAllowed IsValidListValue(const T& value) const 103 { 104 return (_listValueValidator ? 105 _listValueValidator(_schema, VtValue(value)) : 106 SdfAllowed(true)); 107 } 108 109 template <class T> IsValidMapKey(const T & value)110 SdfAllowed IsValidMapKey(const T& value) const 111 { 112 return (_mapKeyValidator ? 113 _mapKeyValidator(_schema, VtValue(value)) : 114 SdfAllowed(true)); 115 } 116 117 template <class T> IsValidMapValue(const T & value)118 SdfAllowed IsValidMapValue(const T& value) const 119 { 120 return (_mapValueValidator ? 121 _mapValueValidator(_schema, VtValue(value)) : 122 SdfAllowed(true)); 123 } 124 125 /// @} 126 127 /// Functions for setting field attributes during registration. 128 /// @{ 129 130 FieldDefinition& FallbackValue(const VtValue& v); 131 132 FieldDefinition& Plugin(); 133 FieldDefinition& Children(); 134 FieldDefinition& ReadOnly(); 135 FieldDefinition& AddInfo(const TfToken& tok, const JsValue& val); 136 137 using Validator = 138 SdfAllowed (*) (const SdfSchemaBase&, const VtValue&); 139 FieldDefinition& ValueValidator(Validator v); 140 FieldDefinition& ListValueValidator(Validator v); 141 FieldDefinition& MapKeyValidator(Validator v); 142 FieldDefinition& MapValueValidator(Validator v); 143 144 /// @} 145 146 private: 147 const SdfSchemaBase& _schema; 148 TfToken _name; 149 VtValue _fallbackValue; 150 InfoVec _info; 151 152 bool _isPlugin; 153 bool _isReadOnly; 154 bool _holdsChildren; 155 156 Validator _valueValidator; 157 Validator _listValueValidator; 158 Validator _mapKeyValidator; 159 Validator _mapValueValidator; 160 }; 161 162 // Structure containing information about a field as it pertains to the 163 // spec this object defines. 164 struct _FieldInfo { _FieldInfo_FieldInfo165 _FieldInfo(): required(false), metadata(false) { } 166 bool required; 167 bool metadata; 168 TfToken metadataDisplayGroup; 169 }; 170 171 class SpecDefinition; 172 173 /// \class SpecDefinition 174 /// 175 /// Class representing fields and other information for a spec type. 176 /// 177 class SpecDefinition { 178 public: 179 /// Returns all fields for this spec. 180 SDF_API TfTokenVector GetFields() const; 181 182 /// Returns all value fields marked as required for this spec. GetRequiredFields()183 TfTokenVector const &GetRequiredFields() const { 184 return _requiredFields; 185 } 186 187 /// Returns all value fields marked as metadata for this spec. 188 SDF_API TfTokenVector GetMetadataFields() const; 189 190 /// Returns whether the given field is valid for this spec. 191 SDF_API bool IsValidField(const TfToken& name) const; 192 193 /// Returns whether the given field is metadata for this spec. 194 SDF_API bool IsMetadataField(const TfToken& name) const; 195 196 /// Returns the display group for this metadata field. Returns the 197 /// empty token if this field is not a metadata field or if this 198 /// metadata field has no display group. 199 SDF_API 200 TfToken GetMetadataFieldDisplayGroup(const TfToken& name) const; 201 202 /// Returns whether the given field is required for this spec. 203 SDF_API bool IsRequiredField(const TfToken& name) const; 204 205 206 private: 207 typedef TfHashMap<TfToken, _FieldInfo, TfToken::HashFunctor> 208 _FieldMap; 209 _FieldMap _fields; 210 211 // A separate vector of required field names from _fields. Access to 212 // these is in a hot path, so we cache them separately. 213 TfTokenVector _requiredFields; 214 215 private: 216 friend class _SpecDefiner; 217 void _AddField(const TfToken& name, const _FieldInfo& fieldInfo); 218 }; 219 220 /// Returns the field definition for the given field. 221 /// Returns NULL if no definition exists for given field. 222 SDF_API 223 const FieldDefinition* GetFieldDefinition(const TfToken &fieldKey) const; 224 225 /// Returns the spec definition for the given spec type. 226 /// Returns NULL if no definition exists for the given spec type. GetSpecDefinition(SdfSpecType specType)227 inline const SpecDefinition* GetSpecDefinition(SdfSpecType specType) const { 228 return _specDefinitions[specType].second ? 229 &_specDefinitions[specType].first : nullptr; 230 } 231 232 /// Convenience functions for accessing specific field information. 233 /// @{ 234 235 /// Return whether the specified field has been registered. Also 236 /// optionally return the fallback value. 237 SDF_API 238 bool IsRegistered(const TfToken &fieldKey, VtValue *fallback=NULL) const; 239 240 /// Returns whether the given field is a 'children' field -- that is, it 241 /// indexes certain children beneath the owning spec. 242 SDF_API 243 bool HoldsChildren(const TfToken &fieldKey) const; 244 245 /// Return the fallback value for the specified \p fieldKey or the 246 /// empty value if \p fieldKey is not registered. 247 SDF_API 248 const VtValue& GetFallback(const TfToken &fieldKey) const; 249 250 /// Coerce \p value to the correct type for the specified field. 251 SDF_API 252 VtValue CastToTypeOf(const TfToken &fieldKey, const VtValue &value) const; 253 254 /// Return whether the given field is valid for the given spec type. 255 SDF_API 256 bool IsValidFieldForSpec(const TfToken &fieldKey, SdfSpecType specType) const; 257 258 /// Returns all fields registered for the given spec type. 259 SDF_API TfTokenVector GetFields(SdfSpecType specType) const; 260 261 /// Returns all metadata fields registered for the given spec type. 262 SDF_API TfTokenVector GetMetadataFields(SdfSpecType specType) const; 263 264 /// Return the metadata field display group for metadata \a metadataField on 265 /// \a specType. Return the empty token if \a metadataField is not a 266 /// metadata field, or if it has no display group. 267 SDF_API 268 TfToken GetMetadataFieldDisplayGroup(SdfSpecType specType, 269 TfToken const &metadataField) const; 270 271 /// Returns all required fields registered for the given spec type. 272 SDF_API const TfTokenVector &GetRequiredFields(SdfSpecType specType) const; 273 274 /// Return true if \p fieldName is a required field name for at least one 275 /// spec type, return false otherwise. The main use of this function is to 276 /// quickly rule out field names that aren't required (and thus don't need 277 /// special handling). IsRequiredFieldName(const TfToken & fieldName)278 inline bool IsRequiredFieldName(const TfToken &fieldName) const { 279 for (size_t i = 0; i != _requiredFieldNames.size(); ++i) { 280 if (_requiredFieldNames[i] == fieldName) 281 return true; 282 } 283 return false; 284 } 285 286 /// @} 287 288 /// Specific validation functions for various fields. These are internally 289 /// registered as validators for the associated field, but can also be 290 /// used directly. 291 /// @{ 292 293 static SdfAllowed IsValidAttributeConnectionPath(const SdfPath& path); 294 static SdfAllowed IsValidIdentifier(const std::string& name); 295 static SdfAllowed IsValidNamespacedIdentifier(const std::string& name); 296 static SdfAllowed IsValidInheritPath(const SdfPath& path); 297 static SdfAllowed IsValidPayload(const SdfPayload& payload); 298 static SdfAllowed IsValidReference(const SdfReference& ref); 299 static SdfAllowed IsValidRelationshipTargetPath(const SdfPath& path); 300 static SdfAllowed IsValidRelocatesPath(const SdfPath& path); 301 static SdfAllowed IsValidSpecializesPath(const SdfPath& path); 302 static SdfAllowed IsValidSubLayer(const std::string& sublayer); 303 static SdfAllowed IsValidVariantIdentifier(const std::string& name); 304 305 /// @} 306 307 /// Scene description value types 308 /// @{ 309 310 /// Given a value, check if it is a valid value type. 311 /// This function only checks that the type of the value is valid 312 /// for this schema. It does not imply that the value is valid for 313 /// a particular field -- the field's validation function must be 314 /// used for that. 315 SDF_API 316 SdfAllowed IsValidValue(const VtValue& value) const; 317 318 /// Returns all registered type names. 319 SDF_API 320 std::vector<SdfValueTypeName> GetAllTypes() const; 321 322 /// Return the type name object for the given type name token. 323 SDF_API 324 SdfValueTypeName FindType(const TfToken& typeName) const; 325 /// \overload 326 SDF_API 327 SdfValueTypeName FindType(const char *typeName) const; 328 /// \overload 329 SDF_API 330 SdfValueTypeName FindType(std::string const &typeName) const; 331 332 /// Return the type name object for the given type and optional role. 333 SDF_API 334 SdfValueTypeName FindType(const TfType& type, 335 const TfToken& role = TfToken()) const; 336 337 /// Return the type name object for the value's type and optional role. 338 SDF_API 339 SdfValueTypeName FindType(const VtValue& value, 340 const TfToken& role = TfToken()) const; 341 342 /// Return the type name object for the given type name string if it 343 /// exists otherwise create a temporary type name object. Clients 344 /// should not normally need to call this. 345 SDF_API 346 SdfValueTypeName FindOrCreateType(const TfToken& typeName) const; 347 348 /// @} 349 350 protected: 351 /// \class _SpecDefiner 352 /// 353 /// Class that defines fields for a spec type. 354 /// 355 class _SpecDefiner { 356 public: 357 /// Functions for setting spec attributes during registration 358 /// @{ 359 360 _SpecDefiner& Field( 361 const TfToken& name, bool required = false); 362 _SpecDefiner& MetadataField( 363 const TfToken& name, bool required = false); 364 _SpecDefiner& MetadataField( 365 const TfToken& name, const TfToken& displayGroup, 366 bool required = false); 367 368 _SpecDefiner &CopyFrom(const SpecDefinition &other); 369 370 /// @} 371 private: 372 friend class SdfSchemaBase; _SpecDefiner(SdfSchemaBase * schema,SpecDefinition * definition)373 explicit _SpecDefiner(SdfSchemaBase *schema, SpecDefinition *definition) 374 : _schema(schema) 375 , _definition(definition) 376 {} 377 SdfSchemaBase *_schema; 378 SpecDefinition *_definition; 379 }; 380 381 /// A helper for registering value types. 382 class _ValueTypeRegistrar { 383 public: 384 explicit _ValueTypeRegistrar(Sdf_ValueTypeRegistry*); 385 386 class Type 387 { 388 public: 389 ~Type(); 390 391 // Specify a type with the given name, default value, and default 392 // array value of VtArray<T>. 393 template <class T> Type(const TfToken & name,const T & defaultValue)394 Type(const TfToken& name, const T& defaultValue) 395 : Type(name, VtValue(defaultValue), VtValue(VtArray<T>())) 396 { } 397 template <class T> Type(char const * name,const T & defaultValue)398 Type(char const *name, const T& defaultValue) 399 : Type(TfToken(name), 400 VtValue(defaultValue), VtValue(VtArray<T>())) 401 { } 402 403 // Specify a type with the given name and underlying C++ type. 404 // No default value or array value will be registered. 405 Type(const TfToken& name, const TfType& type); 406 407 // Set C++ type name string for this type. Defaults to type name 408 // from TfType. 409 Type& CPPTypeName(const std::string& cppTypeName); 410 411 // Set shape for this type. Defaults to shapeless. 412 Type& Dimensions(const SdfTupleDimensions& dims); 413 414 // Set default unit for this type. Defaults to dimensionless unit. 415 Type& DefaultUnit(TfEnum unit); 416 417 // Set role for this type. Defaults to no role. 418 Type& Role(const TfToken& role); 419 420 // Indicate that arrays of this type are not supported. 421 Type& NoArrays(); 422 423 private: 424 Type(const TfToken& name, 425 const VtValue& defaultValue, 426 const VtValue& defaultArrayValue); 427 428 class _Impl; 429 std::unique_ptr<_Impl> _impl; 430 431 friend class _ValueTypeRegistrar; 432 }; 433 434 /// Register a value type and its corresponding array value type. 435 void AddType(const Type& type); 436 437 private: 438 Sdf_ValueTypeRegistry* _registry; 439 }; 440 441 SdfSchemaBase(); 442 443 /// Construct an SdfSchemaBase but does not populate it with standard 444 /// fields and types. 445 class EmptyTag {}; 446 SdfSchemaBase(EmptyTag); 447 448 virtual ~SdfSchemaBase(); 449 450 /// Creates and registers a new field named \p fieldKey with the fallback 451 /// value \p fallback. If \p plugin is specified, it indicates that this 452 /// field is not a built-in field from this schema, but rather a field 453 /// that was externally registered. 454 /// 455 /// It is a fatal error to call this function with a key that has already 456 /// been used for another field. 457 template <class T> 458 FieldDefinition& _RegisterField( 459 const TfToken &fieldKey, const T &fallback, bool plugin = false) 460 { 461 return _CreateField(fieldKey, VtValue(fallback), plugin); 462 } 463 464 /// Registers the given spec \p type with this schema and return a 465 /// _SpecDefiner for specifying additional fields. _Define(SdfSpecType type)466 _SpecDefiner _Define(SdfSpecType type) { 467 // Mark the definition as valid and return a pointer to it. 468 _specDefinitions[type].second = true; 469 return _SpecDefiner(this, &_specDefinitions[type].first); 470 } 471 472 /// Returns a _SpecDefiner for the previously-defined spec \p type 473 /// for specifying additional fields. 474 _SpecDefiner _ExtendSpecDefinition(SdfSpecType specType); 475 476 /// Registers the standard fields. 477 void _RegisterStandardFields(); 478 479 /// Registers plugin fields and sets up handling so that fields will 480 /// be added when additional plugins are registered. 481 void _RegisterPluginFields(); 482 483 /// Registers standard attribute value types. 484 void _RegisterStandardTypes(); 485 486 /// Registers legacy attribute value types. 487 void _RegisterLegacyTypes(); 488 489 /// Returns a type registrar. 490 _ValueTypeRegistrar _GetTypeRegistrar() const; 491 492 /// Factory function for creating a default value for a metadata 493 /// field. The parameters are the value type name and default 494 /// value (if any) specified in the defining plugin. 495 typedef std::function<VtValue(const std::string&, const JsValue&)> 496 _DefaultValueFactoryFn; 497 498 /// Registers all metadata fields specified in the given plugins 499 /// under the given metadata tag. 500 const std::vector<const SdfSchemaBase::FieldDefinition *> 501 _UpdateMetadataFromPlugins(const PlugPluginPtrVector& plugins, 502 const std::string& metadataTag = 503 std::string(), 504 const _DefaultValueFactoryFn& defFactory = 505 _DefaultValueFactoryFn()); 506 507 private: 508 friend class _SpecDefiner; 509 510 void _OnDidRegisterPlugins(const PlugNotice::DidRegisterPlugins& n); 511 512 // Return a _SpecDefiner for an existing spec definition, \p local. _Define(SpecDefinition * local)513 _SpecDefiner _Define(SpecDefinition *local) { 514 return _SpecDefiner(this, local); 515 } 516 517 void _AddRequiredFieldName(const TfToken &name); 518 519 const SpecDefinition* _CheckAndGetSpecDefinition(SdfSpecType type) const; 520 521 friend struct Sdf_SchemaFieldTypeRegistrar; 522 FieldDefinition& _CreateField( 523 const TfToken &fieldKey, const VtValue &fallback, bool plugin = false); 524 525 template <class T> _DoRegisterField(const TfToken & fieldKey,const T & fallback)526 FieldDefinition& _DoRegisterField(const TfToken &fieldKey, const T &fallback) 527 { 528 return _DoRegisterField(fieldKey, VtValue(fallback)); 529 } 530 531 FieldDefinition& _DoRegisterField( 532 const TfToken &fieldKey, const VtValue &fallback); 533 534 private: 535 typedef TfHashMap<TfToken, SdfSchemaBase::FieldDefinition, 536 TfToken::HashFunctor> 537 _FieldDefinitionMap; 538 _FieldDefinitionMap _fieldDefinitions; 539 540 // Pair of definition and flag indicating validity. 541 std::pair<SdfSchemaBase::SpecDefinition, bool> 542 _specDefinitions[SdfNumSpecTypes]; 543 544 std::unique_ptr<Sdf_ValueTypeRegistry> _valueTypeRegistry; 545 TfTokenVector _requiredFieldNames; 546 }; 547 548 /// \class SdfSchema 549 /// 550 /// Class that provides information about the various scene description 551 /// fields. 552 /// 553 class SdfSchema : public SdfSchemaBase { 554 public: 555 SDF_API GetInstance()556 static const SdfSchema& GetInstance() 557 { 558 return TfSingleton<SdfSchema>::GetInstance(); 559 } 560 561 private: 562 friend class TfSingleton<SdfSchema>; 563 SdfSchema(); 564 virtual ~SdfSchema(); 565 }; 566 567 SDF_API_TEMPLATE_CLASS(TfSingleton<SdfSchema>); 568 569 /// 570 /// The following fields are pre-registered by Sdf. 571 /// \showinitializer 572 #define SDF_FIELD_KEYS \ 573 ((Active, "active")) \ 574 ((AllowedTokens, "allowedTokens")) \ 575 ((AssetInfo, "assetInfo")) \ 576 ((ColorConfiguration, "colorConfiguration")) \ 577 ((ColorManagementSystem, "colorManagementSystem")) \ 578 ((ColorSpace, "colorSpace")) \ 579 ((Comment, "comment")) \ 580 ((ConnectionPaths, "connectionPaths")) \ 581 ((Custom, "custom")) \ 582 ((CustomData, "customData")) \ 583 ((CustomLayerData, "customLayerData")) \ 584 ((Default, "default")) \ 585 ((DefaultPrim, "defaultPrim")) \ 586 ((DisplayGroup, "displayGroup")) \ 587 ((DisplayGroupOrder, "displayGroupOrder")) \ 588 ((DisplayName, "displayName")) \ 589 ((DisplayUnit, "displayUnit")) \ 590 ((Documentation, "documentation")) \ 591 ((EndTimeCode, "endTimeCode")) \ 592 ((FramePrecision, "framePrecision")) \ 593 ((FramesPerSecond, "framesPerSecond")) \ 594 ((Hidden, "hidden")) \ 595 ((HasOwnedSubLayers, "hasOwnedSubLayers")) \ 596 ((InheritPaths, "inheritPaths")) \ 597 ((Instanceable, "instanceable")) \ 598 ((Kind, "kind")) \ 599 ((PrimOrder, "primOrder")) \ 600 ((NoLoadHint, "noLoadHint")) \ 601 ((Owner, "owner")) \ 602 ((Payload, "payload")) \ 603 ((Permission, "permission")) \ 604 ((Prefix, "prefix")) \ 605 ((PrefixSubstitutions, "prefixSubstitutions")) \ 606 ((PropertyOrder, "propertyOrder")) \ 607 ((References, "references")) \ 608 ((Relocates, "relocates")) \ 609 ((SessionOwner, "sessionOwner")) \ 610 ((Specializes, "specializes")) \ 611 ((Specifier, "specifier")) \ 612 ((StartTimeCode, "startTimeCode")) \ 613 ((SubLayers, "subLayers")) \ 614 ((SubLayerOffsets, "subLayerOffsets")) \ 615 ((Suffix, "suffix")) \ 616 ((SuffixSubstitutions, "suffixSubstitutions")) \ 617 ((SymmetricPeer, "symmetricPeer")) \ 618 ((SymmetryArgs, "symmetryArgs")) \ 619 ((SymmetryArguments, "symmetryArguments")) \ 620 ((SymmetryFunction, "symmetryFunction")) \ 621 ((TargetPaths, "targetPaths")) \ 622 ((TimeSamples, "timeSamples")) \ 623 ((TimeCodesPerSecond, "timeCodesPerSecond")) \ 624 ((TypeName, "typeName")) \ 625 ((VariantSelection, "variantSelection")) \ 626 ((Variability, "variability")) \ 627 ((VariantSetNames, "variantSetNames")) \ 628 \ 629 /* XXX: These fields should move into Sd. See bug 123508. */ \ 630 ((EndFrame, "endFrame")) \ 631 ((StartFrame, "startFrame")) 632 633 #define SDF_CHILDREN_KEYS \ 634 ((ConnectionChildren, "connectionChildren")) \ 635 ((ExpressionChildren, "expressionChildren")) \ 636 ((MapperArgChildren, "mapperArgChildren")) \ 637 ((MapperChildren, "mapperChildren")) \ 638 ((PrimChildren, "primChildren")) \ 639 ((PropertyChildren, "properties")) \ 640 ((RelationshipTargetChildren, "targetChildren")) \ 641 ((VariantChildren, "variantChildren")) \ 642 ((VariantSetChildren, "variantSetChildren")) 643 644 TF_DECLARE_PUBLIC_TOKENS(SdfFieldKeys, SDF_API, SDF_FIELD_KEYS); 645 TF_DECLARE_PUBLIC_TOKENS(SdfChildrenKeys, SDF_API, SDF_CHILDREN_KEYS); 646 647 PXR_NAMESPACE_CLOSE_SCOPE 648 649 #endif // PXR_USD_SDF_SCHEMA_H 650