Loading...
Searching...
No Matches
abstractData.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_USD_SDF_ABSTRACT_DATA_H
8#define PXR_USD_SDF_ABSTRACT_DATA_H
9
10#include "pxr/pxr.h"
11#include "pxr/usd/sdf/path.h"
12#include "pxr/usd/sdf/types.h"
13
14#include "pxr/base/vt/value.h"
15
17#include "pxr/base/tf/token.h"
18#include "pxr/base/tf/refBase.h"
21
22#include <vector>
23#include <type_traits>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
31
32
33#define SDF_DATA_TOKENS \
34 ((TimeSamples, "timeSamples"))
35
36TF_DECLARE_PUBLIC_TOKENS(SdfDataTokens, SDF_API, SDF_DATA_TOKENS);
37
38
56class SdfAbstractData : public TfRefBase, public TfWeakBase
57{
58public:
60 SDF_API
61 virtual ~SdfAbstractData();
62
67 SDF_API
68 virtual void CopyFrom(const SdfAbstractDataConstPtr& source);
69
77 SDF_API
78 virtual bool StreamsData() const = 0;
79
98 SDF_API
99 virtual bool IsDetached() const;
100
105 SDF_API
106 virtual bool IsEmpty() const;
107
113 // XXX: What are the right semantics for this?
114 // Does it matter if the underlying implementation matches?
115 SDF_API
116 virtual bool Equals(const SdfAbstractDataRefPtr &rhs) const;
117
122 SDF_API
123 virtual void WriteToStream(std::ostream& out) const;
124
127
130 SDF_API
131 virtual void CreateSpec(const SdfPath &path,
132 SdfSpecType specType) = 0;
133
135 SDF_API
136 virtual bool HasSpec(const SdfPath &path) const = 0;
137
140 SDF_API
141 virtual void EraseSpec(const SdfPath &path) = 0;
142
145 SDF_API
146 virtual void MoveSpec(const SdfPath &oldPath,
147 const SdfPath &newPath) = 0;
148
151 virtual SdfSpecType GetSpecType(const SdfPath &path) const = 0;
152
157 SDF_API
159
161
164
167 SDF_API
168 virtual bool Has(const SdfPath& path, const TfToken& fieldName,
169 SdfAbstractDataValue* value) const = 0;
170
173 SDF_API
174 virtual bool Has(const SdfPath& path, const TfToken &fieldName,
175 VtValue *value = NULL) const = 0;
176
187 SDF_API
188 virtual bool
189 HasSpecAndField(const SdfPath &path, const TfToken &fieldName,
190 SdfAbstractDataValue *value, SdfSpecType *specType) const;
191
202 SDF_API
203 virtual bool
204 HasSpecAndField(const SdfPath &path, const TfToken &fieldName,
205 VtValue *value, SdfSpecType *specType) const;
206
209 SDF_API
210 virtual VtValue Get(const SdfPath& path,
211 const TfToken& fieldName) const = 0;
212
221 SDF_API
222 virtual std::type_info const &
223 GetTypeid(const SdfPath &path, const TfToken &fieldName) const;
224
229 SDF_API
230 virtual void Set(const SdfPath &path, const TfToken &fieldName,
231 const VtValue &value) = 0;
232
236 SDF_API
237 virtual void Set(const SdfPath &path, const TfToken &fieldName,
238 const SdfAbstractDataConstValue& value) = 0;
239
241 SDF_API
242 virtual void Erase(const SdfPath& path,
243 const TfToken& fieldName) = 0;
244
246 SDF_API
247 virtual std::vector<TfToken> List(const SdfPath& path) const = 0;
248
251 template <class T>
252 inline T GetAs(const SdfPath& path, const TfToken& fieldName,
253 const T& defaultValue = T()) const;
254
256
257
260
261 // Return true and set \p value (if non null) if the field identified by
262 // \p path and \p fieldName is dictionary-valued, and if there is an element
263 // at \p keyPath in that dictionary. Return false otherwise. If
264 // \p keyPath names an entire sub-dictionary, set \p value to that entire
265 // sub-dictionary and return true.
266 SDF_API
267 virtual bool HasDictKey(const SdfPath& path,
268 const TfToken &fieldName,
269 const TfToken &keyPath,
270 SdfAbstractDataValue* value) const;
271 SDF_API
272 virtual bool HasDictKey(const SdfPath& path,
273 const TfToken &fieldName,
274 const TfToken &keyPath,
275 VtValue *value = NULL) const;
276
277 // Same as HasDictKey but return empty VtValue on failure.
278 SDF_API
279 virtual VtValue GetDictValueByKey(const SdfPath& path,
280 const TfToken &fieldName,
281 const TfToken &keyPath) const;
282
283 // Set the element at \p keyPath in the dictionary-valued field identified
284 // by \p path and \p fieldName. If the field itself is not
285 // dictionary-valued, replace the field with a new dictionary and set the
286 // element at \p keyPath in it. If \p value is empty, invoke
287 // EraseDictValueByKey instead.
288 SDF_API
289 virtual void SetDictValueByKey(const SdfPath& path,
290 const TfToken &fieldName,
291 const TfToken &keyPath,
292 const VtValue &value);
293 SDF_API
294 virtual void SetDictValueByKey(const SdfPath& path,
295 const TfToken &fieldName,
296 const TfToken &keyPath,
297 const SdfAbstractDataConstValue& value);
298
299 // If \p path and \p fieldName identify a dictionary-valued field with an
300 // element at \p keyPath, remove that element from the dictionary. If this
301 // leaves the dictionary empty, Erase() the entire field.
302 SDF_API
303 virtual void EraseDictValueByKey(const SdfPath& path,
304 const TfToken &fieldName,
305 const TfToken &keyPath);
306
307 // If \p path, \p fieldName, and \p keyPath identify a (sub) dictionary,
308 // return a vector of the keys in that dictionary, otherwise return an empty
309 // vector.
310 SDF_API
311 virtual std::vector<TfToken> ListDictKeys(const SdfPath& path,
312 const TfToken &fieldName,
313 const TfToken &keyPath) const;
314
315
317
318
328
329 SDF_API
330 virtual std::set<double>
331 ListAllTimeSamples() const = 0;
332
333 SDF_API
334 virtual std::set<double>
335 ListTimeSamplesForPath(const SdfPath& path) const = 0;
336
337 SDF_API
338 virtual bool
339 GetBracketingTimeSamples(double time, double* tLower,
340 double* tUpper) const = 0;
341
342 SDF_API
343 virtual size_t
344 GetNumTimeSamplesForPath(const SdfPath& path) const = 0;
345
346 SDF_API
347 virtual bool
348 GetBracketingTimeSamplesForPath(const SdfPath& path,
349 double time,
350 double* tLower, double* tUpper) const = 0;
351
364 SDF_API
365 virtual bool
366 GetPreviousTimeSampleForPath(const SdfPath& path, double time,
367 double* tPrevious) const;
368
369 SDF_API
370 virtual bool
371 QueryTimeSample(const SdfPath& path, double time,
372 VtValue *optionalValue = NULL) const = 0;
373 SDF_API
374 virtual bool
375 QueryTimeSample(const SdfPath& path, double time,
376 SdfAbstractDataValue *optionalValue) const = 0;
377
385 SDF_API
386 virtual const std::type_info &
387 QueryTimeSampleTypeid(const SdfPath &path, double time) const;
388
389 SDF_API
390 virtual void
391 SetTimeSample(const SdfPath& path, double time,
392 const VtValue & value) = 0;
393
394 SDF_API
395 virtual void
396 EraseTimeSample(const SdfPath& path, double time) = 0;
397
399
400protected:
406 SDF_API
407 virtual void _VisitSpecs(SdfAbstractDataSpecVisitor* visitor) const = 0;
408};
409
410template <class T>
412 const SdfPath& path,
413 const TfToken& field, const T& defaultVal) const
414{
415 VtValue val = Get(path, field);
416 if (val.IsHolding<T>()) {
417 return val.UncheckedGet<T>();
418 }
419 return defaultVal;
420}
421
428{
429public:
430 template <class T>
431 bool StoreValue(T &&v)
432 {
433 // this can be std::remove_cvref_t in c++20.
434 using Type = std::remove_cv_t<std::remove_reference_t<T>>;
435
436 if constexpr (std::is_same_v<Type, VtValue>) {
437 return _StoreVtValue(std::forward<T>(v));
438 }
439
440 isValueBlock = false;
441 isAnimationBlock = false;
442 typeMismatch = false;
443 if constexpr (std::is_same_v<Type, SdfValueBlock>) {
444 isValueBlock = true;
445 return true;
446 } else if constexpr (std::is_same_v<Type, SdfAnimationBlock>) {
447 isAnimationBlock = true;
448 return true;
449 }
450 if (TfSafeTypeCompare(typeid(Type), valueType)) {
451 *static_cast<Type*>(value) = std::forward<T>(v);
452 return true;
453 }
454 typeMismatch = true;
455 return false;
456 }
457
458 void* value;
459 const std::type_info& valueType;
460 bool isValueBlock;
461 bool isAnimationBlock;
462 bool typeMismatch;
463
464protected:
465 SdfAbstractDataValue(void* value_, const std::type_info& valueType_)
466 : value(value_)
467 , valueType(valueType_)
468 , isValueBlock(false)
469 , isAnimationBlock(false)
470 , typeMismatch(false)
471 { }
472
473private:
474 virtual bool _StoreVtValue(const VtValue& value) = 0;
475 virtual bool _StoreVtValue(VtValue &&value) = 0;
476};
477
491template <class T>
493{
494public:
496 : SdfAbstractDataValue(value, typeid(T))
497 { }
498
499private:
500 T const &_Get(const VtValue &v) {
501 return v.UncheckedGet<T>();
502 }
503
504 T _Get(VtValue &&v) {
505 return v.UncheckedRemove<T>();
506 }
507
508 template <class Value>
509 bool _StoreVtValueImpl(Value &&v) {
510 typeMismatch = false;
511 isValueBlock = false;
512 isAnimationBlock = false;
513 if (ARCH_LIKELY(std::forward<Value>(v).template IsHolding<T>())) {
514 *static_cast<T*>(value) = _Get(std::forward<Value>(v));
515 if constexpr (std::is_same_v<T, SdfValueBlock>) {
516 isValueBlock = true;
517 } else if constexpr (std::is_same_v<T, SdfAnimationBlock>) {
518 isAnimationBlock = true;
519 }
520 return true;
521 }
522
523 if (std::forward<Value>(v).template IsHolding<SdfValueBlock>()) {
524 isValueBlock = true;
525 return true;
526 }
527 else if (std::forward<Value>(v).template IsHolding<SdfAnimationBlock>())
528 {
529 isAnimationBlock = true;
530 return true;
531 }
532
533 typeMismatch = true;
534
535 return false;
536 }
537
538 virtual bool
539 _StoreVtValue(const VtValue& v) override {
540 return _StoreVtValueImpl(v);
541 }
542
543 virtual bool
544 _StoreVtValue(VtValue &&v) override {
545 return _StoreVtValueImpl(v);
546 }
547};
548
555{
556public:
557 virtual bool GetValue(VtValue* value) const = 0;
558
559 template <class T> bool GetValue(T* v) const
560 {
561 if (TfSafeTypeCompare(typeid(T), valueType)) {
562 *v = *static_cast<const T*>(value);
563 return true;
564 }
565 return false;
566 }
567
568 virtual bool IsEqual(const VtValue& value) const = 0;
569
570 const void* value;
571 const std::type_info& valueType;
572 const bool isArrayEdit;
573 const std::type_info& elementValueType; // void unless isArrayEdit
574
575protected:
576 SdfAbstractDataConstValue(const void* value_,
577 const std::type_info& valueType_,
578 const bool isArrayEdit_,
579 const std::type_info& elementValueType_)
580 : value(value_)
581 , valueType(valueType_)
582 , isArrayEdit(isArrayEdit_)
583 , elementValueType(elementValueType_)
584 {
585 }
586};
587
601template <class T>
603{
604public:
605 static std::type_info const &_GetElementType() {
606 if constexpr (VtIsArrayEdit<T>::value) {
607 return typeid(typename T::ElementType);
608 }
609 else {
610 return typeid(void);
611 }
612 }
613
614 SdfAbstractDataConstTypedValue(const T* value)
616 value, typeid(T), VtIsArrayEdit<T>::value, this->_GetElementType())
617 {}
618
619 virtual bool GetValue(VtValue* v) const
620 {
621 *v = _GetValue();
622 return true;
623 }
624
625 virtual bool IsEqual(const VtValue& v) const
626 {
627 return (v.IsHolding<T>() && v.UncheckedGet<T>() == _GetValue());
628 }
629
630private:
631 const T& _GetValue() const
632 {
633 return *static_cast<const T*>(value);
634 }
635};
636
637// Specialization of SdAbstractDataConstTypedValue that converts character
638// arrays to std::string.
639template <int N>
640class SdfAbstractDataConstTypedValue<char[N]>
641 : public SdfAbstractDataConstTypedValue<std::string>
642{
643public:
644 typedef char CharArray[N];
645 SdfAbstractDataConstTypedValue(const CharArray* value)
646 : SdfAbstractDataConstTypedValue<std::string>(&_str)
647 , _str(*value)
648 { }
649
650private:
651 std::string _str;
652};
653
660{
661public:
662 SDF_API
664
668 SDF_API
669 virtual bool VisitSpec(const SdfAbstractData& data,
670 const SdfPath& path) = 0;
671
674 SDF_API
675 virtual void Done(const SdfAbstractData& data) = 0;
676};
677
678PXR_NAMESPACE_CLOSE_SCOPE
679
680#endif // PXR_USD_SDF_ABSTRACT_DATA_H
The fully-typed container for a field value in an SdfAbstractData.
Definition: abstractData.h:603
A type-erased container for a const field value in an SdfAbstractData.
Definition: abstractData.h:555
Interface for scene description data storage.
Definition: abstractData.h:57
virtual SDF_API void Set(const SdfPath &path, const TfToken &fieldName, const SdfAbstractDataConstValue &value)=0
Set the value of the given path and fieldName.
virtual SDF_API const std::type_info & QueryTimeSampleTypeid(const SdfPath &path, double time) const
If there is a time sample authored at time, return its value's typeid(), otherwise return typeid(void...
virtual SDF_API bool HasSpec(const SdfPath &path) const =0
Return true if this data has a spec for path.
virtual SDF_API bool Has(const SdfPath &path, const TfToken &fieldName, SdfAbstractDataValue *value) const =0
Returns whether a value exists for the given path and fieldName.
virtual SDF_API bool Has(const SdfPath &path, const TfToken &fieldName, VtValue *value=NULL) const =0
Return whether a value exists for the given path and fieldName.
virtual SDF_API bool IsDetached() const
Returns true if this data object is detached from its serialized data store, false otherwise.
virtual SDF_API bool GetPreviousTimeSampleForPath(const SdfPath &path, double time, double *tPrevious) const
Returns the previous time sample authored just before the querying time.
virtual SDF_API std::type_info const & GetTypeid(const SdfPath &path, const TfToken &fieldName) const
Return the type of the value for fieldName on spec path.
virtual SDF_API bool IsEmpty() const
Returns true if this data object has no specs, false otherwise.
virtual SDF_API bool Equals(const SdfAbstractDataRefPtr &rhs) const
Returns true if this data object contains the same specs and fields as lhs, false otherwise.
virtual SDF_API void CopyFrom(const SdfAbstractDataConstPtr &source)
Copy the data in source into this data object.
virtual SDF_API VtValue Get(const SdfPath &path, const TfToken &fieldName) const =0
Return the value for the given path and fieldName.
virtual SDF_API void CreateSpec(const SdfPath &path, SdfSpecType specType)=0
Create a new spec at path with the given specType.
virtual SDF_API bool HasSpecAndField(const SdfPath &path, const TfToken &fieldName, VtValue *value, SdfSpecType *specType) const
Fill specType (which cannot be nullptr) as if by a call to GetSpecType(path).
virtual SDF_API void EraseSpec(const SdfPath &path)=0
Erase the spec at path and any fields that are on it.
virtual SDF_API void WriteToStream(std::ostream &out) const
Writes the contents of this data object to out.
virtual SDF_API std::vector< TfToken > List(const SdfPath &path) const =0
Return the names of all the fields that are set at path.
virtual SDF_API void Set(const SdfPath &path, const TfToken &fieldName, const VtValue &value)=0
Set the value of the given path and fieldName.
virtual SDF_API bool StreamsData() const =0
Returns true if this data object streams its data to and from its serialized data store on demand.
virtual SDF_API bool HasSpecAndField(const SdfPath &path, const TfToken &fieldName, SdfAbstractDataValue *value, SdfSpecType *specType) const
Fill specType (which cannot be nullptr) as if by a call to GetSpecType(path).
virtual SDF_API void _VisitSpecs(SdfAbstractDataSpecVisitor *visitor) const =0
Visits every spec in this SdfAbstractData object with the given visitor.
SDF_API void VisitSpecs(SdfAbstractDataSpecVisitor *visitor) const
Visits every spec in this SdfAbstractData object with the given visitor.
virtual SDF_API void MoveSpec(const SdfPath &oldPath, const SdfPath &newPath)=0
Move the spec at oldPath to newPath, including all the fields that are on it.
T GetAs(const SdfPath &path, const TfToken &fieldName, const T &defaultValue=T()) const
Return the value for the given path and fieldName.
Definition: abstractData.h:411
virtual SDF_API void Erase(const SdfPath &path, const TfToken &fieldName)=0
Remove the field at path and fieldName, if one exists.
virtual SdfSpecType GetSpecType(const SdfPath &path) const =0
Return the spec type for the spec at path.
Base class for objects used to visit specs in an SdfAbstractData object.
Definition: abstractData.h:660
virtual SDF_API bool VisitSpec(const SdfAbstractData &data, const SdfPath &path)=0
SdfAbstractData::VisitSpecs calls this function for every entry it contains, passing itself as data a...
virtual SDF_API void Done(const SdfAbstractData &data)=0
SdfAbstractData::VisitSpecs will call this after visitation is complete, even if some VisitSpec() ret...
The fully-typed container for a field value in an SdfAbstractData.
Definition: abstractData.h:493
A type-erased container for a field value in an SdfAbstractData.
Definition: abstractData.h:428
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:281
Enable a concrete base class for use with TfRefPtr.
Definition: refBase.h:56
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:124
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:90
T UncheckedRemove()
Make this value empty and return the held T instance.
Definition: value.h:960
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition: value.h:1002
T const & UncheckedGet() const &
Returns a const reference to the held object if the held object is of type T.
Definition: value.h:1046
Standard pointer typedefs.
#define TF_DECLARE_WEAK_AND_REF_PTRS(type)
Define standard weak, ref, and vector pointer types.
Definition: declarePtrs.h:72
STL namespace.
Basic Sdf data types.
SdfSpecType
An enum that specifies the type of an object.
Definition: types.h:71
bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
Safely compare std::type_info structures.
This file defines some macros that are useful for declaring and using static TfTokens.
#define TF_DECLARE_PUBLIC_TOKENS(...)
Macro to define public tokens.
Definition: staticTokens.h:92
A trait to detect instantiations of VtArrayEdit, specialized in arrayEdit.h.
Definition: traits.h:26
TfToken class for efficient string referencing and hashing, plus conversions to and from stl string c...