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_OBJECT_H 25 #define PXR_USD_USD_OBJECT_H 26 27 /// \file usd/object.h 28 29 #include "pxr/pxr.h" 30 #include "pxr/usd/usd/api.h" 31 #include "pxr/usd/usd/common.h" 32 #include "pxr/usd/usd/primData.h" 33 #include "pxr/usd/usd/stage.h" 34 35 #include "pxr/usd/sdf/abstractData.h" 36 #include "pxr/usd/sdf/path.h" 37 38 #include <type_traits> 39 40 PXR_NAMESPACE_OPEN_SCOPE 41 42 43 TF_DECLARE_WEAK_PTRS(UsdStage); 44 45 /// \enum UsdObjType 46 /// 47 /// Enum values to represent the various Usd object types. 48 /// 49 enum UsdObjType 50 { 51 // Value order matters in this enum. 52 UsdTypeObject, 53 UsdTypePrim, 54 UsdTypeProperty, 55 UsdTypeAttribute, 56 UsdTypeRelationship, 57 58 Usd_NumObjTypes 59 }; 60 61 62 namespace _Detail { 63 64 // A metafunction that takes a UsdObject class like UsdObject, UsdPrim, 65 // UsdProperty, etc, and gives its corresponding UsdObjType, e.g. UsdTypeObject, 66 // UsdTypePrim, UsdTypeProperty, etc. Usage: GetObjType<UsdPrim>::Value. 67 template <UsdObjType Type> 68 struct Const { static const UsdObjType Value = Type; }; 69 template <class T> struct GetObjType { 70 static_assert(std::is_base_of<UsdObject, T>::value, 71 "Type T must be a subclass of UsdObject."); 72 }; 73 template <> struct GetObjType<UsdObject> : Const<UsdTypeObject> {}; 74 template <> struct GetObjType<UsdPrim> : Const<UsdTypePrim> {}; 75 template <> struct GetObjType<UsdProperty> : Const<UsdTypeProperty> {}; 76 template <> struct GetObjType<UsdAttribute> : Const<UsdTypeAttribute> {}; 77 template <> struct GetObjType<UsdRelationship> : Const<UsdTypeRelationship> {}; 78 79 } // _Detail 80 81 /// Return true if \a subType is the same as or a subtype of \a baseType, false 82 /// otherwise. 83 inline bool 84 UsdIsSubtype(UsdObjType baseType, UsdObjType subType) { 85 return (baseType == UsdTypeObject) || (baseType == subType) || 86 (baseType == UsdTypeProperty && subType > UsdTypeProperty); 87 } 88 89 /// Return true if \a from is convertible to \a to, false otherwise. Equivalent 90 /// to UsdIsSubtype(to, from). 91 inline bool 92 UsdIsConvertible(UsdObjType from, UsdObjType to) { 93 return UsdIsSubtype(to, from); 94 } 95 96 /// Return true if \a type is a concrete object type, namely one of Prim, 97 /// Attribute, or Relationship. 98 inline bool 99 UsdIsConcrete(UsdObjType type) { 100 return type == UsdTypePrim || 101 type == UsdTypeAttribute || 102 type == UsdTypeRelationship; 103 } 104 105 /// \class UsdObject 106 /// 107 /// Base class for Usd scenegraph objects, providing common API. 108 /// 109 /// The commonality between the three types of scenegraph objects in Usd 110 /// (\ref UsdPrim, \ref UsdAttribute, \ref UsdRelationship) is that they can 111 /// all have metadata. Other objects in the API (\ref UsdReferences, 112 /// \ref UsdVariantSets, etc.) simply \em are kinds of metadata. 113 /// 114 /// UsdObject's API primarily provides schema for interacting with the metadata 115 /// common to all the scenegraph objects, as well as generic access to metadata. 116 /// 117 /// section Usd_UsdObject_Lifetime Lifetime Management and Object Validity 118 /// 119 /// Every derived class of UsdObject supports explicit detection of object 120 /// validity through an \em explicit-bool operator, so client code should always 121 /// be able use objects safely, even across edits to the owning UsdStage. 122 /// UsdObject classes also perform some level of validity checking upon every 123 /// use, in order to facilitate debugging of unsafe code, although we reserve 124 /// the right to activate that behavior only in debug builds, if it becomes 125 /// compelling to do so for performance reasons. This per-use checking will 126 /// cause a fatal error upon failing the inline validity check, with an error 127 /// message describing the namespace location of the dereferenced object on its 128 /// owning UsdStage. 129 /// 130 class UsdObject { 131 public: 132 /// Default constructor produces an invalid object. 133 UsdObject() : _type(UsdTypeObject) {} 134 135 // --------------------------------------------------------------------- // 136 /// \name Structural and Integrity Info about the Object itself 137 /// @{ 138 // --------------------------------------------------------------------- // 139 140 /// Return true if this is a valid object, false otherwise. 141 bool IsValid() const { 142 if (!UsdIsConcrete(_type) || !_prim) 143 return false; 144 if (_type == UsdTypePrim) 145 return true; 146 SdfSpecType specType = _GetDefiningSpecType(); 147 return (_type == UsdTypeAttribute && 148 specType == SdfSpecTypeAttribute) || 149 (_type == UsdTypeRelationship && 150 specType == SdfSpecTypeRelationship); 151 } 152 153 /// Returns \c true if this object is valid, \c false otherwise. 154 explicit operator bool() const { 155 return IsValid(); 156 } 157 158 public: 159 160 /// Equality comparison. Return true if \a lhs and \a rhs represent the 161 /// same UsdObject, false otherwise. 162 friend bool operator==(const UsdObject &lhs, const UsdObject &rhs) { 163 return lhs._type == rhs._type && 164 lhs._prim == rhs._prim && 165 lhs._proxyPrimPath == rhs._proxyPrimPath && 166 lhs._propName == rhs._propName; 167 } 168 169 /// Inequality comparison. Return false if \a lhs and \a rhs represent the 170 /// same UsdObject, true otherwise. 171 friend bool operator!=(const UsdObject &lhs, const UsdObject &rhs) { 172 return !(lhs == rhs); 173 } 174 175 /// Less-than operator. Returns true if \a lhs < \a rhs. 176 /// 177 /// This simply compares the paths of the objects. 178 friend bool operator<(const UsdObject &lhs, const UsdObject &rhs) { 179 return lhs.GetPath() < rhs.GetPath(); 180 } 181 182 // hash_value overload for std/boost hash. 183 USD_API 184 friend size_t hash_value(const UsdObject &obj); 185 186 /// Return the stage that owns the object, and to whose state and lifetime 187 /// this object's validity is tied. 188 USD_API 189 UsdStageWeakPtr GetStage() const; 190 191 /// Return the complete scene path to this object on its UsdStage, 192 /// which may (UsdPrim) or may not (all other subclasses) return a 193 /// cached result 194 SdfPath GetPath() const { 195 // Allow getting expired object paths. 196 if (!_proxyPrimPath.IsEmpty()) { 197 return _type == UsdTypePrim ? 198 _proxyPrimPath : _proxyPrimPath.AppendProperty(_propName); 199 } 200 else if (Usd_PrimDataConstPtr p = get_pointer(_prim)) { 201 return _type == UsdTypePrim ? 202 p->GetPath() : p->GetPath().AppendProperty(_propName); 203 } 204 return SdfPath(); 205 } 206 207 /// Return this object's path if this object is a prim, otherwise this 208 /// object's nearest owning prim's path. Equivalent to GetPrim().GetPath(). 209 const SdfPath &GetPrimPath() const { 210 // Allow getting expired object paths. 211 if (!_proxyPrimPath.IsEmpty()) { 212 return _proxyPrimPath; 213 } 214 else if (Usd_PrimDataConstPtr p = get_pointer(_prim)) { 215 return p->GetPath(); 216 } 217 return SdfPath::EmptyPath(); 218 } 219 220 /// Return this object if it is a prim, otherwise return this object's 221 /// nearest owning prim. 222 inline UsdPrim GetPrim() const; 223 224 /// Return the full name of this object, i.e. the last component of its 225 /// SdfPath in namespace. 226 /// 227 /// This is equivalent to, but generally cheaper than, 228 /// GetPath().GetNameToken() 229 const TfToken &GetName() const { 230 return _type == UsdTypePrim ? GetPrimPath().GetNameToken() : _propName; 231 } 232 233 /// Convert this UsdObject to another object type \p T if possible. Return 234 /// an invalid \p T instance if this object's dynamic type is not 235 /// convertible to \p T or if this object is invalid. 236 template <class T> 237 T As() const { 238 // compile-time type assertion provided by invoking Is<T>(). 239 return Is<T>() ? T(_type, _prim, _proxyPrimPath, _propName) : T(); 240 } 241 242 /// Return true if this object is convertible to \p T. This is equivalent 243 /// to but cheaper than: 244 /// \code 245 /// bool(obj.As<T>()) 246 /// \endcode 247 template <class T> 248 bool Is() const { 249 static_assert(std::is_base_of<UsdObject, T>::value, 250 "Provided type T must derive from or be UsdObject"); 251 return UsdIsConvertible(_type, _Detail::GetObjType<T>::Value); 252 } 253 254 /// Return a string that provides a brief summary description of the 255 /// object. This method, along with IsValid()/bool_operator, 256 /// is always safe to call on a possibly-expired object, and the 257 /// description will specify whether the object is valid or expired, 258 /// along with a few other bits of data. 259 USD_API 260 std::string GetDescription() const; 261 262 // --------------------------------------------------------------------- // 263 /// @} 264 // --------------------------------------------------------------------- // 265 266 267 // --------------------------------------------------------------------- // 268 /// \name Generic Metadata Access 269 /// @{ 270 // --------------------------------------------------------------------- // 271 272 /// Resolve the requested metadatum named \p key into \p value, 273 /// returning true on success. 274 /// 275 /// \return false if \p key was not resolvable, or if \p value's 276 /// type \c T differed from that of the resolved metadatum. 277 /// 278 /// \note For any composition-related metadata, as enumerated in 279 /// GetAllMetadata(), this method will return only the strongest 280 /// opinion found, not applying the composition rules used by Pcp 281 /// to process the data. For more processed/composed views of 282 /// composition data, please refer to the specific interface classes, 283 /// such as UsdReferences, UsdInherits, UsdVariantSets, etc. 284 /// 285 /// \sa \ref Usd_OM_Metadata 286 template<typename T> 287 bool GetMetadata(const TfToken& key, T* value) const; 288 /// \overload 289 /// 290 /// Type-erased access 291 USD_API 292 bool GetMetadata(const TfToken& key, VtValue* value) const; 293 294 /// Set metadatum \p key's value to \p value. 295 /// 296 /// \return false if \p value's type does not match the schema type 297 /// for \p key. 298 /// 299 /// \sa \ref Usd_OM_Metadata 300 template<typename T> 301 bool SetMetadata(const TfToken& key, const T& value) const; 302 /// \overload 303 USD_API 304 bool SetMetadata(const TfToken& key, const VtValue& value) const; 305 306 /// Clears the authored \a key's value at the current EditTarget, 307 /// returning false on error. 308 /// 309 /// If no value is present, this method is a no-op and returns true. It is 310 /// considered an error to call ClearMetadata when no spec is present for 311 /// this UsdObject, i.e. if the object has no presence in the 312 /// current UsdEditTarget. 313 /// 314 /// \sa \ref Usd_OM_Metadata 315 USD_API 316 bool ClearMetadata(const TfToken& key) const; 317 318 /// Returns true if the \a key has a meaningful value, that is, if 319 /// GetMetadata() will provide a value, either because it was authored 320 /// or because a prim's metadata fallback will be provided. 321 USD_API 322 bool HasMetadata(const TfToken& key) const; 323 324 /// Returns true if the \a key has an authored value, false if no 325 /// value was authored or the only value available is a prim's metadata 326 /// fallback. 327 USD_API 328 bool HasAuthoredMetadata(const TfToken& key) const; 329 330 /// Resolve the requested dictionary sub-element \p keyPath of 331 /// dictionary-valued metadatum named \p key into \p value, 332 /// returning true on success. 333 /// 334 /// If you know you neeed just a small number of elements from a dictionary, 335 /// accessing them element-wise using this method can be much less 336 /// expensive than fetching the entire dictionary with GetMetadata(key). 337 /// 338 /// \return false if \p key was not resolvable, or if \p value's 339 /// type \c T differed from that of the resolved metadatum. 340 /// 341 /// The \p keyPath is a ':'-separated path addressing an element 342 /// in subdictionaries. 343 /// 344 /// \sa \ref Usd_Dictionary_Type 345 template <class T> 346 bool GetMetadataByDictKey( 347 const TfToken& key, const TfToken &keyPath, T *value) const; 348 /// \overload 349 USD_API 350 bool GetMetadataByDictKey( 351 const TfToken& key, const TfToken &keyPath, VtValue *value) const; 352 353 /// Author \p value to the field identified by \p key and \p keyPath 354 /// at the current EditTarget. The \p keyPath is a ':'-separated path 355 /// identifying a value in subdictionaries stored in the metadata field at 356 /// \p key. Return true if the value is authored successfully, false 357 /// otherwise. 358 /// 359 /// \sa \ref Usd_Dictionary_Type 360 template<typename T> 361 bool SetMetadataByDictKey( 362 const TfToken& key, const TfToken &keyPath, const T& value) const; 363 /// \overload 364 USD_API 365 bool SetMetadataByDictKey( 366 const TfToken& key, const TfToken &keyPath, const VtValue& value) const; 367 368 /// Clear any authored value identified by \p key and \p keyPath 369 /// at the current EditTarget. The \p keyPath is a ':'-separated path 370 /// identifying a path in subdictionaries stored in the metadata field at 371 /// \p key. Return true if the value is cleared successfully, false 372 /// otherwise. 373 /// 374 /// \sa \ref Usd_Dictionary_Type 375 USD_API 376 bool ClearMetadataByDictKey( 377 const TfToken& key, const TfToken& keyPath) const; 378 379 /// Return true if there exists any authored or fallback opinion for 380 /// \p key and \p keyPath. The \p keyPath is a ':'-separated path 381 /// identifying a value in subdictionaries stored in the metadata field at 382 /// \p key. 383 /// 384 /// \sa \ref Usd_Dictionary_Type 385 USD_API 386 bool HasMetadataDictKey( 387 const TfToken& key, const TfToken &keyPath) const; 388 389 /// Return true if there exists any authored opinion (excluding 390 /// fallbacks) for \p key and \p keyPath. The \p keyPath is a ':'-separated 391 /// path identifying a value in subdictionaries stored in the metadata field 392 /// at \p key. 393 /// 394 /// \sa \ref Usd_Dictionary_Type 395 USD_API 396 bool HasAuthoredMetadataDictKey( 397 const TfToken& key, const TfToken &keyPath) const; 398 399 /// Resolve and return all metadata (including both authored and 400 /// fallback values) on this object, sorted lexicographically. 401 /// 402 /// \note This method does not return field keys for composition arcs, 403 /// such as references, inherits, payloads, sublayers, variants, or 404 /// primChildren, nor does it return the default value or timeSamples. 405 USD_API 406 UsdMetadataValueMap GetAllMetadata() const; 407 408 /// Resolve and return all user-authored metadata on this object, 409 /// sorted lexicographically. 410 /// 411 /// \note This method does not return field keys for composition arcs, 412 /// such as references, inherits, payloads, sublayers, variants, or 413 /// primChildren, nor does it return the default value or timeSamples. 414 USD_API 415 UsdMetadataValueMap GetAllAuthoredMetadata() const; 416 417 // --------------------------------------------------------------------- // 418 /// @} 419 // --------------------------------------------------------------------- // 420 421 // --------------------------------------------------------------------- // 422 /// \name Core metadata fields 423 /// @{ 424 // --------------------------------------------------------------------- // 425 426 /// Gets the value of the 'hidden' metadata field, false if not 427 /// authored. 428 /// 429 /// When an object is marked as hidden, it is an indicator to clients who 430 /// generically display objects (such as GUI widgets) that this object 431 /// should not be included, unless explicitly asked for. Although this 432 /// is just a hint and thus up to each application to interpret, we 433 /// use it primarily as a way of simplifying hierarchy displays, by 434 /// hiding \em only the representation of the object itself, \em not its 435 /// subtree, instead "pulling up" everything below it one level in the 436 /// hierarchical nesting. 437 /// 438 /// Note again that this is a hint for UI only - it should not be 439 /// interpreted by any renderer as making a prim invisible to drawing. 440 USD_API 441 bool IsHidden() const; 442 443 /// Sets the value of the 'hidden' metadata field. See IsHidden() 444 /// for details. 445 USD_API 446 bool SetHidden(bool hidden) const; 447 448 /// Clears the opinion for "Hidden" at the current EditTarget. 449 USD_API 450 bool ClearHidden() const; 451 452 /// Returns true if hidden was explicitly authored and GetMetadata() 453 /// will return a meaningful value for Hidden. 454 /// 455 /// Note that IsHidden returns a fallback value (false) when hidden is not 456 /// authored. 457 USD_API 458 bool HasAuthoredHidden() const; 459 460 /// Return this object's composed customData dictionary. 461 /// 462 /// CustomData is "custom metadata", a place for applications and users 463 /// to put uniform data that is entirely dynamic and subject to no schema 464 /// known to Usd. Unlike metadata like 'hidden', 'displayName' etc, 465 /// which must be declared in code or a data file that is considered part 466 /// of one's Usd distribution (e.g. a plugInfo.json file) to be used, 467 /// customData keys and the datatypes of their corresponding values are 468 /// ad hoc. No validation will ever be performed that values for the 469 /// same key in different layers are of the same type - strongest simply 470 /// wins. 471 /// 472 /// Dictionaries like customData are composed element-wise, and are 473 /// nestable. 474 /// 475 /// There is no means to query a customData field's valuetype other 476 /// than fetching the value and interrogating it. 477 /// \sa GetCustomDataByKey() 478 USD_API 479 VtDictionary GetCustomData() const; 480 481 /// Return the element identified by \p keyPath in this object's 482 /// composed customData dictionary. The \p keyPath is a ':'-separated path 483 /// identifying a value in subdictionaries. This is in general more 484 /// efficient than composing the entire customData dictionary and then 485 /// pulling out one sub-element. 486 USD_API 487 VtValue GetCustomDataByKey(const TfToken &keyPath) const; 488 489 /// Author this object's customData dictionary to \p customData at 490 /// the current EditTarget. 491 USD_API 492 void SetCustomData(const VtDictionary &customData) const; 493 494 /// Author the element identified by \p keyPath in this object's 495 /// customData dictionary at the current EditTarget. The \p keyPath is a 496 /// ':'-separated path identifying a value in subdictionaries. 497 USD_API 498 void SetCustomDataByKey(const TfToken &keyPath, const VtValue &value) const; 499 500 /// Clear the authored opinion for this object's customData 501 /// dictionary at the current EditTarget. Do nothing if there is no such 502 /// authored opinion. 503 USD_API 504 void ClearCustomData() const; 505 506 /// Clear the authored opinion identified by \p keyPath in this 507 /// object's customData dictionary at the current EditTarget. The \p 508 /// keyPath is a ':'-separated path identifying a value in subdictionaries. 509 /// Do nothing if there is no such authored opinion. 510 USD_API 511 void ClearCustomDataByKey(const TfToken &keyPath) const; 512 513 /// Return true if there are any authored or fallback opinions for 514 /// this object's customData dictionary, false otherwise. 515 USD_API 516 bool HasCustomData() const; 517 518 /// Return true if there are any authored or fallback opinions for 519 /// the element identified by \p keyPath in this object's customData 520 /// dictionary, false otherwise. The \p keyPath is a ':'-separated path 521 /// identifying a value in subdictionaries. 522 USD_API 523 bool HasCustomDataKey(const TfToken &keyPath) const; 524 525 /// Return true if there are any authored opinions (excluding 526 /// fallback) for this object's customData dictionary, false otherwise. 527 USD_API 528 bool HasAuthoredCustomData() const; 529 530 /// Return true if there are any authored opinions (excluding 531 /// fallback) for the element identified by \p keyPath in this object's 532 /// customData dictionary, false otherwise. The \p keyPath is a 533 /// ':'-separated path identifying a value in subdictionaries. 534 USD_API 535 bool HasAuthoredCustomDataKey(const TfToken &keyPath) const; 536 537 /// Return this object's composed assetInfo dictionary. 538 /// 539 /// The asset info dictionary is used to annotate objects representing the 540 /// root-prims of assets (generally organized as models) with various 541 /// data related to asset management. For example, asset name, root layer 542 /// identifier, asset version etc. 543 /// 544 /// The elements of this dictionary are composed element-wise, and are 545 /// nestable. 546 /// 547 /// There is no means to query an assetInfo field's valuetype other 548 /// than fetching the value and interrogating it. 549 /// \sa GetAssetInfoByKey() 550 USD_API 551 VtDictionary GetAssetInfo() const; 552 553 /// Return the element identified by \p keyPath in this object's 554 /// composed assetInfo dictionary. The \p keyPath is a ':'-separated path 555 /// identifying a value in subdictionaries. This is in general more 556 /// efficient than composing the entire assetInfo dictionary than 557 /// pulling out one sub-element. 558 USD_API 559 VtValue GetAssetInfoByKey(const TfToken &keyPath) const; 560 561 /// Author this object's assetInfo dictionary to \p assetInfo at 562 /// the current EditTarget. 563 USD_API 564 void SetAssetInfo(const VtDictionary &customData) const; 565 566 /// Author the element identified by \p keyPath in this object's 567 /// assetInfo dictionary at the current EditTarget. The \p keyPath is a 568 /// ':'-separated path identifying a value in subdictionaries. 569 USD_API 570 void SetAssetInfoByKey(const TfToken &keyPath, const VtValue &value) const; 571 572 /// Clear the authored opinion for this object's assetInfo 573 /// dictionary at the current EditTarget. Do nothing if there is no such 574 /// authored opinion. 575 USD_API 576 void ClearAssetInfo() const; 577 578 /// Clear the authored opinion identified by \p keyPath in this 579 /// object's assetInfo dictionary at the current EditTarget. The \p 580 /// keyPath is a ':'-separated path identifying a value in subdictionaries. 581 /// Do nothing if there is no such authored opinion. 582 USD_API 583 void ClearAssetInfoByKey(const TfToken &keyPath) const; 584 585 /// Return true if there are any authored or fallback opinions for 586 /// this object's assetInfo dictionary, false otherwise. 587 USD_API 588 bool HasAssetInfo() const; 589 590 /// Return true if there are any authored or fallback opinions for 591 /// the element identified by \p keyPath in this object's assetInfo 592 /// dictionary, false otherwise. The \p keyPath is a ':'-separated path 593 /// identifying a value in subdictionaries. 594 USD_API 595 bool HasAssetInfoKey(const TfToken &keyPath) const; 596 597 /// Return true if there are any authored opinions (excluding 598 /// fallback) for this object's assetInfo dictionary, false otherwise. 599 USD_API 600 bool HasAuthoredAssetInfo() const; 601 602 /// Return true if there are any authored opinions (excluding 603 /// fallback) for the element identified by \p keyPath in this object's 604 /// assetInfo dictionary, false otherwise. The \p keyPath is a 605 /// ':'-separated path identifying a value in subdictionaries. 606 USD_API 607 bool HasAuthoredAssetInfoKey(const TfToken &keyPath) const; 608 609 /// Return this object's documentation (metadata). This returns the 610 /// empty string if no documentation has been set. 611 /// \sa SetDocumentation() 612 USD_API 613 std::string GetDocumentation() const; 614 615 /// Sets this object's documentation (metadata). Returns true on success. 616 USD_API 617 bool SetDocumentation(const std::string& doc) const; 618 619 /// Clears this object's documentation (metadata) in the current EditTarget 620 /// (only). Returns true on success. 621 USD_API 622 bool ClearDocumentation() const; 623 624 /// Returns true if documentation was explicitly authored and GetMetadata() 625 /// will return a meaningful value for documentation. 626 USD_API 627 bool HasAuthoredDocumentation() const; 628 629 // --------------------------------------------------------------------- // 630 /// @} 631 // --------------------------------------------------------------------- // 632 633 // XXX: This method can and probably should move to UsdProperty 634 static char GetNamespaceDelimiter() 635 { return SdfPathTokens->namespaceDelimiter.GetText()[0]; } 636 637 private: 638 template <class T> 639 bool _GetMetadataImpl(const TfToken& key, 640 T* value, 641 const TfToken &keyPath=TfToken()) const; 642 643 bool _GetMetadataImpl(const TfToken& key, 644 VtValue* value, 645 const TfToken &keyPath=TfToken()) const; 646 647 template <class T> 648 bool _SetMetadataImpl(const TfToken& key, 649 const T& value, 650 const TfToken &keyPath=TfToken()) const; 651 652 bool _SetMetadataImpl(const TfToken& key, 653 const VtValue& value, 654 const TfToken &keyPath=TfToken()) const; 655 656 protected: 657 template <class Derived> struct _Null {}; 658 659 // Private constructor for null dervied types. 660 template <class Derived> 661 explicit UsdObject(_Null<Derived>) 662 : _type(_Detail::GetObjType<Derived>::Value) {} 663 664 // Private constructor for UsdPrim. 665 UsdObject(const Usd_PrimDataHandle &prim, 666 const SdfPath &proxyPrimPath) 667 : _type(UsdTypePrim) 668 , _prim(prim) 669 , _proxyPrimPath(proxyPrimPath) 670 { 671 TF_VERIFY(!_prim || _prim->GetPath() != _proxyPrimPath); 672 } 673 674 // Private constructor for UsdAttribute/UsdRelationship. 675 UsdObject(UsdObjType objType, 676 const Usd_PrimDataHandle &prim, 677 const SdfPath &proxyPrimPath, 678 const TfToken &propName) 679 : _type(objType) 680 , _prim(prim) 681 , _proxyPrimPath(proxyPrimPath) 682 , _propName(propName) 683 { 684 TF_VERIFY(!_prim || _prim->GetPath() != _proxyPrimPath); 685 } 686 687 // Return the stage this object belongs to. 688 UsdStage *_GetStage() const { return _prim->GetStage(); } 689 690 // Return this object's defining spec type. 691 USD_API 692 SdfSpecType _GetDefiningSpecType() const; 693 694 // Helper for subclasses: return held prim data. 695 const Usd_PrimDataHandle &_Prim() const { return _prim; } 696 697 // Helper for subclasses: return held property name. 698 const TfToken &_PropName() const { return _propName; } 699 700 // Helper for subclasses: return held proxy prim path. 701 const SdfPath &_ProxyPrimPath() const { return _proxyPrimPath; } 702 703 private: 704 // Helper for the above helper, and also for GetDescription() 705 std::string _GetObjectDescription(const std::string &preface) const; 706 707 friend class UsdStage; 708 709 friend UsdObjType Usd_GetObjType(const UsdObject &obj) { 710 return obj._type; 711 } 712 713 UsdObjType _type; 714 Usd_PrimDataHandle _prim; 715 SdfPath _proxyPrimPath; 716 TfToken _propName; 717 718 }; 719 720 template<typename T> 721 inline 722 bool 723 UsdObject::GetMetadata(const TfToken& key, T* value) const 724 { 725 return _GetMetadataImpl(key, value); 726 } 727 728 template<typename T> 729 inline 730 bool 731 UsdObject::SetMetadata(const TfToken& key, const T& value) const 732 { 733 return _SetMetadataImpl(key, value); 734 } 735 736 template <typename T> 737 inline 738 bool 739 UsdObject::GetMetadataByDictKey(const TfToken& key, 740 const TfToken &keyPath, 741 T *value) const 742 { 743 return _GetMetadataImpl(key, value, keyPath); 744 } 745 746 template <typename T> 747 inline 748 bool 749 UsdObject::SetMetadataByDictKey(const TfToken& key, 750 const TfToken &keyPath, 751 const T& value) const 752 { 753 return _SetMetadataImpl(key, value, keyPath); 754 } 755 756 template <class T> 757 bool 758 UsdObject::_GetMetadataImpl(const TfToken& key, 759 T* value, 760 const TfToken &keyPath) const 761 { 762 return _GetStage()->_GetMetadata( 763 *this, key, keyPath, /*useFallbacks=*/true, value); 764 } 765 766 template <class T> 767 bool 768 UsdObject::_SetMetadataImpl(const TfToken& key, 769 const T& value, 770 const TfToken &keyPath) const 771 { 772 return _GetStage()->_SetMetadata(*this, key, keyPath, value); 773 } 774 775 PXR_NAMESPACE_CLOSE_SCOPE 776 777 #endif //PXR_USD_USD_OBJECT_H 778