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.
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...
Basic Sdf data types.
SdfSpecType
An enum that specifies the type of an object.
Definition: types.h:71