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 <string>
23#include <vector>
24#include <type_traits>
25
26PXR_NAMESPACE_OPEN_SCOPE
27
32
33
34#define SDF_DATA_TOKENS \
35 ((TimeSamples, "timeSamples"))
36
37TF_DECLARE_PUBLIC_TOKENS(SdfDataTokens, SDF_API, SDF_DATA_TOKENS);
38
39
57class SdfAbstractData : public TfRefBase, public TfWeakBase
58{
59public:
61 SDF_API
62 virtual ~SdfAbstractData();
63
68 SDF_API
69 virtual void CopyFrom(const SdfAbstractDataConstPtr& source);
70
78 SDF_API
79 virtual bool StreamsData() const = 0;
80
99 SDF_API
100 virtual bool IsDetached() const;
101
106 SDF_API
107 virtual bool IsEmpty() const;
108
114 // XXX: What are the right semantics for this?
115 // Does it matter if the underlying implementation matches?
116 SDF_API
117 virtual bool Equals(const SdfAbstractDataRefPtr &rhs) const;
118
123 SDF_API
124 virtual void WriteToStream(std::ostream& out) const;
125
128
131 SDF_API
132 virtual void CreateSpec(const SdfPath &path,
133 SdfSpecType specType) = 0;
134
136 SDF_API
137 virtual bool HasSpec(const SdfPath &path) const = 0;
138
141 SDF_API
142 virtual void EraseSpec(const SdfPath &path) = 0;
143
146 SDF_API
147 virtual void MoveSpec(const SdfPath &oldPath,
148 const SdfPath &newPath) = 0;
149
152 virtual SdfSpecType GetSpecType(const SdfPath &path) const = 0;
153
158 SDF_API
160
162
165
168 SDF_API
169 virtual bool Has(const SdfPath& path, const TfToken& fieldName,
170 SdfAbstractDataValue* value) const = 0;
171
174 SDF_API
175 virtual bool Has(const SdfPath& path, const TfToken &fieldName,
176 VtValue *value = NULL) const = 0;
177
188 SDF_API
189 virtual bool
190 HasSpecAndField(const SdfPath &path, const TfToken &fieldName,
191 SdfAbstractDataValue *value, SdfSpecType *specType) const;
192
203 SDF_API
204 virtual bool
205 HasSpecAndField(const SdfPath &path, const TfToken &fieldName,
206 VtValue *value, SdfSpecType *specType) const;
207
210 SDF_API
211 virtual VtValue Get(const SdfPath& path,
212 const TfToken& fieldName) const = 0;
213
222 SDF_API
223 virtual std::type_info const &
224 GetTypeid(const SdfPath &path, const TfToken &fieldName) const;
225
230 SDF_API
231 virtual void Set(const SdfPath &path, const TfToken &fieldName,
232 const VtValue &value) = 0;
233
237 SDF_API
238 virtual void Set(const SdfPath &path, const TfToken &fieldName,
239 const SdfAbstractDataConstValue& value) = 0;
240
242 SDF_API
243 virtual void Erase(const SdfPath& path,
244 const TfToken& fieldName) = 0;
245
247 SDF_API
248 virtual std::vector<TfToken> List(const SdfPath& path) const = 0;
249
252 template <class T>
253 inline T GetAs(const SdfPath& path, const TfToken& fieldName,
254 const T& defaultValue = T()) const;
255
257
258
261
262 // Return true and set \p value (if non null) if the field identified by
263 // \p path and \p fieldName is dictionary-valued, and if there is an element
264 // at \p keyPath in that dictionary. Return false otherwise. If
265 // \p keyPath names an entire sub-dictionary, set \p value to that entire
266 // sub-dictionary and return true.
267 SDF_API
268 virtual bool HasDictKey(const SdfPath& path,
269 const TfToken &fieldName,
270 const TfToken &keyPath,
271 SdfAbstractDataValue* value) const;
272 SDF_API
273 virtual bool HasDictKey(const SdfPath& path,
274 const TfToken &fieldName,
275 const TfToken &keyPath,
276 VtValue *value = NULL) const;
277
278 // Same as HasDictKey but return empty VtValue on failure.
279 SDF_API
280 virtual VtValue GetDictValueByKey(const SdfPath& path,
281 const TfToken &fieldName,
282 const TfToken &keyPath) const;
283
284 // Set the element at \p keyPath in the dictionary-valued field identified
285 // by \p path and \p fieldName. If the field itself is not
286 // dictionary-valued, replace the field with a new dictionary and set the
287 // element at \p keyPath in it. If \p value is empty, invoke
288 // EraseDictValueByKey instead.
289 SDF_API
290 virtual void SetDictValueByKey(const SdfPath& path,
291 const TfToken &fieldName,
292 const TfToken &keyPath,
293 const VtValue &value);
294 SDF_API
295 virtual void SetDictValueByKey(const SdfPath& path,
296 const TfToken &fieldName,
297 const TfToken &keyPath,
298 const SdfAbstractDataConstValue& value);
299
300 // If \p path and \p fieldName identify a dictionary-valued field with an
301 // element at \p keyPath, remove that element from the dictionary. If this
302 // leaves the dictionary empty, Erase() the entire field.
303 SDF_API
304 virtual void EraseDictValueByKey(const SdfPath& path,
305 const TfToken &fieldName,
306 const TfToken &keyPath);
307
308 // If \p path, \p fieldName, and \p keyPath identify a (sub) dictionary,
309 // return a vector of the keys in that dictionary, otherwise return an empty
310 // vector.
311 SDF_API
312 virtual std::vector<TfToken> ListDictKeys(const SdfPath& path,
313 const TfToken &fieldName,
314 const TfToken &keyPath) const;
315
316
318
319
329
330 SDF_API
331 virtual std::set<double>
332 ListAllTimeSamples() const = 0;
333
334 SDF_API
335 virtual std::set<double>
336 ListTimeSamplesForPath(const SdfPath& path) const = 0;
337
338 SDF_API
339 virtual bool
340 GetBracketingTimeSamples(double time, double* tLower,
341 double* tUpper) const = 0;
342
343 SDF_API
344 virtual size_t
345 GetNumTimeSamplesForPath(const SdfPath& path) const = 0;
346
347 SDF_API
348 virtual bool
349 GetBracketingTimeSamplesForPath(const SdfPath& path,
350 double time,
351 double* tLower, double* tUpper) const = 0;
352
365 SDF_API
366 virtual bool
367 GetPreviousTimeSampleForPath(const SdfPath& path, double time,
368 double* tPrevious) const;
369
370 SDF_API
371 virtual bool
372 QueryTimeSample(const SdfPath& path, double time,
373 VtValue *optionalValue = NULL) const = 0;
374 SDF_API
375 virtual bool
376 QueryTimeSample(const SdfPath& path, double time,
377 SdfAbstractDataValue *optionalValue) const = 0;
378
386 SDF_API
387 virtual const std::type_info &
388 QueryTimeSampleTypeid(const SdfPath &path, double time) const;
389
390 SDF_API
391 virtual void
392 SetTimeSample(const SdfPath& path, double time,
393 const VtValue & value) = 0;
394
395 SDF_API
396 virtual void
397 EraseTimeSample(const SdfPath& path, double time) = 0;
398
400
401protected:
407 SDF_API
408 virtual void _VisitSpecs(SdfAbstractDataSpecVisitor* visitor) const = 0;
409};
410
411template <class T>
413 const SdfPath& path,
414 const TfToken& field, const T& defaultVal) const
415{
416 VtValue val = Get(path, field);
417 if (val.IsHolding<T>()) {
418 return val.UncheckedGet<T>();
419 }
420 return defaultVal;
421}
422
429{
430public:
431 template <class T>
432 bool StoreValue(T &&v)
433 {
434 // this can be std::remove_cvref_t in c++20.
435 using Type = std::remove_cv_t<std::remove_reference_t<T>>;
436
437 if constexpr (std::is_same_v<Type, VtValue>) {
438 return _StoreVtValue(std::forward<T>(v));
439 }
440
441 isValueBlock = false;
442 isAnimationBlock = false;
443 typeMismatch = false;
444 if constexpr (std::is_same_v<Type, SdfValueBlock>) {
445 isValueBlock = true;
446 return true;
447 } else if constexpr (std::is_same_v<Type, SdfAnimationBlock>) {
448 isAnimationBlock = true;
449 return true;
450 }
451 if (TfSafeTypeCompare(typeid(Type), valueType)) {
452 *static_cast<Type*>(value) = std::forward<T>(v);
453 return true;
454 }
455 typeMismatch = true;
456 return false;
457 }
458
459 void* value;
460 const std::type_info& valueType;
461 bool isValueBlock;
462 bool isAnimationBlock;
463 bool typeMismatch;
464
465protected:
466 SdfAbstractDataValue(void* value_, const std::type_info& valueType_)
467 : value(value_)
468 , valueType(valueType_)
469 , isValueBlock(false)
470 , isAnimationBlock(false)
471 , typeMismatch(false)
472 { }
473
474private:
475 virtual bool _StoreVtValue(const VtValue& value) = 0;
476 virtual bool _StoreVtValue(VtValue &&value) = 0;
477};
478
492template <class T>
494{
495public:
497 : SdfAbstractDataValue(value, typeid(T))
498 { }
499
500private:
501 T const &_Get(const VtValue &v) {
502 return v.UncheckedGet<T>();
503 }
504
505 T _Get(VtValue &&v) {
506 return v.UncheckedRemove<T>();
507 }
508
509 template <class Value>
510 bool _StoreVtValueImpl(Value &&v) {
511 typeMismatch = false;
512 isValueBlock = false;
513 isAnimationBlock = false;
514 if (ARCH_LIKELY(std::forward<Value>(v).template IsHolding<T>())) {
515 *static_cast<T*>(value) = _Get(std::forward<Value>(v));
516 if constexpr (std::is_same_v<T, SdfValueBlock>) {
517 isValueBlock = true;
518 } else if constexpr (std::is_same_v<T, SdfAnimationBlock>) {
519 isAnimationBlock = true;
520 }
521 return true;
522 }
523
524 if (std::forward<Value>(v).template IsHolding<SdfValueBlock>()) {
525 isValueBlock = true;
526 return true;
527 }
528 else if (std::forward<Value>(v).template IsHolding<SdfAnimationBlock>())
529 {
530 isAnimationBlock = true;
531 return true;
532 }
533
534 typeMismatch = true;
535
536 return false;
537 }
538
539 virtual bool
540 _StoreVtValue(const VtValue& v) override {
541 return _StoreVtValueImpl(v);
542 }
543
544 virtual bool
545 _StoreVtValue(VtValue &&v) override {
546 return _StoreVtValueImpl(v);
547 }
548};
549
556{
557public:
558 virtual bool GetValue(VtValue* value) const = 0;
559
560 template <class T> bool GetValue(T* v) const
561 {
562 if (TfSafeTypeCompare(typeid(T), valueType)) {
563 *v = *static_cast<const T*>(value);
564 return true;
565 }
566 return false;
567 }
568
569 virtual bool IsEqual(const VtValue& value) const = 0;
570
571 const void* value;
572 const std::type_info& valueType;
573 const bool isArrayEdit;
574 const std::type_info& elementValueType; // void unless isArrayEdit
575
576protected:
577 SdfAbstractDataConstValue(const void* value_,
578 const std::type_info& valueType_,
579 const bool isArrayEdit_,
580 const std::type_info& elementValueType_)
581 : value(value_)
582 , valueType(valueType_)
583 , isArrayEdit(isArrayEdit_)
584 , elementValueType(elementValueType_)
585 {
586 }
587};
588
602template <class T>
604{
605public:
606 static std::type_info const &_GetElementType() {
607 if constexpr (VtIsArrayEdit<T>::value) {
608 return typeid(typename T::ElementType);
609 }
610 else {
611 return typeid(void);
612 }
613 }
614
615 SdfAbstractDataConstTypedValue(const T* value)
617 value, typeid(T), VtIsArrayEdit<T>::value, this->_GetElementType())
618 {}
619
620 virtual bool GetValue(VtValue* v) const
621 {
622 *v = _GetValue();
623 return true;
624 }
625
626 virtual bool IsEqual(const VtValue& v) const
627 {
628 return (v.IsHolding<T>() && v.UncheckedGet<T>() == _GetValue());
629 }
630
631private:
632 const T& _GetValue() const
633 {
634 return *static_cast<const T*>(value);
635 }
636};
637
638// Specialization of SdAbstractDataConstTypedValue that converts character
639// arrays to std::string.
640template <int N>
641class SdfAbstractDataConstTypedValue<char[N]>
642 : public SdfAbstractDataConstTypedValue<std::string>
643{
644public:
645 typedef char CharArray[N];
646 SdfAbstractDataConstTypedValue(const CharArray* value)
647 : SdfAbstractDataConstTypedValue<std::string>(&_str)
648 , _str(*value)
649 { }
650
651private:
652 std::string _str;
653};
654
661{
662public:
663 SDF_API
665
669 SDF_API
670 virtual bool VisitSpec(const SdfAbstractData& data,
671 const SdfPath& path) = 0;
672
675 SDF_API
676 virtual void Done(const SdfAbstractData& data) = 0;
677};
678
679PXR_NAMESPACE_CLOSE_SCOPE
680
681#endif // PXR_USD_SDF_ABSTRACT_DATA_H
The fully-typed container for a field value in an SdfAbstractData.
A type-erased container for a const field value in an SdfAbstractData.
Interface for scene description data storage.
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.
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.
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.
A type-erased container for a field value in an SdfAbstractData.
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:81
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:1019
bool IsHolding() const
Return true if this value is holding an object of type T, false otherwise.
Definition value.h:1061
T const & UncheckedGet() const &
Returns a const reference to the held object if the held object is of type T.
Definition value.h:1105
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.
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:73