HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
data.h
Go to the documentation of this file.
1 //
2 // Copyright 2023 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 
25 #ifndef PXR_BASE_TS_DATA_H
26 #define PXR_BASE_TS_DATA_H
27 
28 #include "pxr/pxr.h"
29 #include "pxr/base/ts/api.h"
30 #include "pxr/base/arch/demangle.h"
31 #include "pxr/base/gf/math.h"
32 #include "pxr/base/tf/diagnostic.h"
33 #include "pxr/base/ts/evalCache.h"
34 #include "pxr/base/ts/mathUtils.h"
35 #include "pxr/base/ts/types.h"
36 #include "pxr/base/vt/value.h"
37 
38 #include <string>
39 #include <math.h>
40 
42 
44 
45 /// \class Ts_Data
46 /// \brief Holds the data for an TsKeyFrame.
47 ///
48 /// \c Ts_Data is an interface for holding \c TsKeyFrame data.
49 ///
50 class Ts_Data {
51 public:
52  virtual ~Ts_Data() = default;
53  virtual void CloneInto(Ts_PolymorphicDataHolder *holder) const = 0;
54 
55  // Create and return an EvalCache that represents the spline segment from
56  // this keyframe to kf2.
57  virtual std::shared_ptr<Ts_UntypedEvalCache> CreateEvalCache(
58  Ts_Data const* kf2) const = 0;
59 
60  // Evaluate between this keyframe data and \p kf2 at \p time. This is
61  // useful for callers that do not otherwise want or need to create/retain an
62  // eval cache.
63  virtual VtValue
64  EvalUncached(Ts_Data const *kf2, TsTime time) const = 0;
65 
66  // Evaluate the derivative between this keyframe data and \p kf2 at \p time.
67  // This is useful for callers that do not otherwise want or need to
68  // create/retain an eval cache.
69  virtual VtValue
70  EvalDerivativeUncached(Ts_Data const *kf2, TsTime time) const = 0;
71 
72  virtual bool operator==(const Ts_Data &) const = 0;
73 
74  // Time
75  inline TsTime GetTime() const {
76  return _time;
77  }
78  inline void SetTime(TsTime newTime) {
79  _time = newTime;
80  }
81 
82  // Knot type
83  virtual TsKnotType GetKnotType() const = 0;
84  virtual void SetKnotType( TsKnotType knotType ) = 0;
85  virtual bool CanSetKnotType( TsKnotType knotType,
86  std::string *reason ) const = 0;
87 
88  // Values
89  virtual VtValue GetValue() const = 0;
90  virtual void SetValue( VtValue val ) = 0;
91  virtual VtValue GetValueDerivative() const = 0;
92  virtual bool GetIsDualValued() const = 0;
93  virtual void SetIsDualValued( bool isDual ) = 0;
94  virtual VtValue GetLeftValue() const = 0;
95  virtual VtValue GetLeftValueDerivative() const = 0;
96  virtual void SetLeftValue( VtValue ) = 0;
97  virtual VtValue GetZero() const = 0;
98  virtual bool ValueCanBeInterpolated() const = 0;
99  virtual bool ValueCanBeExtrapolated() const = 0;
100 
101  // Extrapolation.
102  // Note these methods don't actually use any data from this object
103  // and only depend on the spline type and the given parameters.
104  //
105  virtual VtValue GetSlope( const Ts_Data& ) const = 0;
106  virtual VtValue Extrapolate( const VtValue& value, TsTime dt,
107  const VtValue& slope) const = 0;
108 
109  // Tangents
110 
111  /// True if the data type supports tangents, and the knot type is one that
112  /// shows tangents in the UI. True only for Bezier. Linear and held knots
113  /// return false, even though their tangents can be set.
114  virtual bool HasTangents() const = 0;
115 
116  /// If true, implies the tangents can be written. For historical reasons,
117  /// linear and held knots support tangents. This means that these types
118  /// return true for ValueTypeSupportsTangents() but false for HasTangents().
119  // XXX: pixar-ism?
120  virtual bool ValueTypeSupportsTangents() const = 0;
121 
122  virtual VtValue GetLeftTangentSlope() const = 0;
123  virtual VtValue GetRightTangentSlope() const = 0;
124  virtual TsTime GetLeftTangentLength() const = 0;
125  virtual TsTime GetRightTangentLength() const = 0;
126  virtual void SetLeftTangentSlope( VtValue ) = 0;
127  virtual void SetRightTangentSlope( VtValue ) = 0;
128  virtual void SetLeftTangentLength( TsTime ) = 0;
129  virtual void SetRightTangentLength( TsTime ) = 0;
130  virtual bool GetTangentSymmetryBroken() const = 0;
131  virtual void SetTangentSymmetryBroken( bool broken ) = 0;
132  virtual void ResetTangentSymmetryBroken() = 0;
133 
134 private:
135 
136  TsTime _time = 0.0;
137 };
138 
139 // Typed keyframe data class.
140 template <typename T>
141 class Ts_TypedData : public Ts_Data {
142 public:
143  typedef T ValueType;
145 
146  Ts_TypedData(const T&);
147  Ts_TypedData(
148  const TsTime &t,
149  bool isDual,
150  const T& leftValue,
151  const T& rightValue,
152  const T& leftTangentSlope,
153  const T& rightTangentSlope);
154 
155  ~Ts_TypedData() override = default;
156 
157  void CloneInto(Ts_PolymorphicDataHolder *holder) const override;
158 
159  // Create a untyped eval cache for the segment defined by ourself and the
160  // given keyframe.
161  std::shared_ptr<Ts_UntypedEvalCache> CreateEvalCache(
162  Ts_Data const* kf2) const override;
163 
164  // Evaluate between this keyframe data and \p kf2 at \p time. This is
165  // useful for callers that do not otherwise want or need to create/retain an
166  // eval cache.
168  Ts_Data const *kf2, TsTime time) const override;
169 
170  // Evaluate the derivative between this keyframe data and \p kf2 at \p time.
171  // This is useful for callers that do not otherwise want or need to
172  // create/retain an eval cache.
174  Ts_Data const *kf2, TsTime time) const override;
175 
176  // Create a typed eval cache for the segment defined by ourself and the
177  // given keyframe.
178  std::shared_ptr<Ts_EvalCache<T,
180  Ts_Data const* kf2) const;
181 
182  bool operator==(const Ts_Data &) const override;
183 
184  // Knot type
185  TsKnotType GetKnotType() const override;
186  void SetKnotType( TsKnotType knotType ) override;
187  bool CanSetKnotType(
188  TsKnotType knotType, std::string *reason ) const override;
189 
190  // Values
191  VtValue GetValue() const override;
192  void SetValue( VtValue ) override;
193  VtValue GetValueDerivative() const override;
194  bool GetIsDualValued() const override;
195  void SetIsDualValued( bool isDual ) override;
196  VtValue GetLeftValue() const override;
197  VtValue GetLeftValueDerivative() const override;
198  void SetLeftValue( VtValue ) override;
199  VtValue GetZero() const override;
200  bool ValueCanBeInterpolated() const override;
201  bool ValueCanBeExtrapolated() const override;
202 
203  // Tangents
204  bool HasTangents() const override;
205  bool ValueTypeSupportsTangents() const override;
206  VtValue GetLeftTangentSlope() const override;
207  VtValue GetRightTangentSlope() const override;
208  TsTime GetLeftTangentLength() const override;
209  TsTime GetRightTangentLength() const override;
210  void SetLeftTangentSlope( VtValue ) override;
211  void SetRightTangentSlope( VtValue ) override;
212  void SetLeftTangentLength( TsTime ) override;
213  void SetRightTangentLength( TsTime ) override;
214  bool GetTangentSymmetryBroken() const override;
215  void SetTangentSymmetryBroken( bool broken ) override;
216  void ResetTangentSymmetryBroken() override;
217 
218 public:
219 
220  // Slope computation methods.
221 
222  VtValue GetSlope(const Ts_Data &right) const override
223  {
224  if constexpr (TsTraits<T>::extrapolatable)
225  {
226  const TsTime dx = right.GetTime() - GetTime();
227  const TsTime dxInv = 1.0 / dx;
228 
229  const T y1 = GetValue().template Get<T>();
230  const T y2 = right.GetLeftValue().template Get<T>();
231  const T dy = y2 - y1;
232 
233  // This is effectively dy/dx, but some types lack operator/, so
234  // phrase in terms of operator*.
235  const T slope = dy * dxInv;
236  return VtValue(slope);
237  }
238  else
239  {
240  return VtValue(TsTraits<T>::zero);
241  }
242  }
243 
245  const VtValue &value, TsTime dt, const VtValue &slope) const override
246  {
247  if constexpr (TsTraits<T>::extrapolatable)
248  {
249  const T v = value.template Get<T>();
250  const T s = slope.template Get<T>();
251  const T result = v + dt * s;
252  return VtValue(result);
253  }
254  else
255  {
256  return value;
257  }
258  }
259 
260 private:
261 
262  // Convenience accessors for the data stored inside the _Values struct.
263 
264  T const& _GetRightValue() const {
265  return _values.Get()._rhv;
266  }
267  T const& _GetLeftValue() const {
268  return _values.Get()._lhv;
269  }
270  T const& _GetRightTangentSlope() const {
271  return _values.Get()._rightTangentSlope;
272  }
273  T const& _GetLeftTangentSlope() const {
274  return _values.Get()._leftTangentSlope;
275  }
276 
277  void _SetRightValue(T const& rhv) {
278  _values.GetMutable()._rhv = rhv;
279  }
280  void _SetLeftValue(T const& lhv) {
281  _values.GetMutable()._lhv = lhv;
282  }
283  void _SetRightTangentSlope(T const& rightTangentSlope) {
284  _values.GetMutable()._rightTangentSlope = rightTangentSlope;
285  }
286  void _SetLeftTangentSlope(T const& leftTangentSlope) {
287  _values.GetMutable()._leftTangentSlope = leftTangentSlope;
288  }
289 
290 private:
291  friend class TsKeyFrame;
292  friend class Ts_UntypedEvalCache;
293  friend class Ts_EvalQuaternionCache<T>;
294  friend class Ts_EvalCache<T, TsTraits<T>::interpolatable>;
295 
296  // A struct containing all the member variables that depend on type T.
297  template <class V>
298  struct _Values {
299 
300  explicit _Values(
301  V const& lhv=TsTraits<T>::zero,
302  V const& rhv=TsTraits<T>::zero,
303  V const& leftTangentSlope=TsTraits<T>::zero,
304  V const& rightTangentSlope=TsTraits<T>::zero) :
305  _lhv(lhv),
306  _rhv(rhv),
307  _leftTangentSlope(leftTangentSlope),
308  _rightTangentSlope(rightTangentSlope)
309  {
310  }
311 
312  // Left and right hand values.
313  // Single-value knots only use _rhv; dual-value knots use both.
314  V _lhv, _rhv;
315 
316  // Tangent slope, or derivative, in units per frame.
317  V _leftTangentSlope, _rightTangentSlope;
318  };
319 
320  // A wrapper for _Values with small-object optimization. The _ValuesHolder
321  // object is always the same size. If T is sizeof(double) or smaller, the
322  // _Values struct is held in member data. If T is larger than double, the
323  // struct is heap-allocated.
324  class _ValuesHolder
325  {
326  private:
327  static constexpr size_t _size = sizeof(_Values<double>);
328  static constexpr bool _isSmall = (sizeof(_Values<T>) <= _size);
329 
330  // Storage implementation for small types.
331  struct _LocalStorage
332  {
333  _LocalStorage(_Values<T> &&values)
334  : _data(std::move(values)) {}
335 
336  const _Values<T>& Get() const { return _data; }
337  _Values<T>& GetMutable() { return _data; }
338 
339  _Values<T> _data;
340  };
341 
342  // Storage implementation for large types.
343  struct _HeapStorage
344  {
345  _HeapStorage(_Values<T> &&values)
346  : _data(new _Values<T>(std::move(values))) {}
347 
348  // Copy constructor: deep-copies data.
349  _HeapStorage(const _HeapStorage &other)
350  : _data(new _Values<T>(other.Get())) {}
351 
352  const _Values<T>& Get() const { return *_data; }
353  _Values<T>& GetMutable() { return *_data; }
354 
355  std::unique_ptr<_Values<T>> _data;
356  };
357 
358  // Select storage implementation.
359  using _Storage =
360  typename std::conditional<
361  _isSmall, _LocalStorage, _HeapStorage>::type;
362 
363  public:
364  // Construct from _Values rvalue.
365  explicit _ValuesHolder(_Values<T> &&values)
366  : _storage(std::move(values)) {}
367 
368  // Copy constructor.
369  _ValuesHolder(const _ValuesHolder &other)
370  : _storage(other._storage) {}
371 
372  // Destructor: explicitly call _Storage destructor.
373  ~_ValuesHolder() { _storage.~_Storage(); }
374 
375  // Accessors.
376  const _Values<T>& Get() const { return _storage.Get(); }
377  _Values<T>& GetMutable() { return _storage.GetMutable(); }
378 
379  private:
380  union
381  {
382  _Storage _storage;
383  char _padding[_size];
384  };
385  };
386 
387  // Sanity check: every instantiation of _ValuesHolder is the same size.
388  static_assert(
389  sizeof(_ValuesHolder) == sizeof(_Values<double>),
390  "_ValuesHolder does not have expected type-independent size");
391 
392 private:
393  _ValuesHolder _values;
394 
395  // Tangent length, in frames.
396  TsTime _leftTangentLength, _rightTangentLength;
397 
398  TsKnotType _knotType;
399  bool _isDual;
400  bool _tangentSymmetryBroken;
401 };
402 
403 // A wrapper for Ts_TypedData<T> for arbitrary T, exposed as a pointer to the
404 // non-templated base class Ts_Data, but allocated in member data rather than
405 // on the heap.
407 {
408 public:
409  // Wrapper for held-knot-at-time-zero constructor.
410  template <typename T>
411  void New(const T &val)
412  {
413  new (&_storage) Ts_TypedData<T>(val);
414  }
415 
416  // Wrapper for general constructor.
417  template <typename T>
418  void New(
419  const TsTime &t,
420  bool isDual,
421  const T &leftValue,
422  const T &rightValue,
423  const T &leftTangentSlope,
424  const T &rightTangentSlope)
425  {
426  new (&_storage) Ts_TypedData<T>(
427  t, isDual, leftValue, rightValue,
428  leftTangentSlope, rightTangentSlope);
429  }
430 
431  // Copy constructor.
432  template <typename T>
433  void New(const Ts_TypedData<T> &other)
434  {
435  new (&_storage) Ts_TypedData<T>(other);
436  }
437 
438  // Explicit destructor. Clients call this method from their destructors,
439  // and prior to calling New to replace an existing knot.
440  void Destroy()
441  {
442  reinterpret_cast<Ts_Data*>(&_storage)->~Ts_Data();
443  }
444 
445  // Const accessor.
446  const Ts_Data* Get() const
447  {
448  return reinterpret_cast<const Ts_Data*>(&_storage);
449  }
450 
451  // Non-const accessor.
453  {
454  return reinterpret_cast<Ts_Data*>(&_storage);
455  }
456 
457 private:
458  // Our buffer is sized for Ts_TypedData<T>. This is always the same size
459  // regardless of T; see Ts_TypedData::_ValuesHolder.
460  using _Storage =
461  typename std::aligned_storage<
462  sizeof(Ts_TypedData<double>), sizeof(void*)>::type;
463 
464 private:
465  _Storage _storage;
466 };
467 
468 ////////////////////////////////////////////////////////////////////////
469 // Ts_TypedData
470 
471 template <typename T>
473  _values(_Values<T>(value,value)),
474  _leftTangentLength(0.0),
475  _rightTangentLength(0.0),
476  _knotType(TsKnotHeld),
477  _isDual(false),
478  _tangentSymmetryBroken(false)
479 {
480 }
481 
482 template <typename T>
484  const TsTime &t,
485  bool isDual,
486  const T& leftValue,
487  const T& rightValue,
488  const T& leftTangentSlope,
489  const T& rightTangentSlope) :
490  _values(_Values<T>(leftValue,rightValue,
491  leftTangentSlope,rightTangentSlope)),
492  _leftTangentLength(0.0),
493  _rightTangentLength(0.0),
494  _knotType(TsKnotHeld),
495  _isDual(isDual),
496  _tangentSymmetryBroken(false)
497 {
498  SetTime(t);
499 }
500 
501 template <typename T>
502 void
504 {
505  holder->New(*this);
506 }
507 
508 template <typename T>
509 std::shared_ptr<Ts_UntypedEvalCache>
511 {
512  // Cast kf2 to the correct typed data. This is a private class, and we
513  // assume kf2 is from the same spline, so it will have the same value type.
514  Ts_TypedData<T> const* typedKf2 =
515  static_cast<Ts_TypedData<T> const*>(kf2);
516 
517  // Construct and return a new EvalCache of the appropriate type.
518  return std::make_shared<
520 }
521 
522 template <typename T>
523 std::shared_ptr<Ts_EvalCache<T, TsTraits<T>::interpolatable> >
525 {
526  Ts_TypedData<T> const* typedKf2 =
527  static_cast<Ts_TypedData<T> const*>(kf2);
528 
529  return std::shared_ptr<Ts_EvalCache<T, TsTraits<T>::interpolatable> >(
530  new Ts_EvalCache<T, TsTraits<T>::interpolatable>(this, typedKf2));
531 }
532 
533 template <typename T>
534 VtValue
536 ::EvalUncached(Ts_Data const *kf2, TsTime time) const
537 {
538  // Cast kf2 to the correct typed data. This is a private class, and we
539  // assume kf2 is from the same spline, so it will have the same value type.
540  Ts_TypedData<T> const* typedKf2 =
541  static_cast<Ts_TypedData<T> const*>(kf2);
542 
543  return Ts_EvalCache<T, TsTraits<T>::interpolatable>(this, typedKf2)
544  .Eval(time);
545 }
546 
547 template <typename T>
548 VtValue
551 {
552  // Cast kf2 to the correct typed data. This is a private class, and we
553  // assume kf2 is from the same spline, so it will have the same value type.
554  Ts_TypedData<T> const* typedKf2 =
555  static_cast<Ts_TypedData<T> const*>(kf2);
556 
557  return Ts_EvalCache<T, TsTraits<T>::interpolatable>(this, typedKf2)
558  .EvalDerivative(time);
559 }
560 
561 template <typename T>
562 bool
564 {
566  return
567  GetKnotType() == rhs.GetKnotType() &&
568  GetTime() == rhs.GetTime() &&
569  GetValue() == rhs.GetValue() &&
570  GetIsDualValued() == rhs.GetIsDualValued() &&
571  (!GetIsDualValued() || (GetLeftValue() == rhs.GetLeftValue()));
572  }
573 
574  return
575  GetTime() == rhs.GetTime() &&
576  GetValue() == rhs.GetValue() &&
577  GetKnotType() == rhs.GetKnotType() &&
578  GetIsDualValued() == rhs.GetIsDualValued() &&
579  (!GetIsDualValued() || (GetLeftValue() == rhs.GetLeftValue())) &&
580  GetLeftTangentLength() == rhs.GetLeftTangentLength() &&
581  GetRightTangentLength() == rhs.GetRightTangentLength() &&
582  GetLeftTangentSlope() == rhs.GetLeftTangentSlope() &&
583  GetRightTangentSlope() == rhs.GetRightTangentSlope() &&
584  GetTangentSymmetryBroken() == rhs.GetTangentSymmetryBroken();
585 }
586 
587 template <typename T>
590 {
591  return _knotType;
592 }
593 
594 template <typename T>
595 void
597 {
598  std::string reason;
599 
600  if (!CanSetKnotType(knotType, &reason)) {
601  TF_CODING_ERROR(reason);
602  return;
603  }
604 
605  _knotType = knotType;
606 }
607 
608 template <typename T>
609 bool
611  std::string *reason ) const
612 {
613  // Non-interpolatable values can only have held key frames.
614  if (!ValueCanBeInterpolated() && knotType != TsKnotHeld) {
615  if (reason) {
616  *reason = "Value cannot be interpolated; only 'held' " \
617  "key frames are allowed.";
618  }
619  return false;
620  }
621 
622  // Only value types that support tangents can have bezier key frames.
623  if (!TsTraits<T>::supportsTangents && knotType == TsKnotBezier) {
624  if (reason) {
625  *reason = TfStringPrintf(
626  "Cannot set keyframe type %s; values of type '%s' "
627  "do not support tangents.",
628  TfEnum::GetDisplayName(knotType).c_str(),
629  ArchGetDemangled(typeid(ValueType)).c_str());
630  }
631  return false;
632  }
633 
634  return true;
635 }
636 
637 template <typename T>
638 VtValue
640 {
641  return VtValue(_GetRightValue());
642 }
643 
644 template <typename T>
645 VtValue
647 {
649  return GetRightTangentSlope();
650  } else {
651  return VtValue(TsTraits<T>::zero);
652  }
653 }
654 
655 template <typename T>
656 void
658 {
659  VtValue v = val.Cast<T>();
660  if (!v.IsEmpty()) {
661  _SetRightValue(v.Get<T>());
662  if (!ValueCanBeInterpolated())
663  SetKnotType(TsKnotHeld);
664  } else {
665  TF_CODING_ERROR("cannot convert type '%s' to '%s' to assign "
666  "to keyframe", val.GetTypeName().c_str(),
667  ArchGetDemangled(typeid(ValueType)).c_str());
668  }
669 }
670 
671 template <typename T>
672 bool
674 {
675  return _isDual;
676 }
677 
678 template <typename T>
679 void
681 {
682  if (isDual && !TsTraits<T>::interpolatable) {
683  TF_CODING_ERROR("keyframes of type '%s' cannot be dual-valued",
684  ArchGetDemangled(typeid(ValueType)).c_str());
685  return;
686  }
687 
688  _isDual = isDual;
689 
690  if (_isDual) {
691  // The data stored for the left value was meaningless.
692  // Mirror the right-side value to the left.
693  SetLeftValue(GetValue());
694  }
695 }
696 
697 template <typename T>
698 VtValue
700 {
701  return VtValue(_isDual ? _GetLeftValue() : _GetRightValue());
702 }
703 
704 template <typename T>
705 VtValue
707 {
709  return GetLeftTangentSlope();
710  } else {
711  return VtValue(TsTraits<T>::zero);
712  }
713 }
714 
715 template <typename T>
716 void
718 {
720  TF_CODING_ERROR("keyframes of type '%s' cannot be dual-valued",
721  ArchGetDemangled(typeid(ValueType)).c_str() );
722  return;
723  }
724  if (!GetIsDualValued()) {
725  TF_CODING_ERROR("keyframe is not dual-valued; cannot set left value");
726  return;
727  }
728 
729  VtValue v = val.Cast<T>();
730  if (!v.IsEmpty()) {
731  _SetLeftValue(v.Get<T>());
732  if (!ValueCanBeInterpolated())
733  SetKnotType(TsKnotHeld);
734  } else {
735  TF_CODING_ERROR("cannot convert type '%s' to '%s' to assign to "
736  "keyframe", val.GetTypeName().c_str(),
737  ArchGetDemangled(typeid(ValueType)).c_str());
738  }
739 }
740 
741 template <typename T>
742 VtValue
744 {
745  return VtValue(TsTraits<T>::zero);
746 }
747 
748 template <typename T>
749 bool
751 {
753 }
754 
755 template <typename T>
756 bool
758 {
760 }
761 
762 template <typename T>
763 bool
765 {
766  return TsTraits<T>::supportsTangents && _knotType == TsKnotBezier;
767 }
768 
769 template <typename T>
770 bool
772 {
773  // Oddly, linear and held knots have settable tangents. Animators use
774  // this when switching Beziers to Held and then back again.
776 }
777 
778 template <typename T>
779 VtValue
781 {
783  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
784  ArchGetDemangled(typeid(ValueType)).c_str());
785  return VtValue();
786  }
787 
788  return VtValue(_GetLeftTangentSlope());
789 }
790 
791 template <typename T>
792 VtValue
794 {
796  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
797  ArchGetDemangled(typeid(ValueType)).c_str() );
798  return VtValue();
799  }
800 
801  return VtValue(_GetRightTangentSlope());
802 }
803 
804 template <typename T>
805 TsTime
807 {
809  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
810  ArchGetDemangled(typeid(ValueType)).c_str());
811  return 0;
812  }
813 
814  return _leftTangentLength;
815 }
816 
817 template <typename T>
818 TsTime
820 {
822  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
823  ArchGetDemangled(typeid(ValueType)).c_str());
824  return 0;
825  }
826 
827  return _rightTangentLength;
828 }
829 
830 template <typename T>
831 void
833 {
835  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
836  ArchGetDemangled(typeid(ValueType)).c_str());
837  return;
838  }
839 
840  VtValue v = val.Cast<T>();
841  if (!v.IsEmpty()) {
842  _SetLeftTangentSlope(val.Get<T>());
843  } else {
844  TF_CODING_ERROR("cannot convert type '%s' to '%s' to assign to "
845  "keyframe", val.GetTypeName().c_str(),
846  ArchGetDemangled(typeid(ValueType)).c_str());
847  }
848 }
849 
850 template <typename T>
851 void
853 {
855  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
856  ArchGetDemangled(typeid(ValueType)).c_str());
857  return;
858  }
859 
860  VtValue v = val.Cast<T>();
861  if (!v.IsEmpty()) {
862  _SetRightTangentSlope(val.Get<T>());
863  } else {
864  TF_CODING_ERROR("cannot convert type '%s' to '%s' to assign to keyframe"
865  , val.GetTypeName().c_str(),
866  ArchGetDemangled(typeid(ValueType)).c_str());
867  }
868 }
869 
870 #define TS_LENGTH_EPSILON 1e-6
871 
872 template <typename T>
873 void
875 {
877  TF_CODING_ERROR( "keyframes of type '%s' do not have tangents",
878  ArchGetDemangled(typeid(ValueType)).c_str());
879  return;
880  }
881  if (std::isnan(newLen)) {
882  TF_CODING_ERROR("Cannot set tangent length to NaN; ignoring");
883  return;
884  }
885  if (std::isinf(newLen)) {
886  TF_CODING_ERROR("Cannot set tangent length to inf; ignoring");
887  return;
888  }
889  if (newLen < 0.0) {
890  if (-newLen < TS_LENGTH_EPSILON) {
891  newLen = 0.0;
892  } else {
894  "Cannot set tangent length to negative value; ignoring");
895  return;
896  }
897  }
898 
899  _leftTangentLength = newLen;
900 }
901 
902 template <typename T>
903 void
905 {
907  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
908  ArchGetDemangled(typeid(ValueType)).c_str());
909  return;
910  }
911  if (std::isnan(newLen)) {
912  TF_CODING_ERROR("Cannot set tangent length to NaN; ignoring");
913  return;
914  }
915  if (std::isinf(newLen)) {
916  TF_CODING_ERROR("Cannot set tangent length to inf; ignoring");
917  return;
918  }
919  if (newLen < 0.0) {
920  if (-newLen < TS_LENGTH_EPSILON) {
921  newLen = 0.0;
922  } else {
924  "Cannot set tangent length to negative value; ignoring");
925  return;
926  }
927  }
928 
929  _rightTangentLength = newLen;
930 }
931 
932 template <typename T>
933 bool
935 {
937  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
938  ArchGetDemangled(typeid(ValueType)).c_str());
939  return false;
940  }
941 
942  return _tangentSymmetryBroken;
943 }
944 
945 template <typename T>
946 void
948 {
950  TF_CODING_ERROR("keyframes of type '%s' do not have tangents",
951  ArchGetDemangled(typeid(ValueType)).c_str());
952  return;
953  }
954 
955  if (_tangentSymmetryBroken != broken) {
956  _tangentSymmetryBroken = broken;
957  if (!_tangentSymmetryBroken) {
958  _SetLeftTangentSlope(_GetRightTangentSlope());
959  }
960  }
961 }
962 
963 template <typename T>
964 void
966 {
967  // do nothing -- no tangents
968 }
969 
970 // Declare specializations for float and double.
971 // Definitions are in Data.cpp.
972 template <>
973 TS_API void
975 
976 template <>
977 TS_API void
979 
980 template <>
981 TS_API bool
983 
984 template <>
985 TS_API bool
987 
989 
990 #endif
virtual bool GetIsDualValued() const =0
TF_API std::string TfStringPrintf(const char *fmt,...)
VtValue EvalUncached(Ts_Data const *kf2, TsTime time) const override
Definition: data.h:536
virtual VtValue GetValueDerivative() const =0
bool HasTangents() const override
Definition: data.h:764
virtual VtValue GetSlope(const Ts_Data &) const =0
bool operator==(const Ts_Data &) const override
Definition: data.h:563
virtual void CloneInto(Ts_PolymorphicDataHolder *holder) const =0
void SetTangentSymmetryBroken(bool broken) override
Definition: data.h:947
virtual void SetIsDualValued(bool isDual)=0
virtual void SetKnotType(TsKnotType knotType)=0
virtual void SetRightTangentSlope(VtValue)=0
virtual VtValue Extrapolate(const VtValue &value, TsTime dt, const VtValue &slope) const =0
void CloneInto(Ts_PolymorphicDataHolder *holder) const override
Definition: data.h:503
GT_API const UT_StringHolder time
const GLdouble * v
Definition: glcorearb.h:837
~Ts_TypedData() override=default
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLfloat * value
Definition: glcorearb.h:824
A held-value knot; tangents will be ignored.
Definition: types.h:65
void SetLeftTangentLength(TsTime) override
Definition: data.h:874
GLdouble right
Definition: glad.h:2817
void New(const T &val)
Definition: data.h:411
#define TF_CODING_ERROR
virtual void ResetTangentSymmetryBroken()=0
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
virtual bool HasTangents() const =0
std::shared_ptr< Ts_EvalCache< T, TsTraits< T >::interpolatable > > CreateTypedEvalCache(Ts_Data const *kf2) const
Definition: data.h:524
void SetRightTangentSlope(VtValue) override
Definition: data.h:852
VtValue GetSlope(const Ts_Data &right) const override
Definition: data.h:222
void SetTime(TsTime newTime)
Definition: data.h:78
A Bezier knot.
Definition: types.h:67
GLdouble s
Definition: glad.h:3009
Ts_Data * GetMutable()
Definition: data.h:452
bool ValueCanBeInterpolated() const override
Definition: data.h:750
virtual VtValue GetLeftTangentSlope() const =0
bool CanSetKnotType(TsKnotType knotType, std::string *reason) const override
Definition: data.h:610
virtual TsTime GetLeftTangentLength() const =0
virtual std::shared_ptr< Ts_UntypedEvalCache > CreateEvalCache(Ts_Data const *kf2) const =0
**But if you need a result
Definition: thread.h:613
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1300
Ts_TypedData(const T &)
Definition: data.h:472
const Ts_Data * Get() const
Definition: data.h:446
virtual VtValue GetRightTangentSlope() const =0
virtual void SetRightTangentLength(TsTime)=0
bool ValueCanBeExtrapolated() const override
Definition: data.h:757
virtual bool GetTangentSymmetryBroken() const =0
#define TS_LENGTH_EPSILON
Definition: data.h:870
T const & Get() const &
Definition: value.h:1137
VtValue GetRightTangentSlope() const override
Definition: data.h:793
virtual void SetTangentSymmetryBroken(bool broken)=0
VtValue GetLeftValueDerivative() const override
Definition: data.h:706
virtual VtValue GetValue() const =0
TsTime GetRightTangentLength() const override
Definition: data.h:819
VtValue Extrapolate(const VtValue &value, TsTime dt, const VtValue &slope) const override
Definition: data.h:244
virtual void SetLeftTangentSlope(VtValue)=0
void New(const Ts_TypedData< T > &other)
Definition: data.h:433
TsKnotType
Keyframe knot types.
Definition: types.h:64
void New(const TsTime &t, bool isDual, const T &leftValue, const T &rightValue, const T &leftTangentSlope, const T &rightTangentSlope)
Definition: data.h:418
TsTime GetLeftTangentLength() const override
Definition: data.h:806
void SetKnotType(TsKnotType knotType) override
Definition: data.h:596
GLdouble y1
Definition: glad.h:2349
virtual VtValue GetZero() const =0
virtual void SetLeftTangentLength(TsTime)=0
SIM_API const UT_StringHolder broken
void SetIsDualValued(bool isDual) override
Definition: data.h:680
Specifies the value of an TsSpline object at a particular point in time.
Definition: keyFrame.h:66
VtValue GetZero() const override
Definition: data.h:743
virtual void SetValue(VtValue val)=0
virtual bool CanSetKnotType(TsKnotType knotType, std::string *reason) const =0
VtValue GetValue() const override
Definition: data.h:639
void SetLeftValue(VtValue) override
Definition: data.h:717
TsKnotType GetKnotType() const override
Definition: data.h:589
GLdouble t
Definition: glad.h:2397
PXR_NAMESPACE_OPEN_SCOPE typedef double TsTime
The time type used by Ts.
Definition: types.h:57
#define TS_API
Definition: api.h:41
void SetRightTangentLength(TsTime) override
Definition: data.h:904
virtual TsKnotType GetKnotType() const =0
VtValue GetValueDerivative() const override
Definition: data.h:646
virtual bool ValueCanBeInterpolated() const =0
virtual TsTime GetRightTangentLength() const =0
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
TsTime GetTime() const
Definition: data.h:75
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
Holds the data for an TsKeyFrame.
Definition: data.h:50
static VtValue Cast(VtValue const &val)
Definition: value.h:1204
virtual VtValue GetLeftValueDerivative() const =0
T ValueType
Definition: data.h:143
virtual VtValue GetLeftValue() const =0
static TF_API std::string GetDisplayName(TfEnum val)
virtual ~Ts_Data()=default
GLuint GLfloat * val
Definition: glcorearb.h:1608
VtValue GetLeftValue() const override
Definition: data.h:699
bool GetIsDualValued() const override
Definition: data.h:673
virtual bool ValueCanBeExtrapolated() const =0
VT_API std::string GetTypeName() const
Return the type name of the held typeid.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
VtValue GetLeftTangentSlope() const override
Definition: data.h:780
Ts_TypedData< T > This
Definition: data.h:144
void SetValue(VtValue) override
Definition: data.h:657
bool ValueTypeSupportsTangents() const override
Definition: data.h:771
Definition: core.h:1131
bool GetTangentSymmetryBroken() const override
Definition: data.h:934
GLdouble GLdouble GLdouble y2
Definition: glad.h:2349
virtual bool operator==(const Ts_Data &) const =0
void ResetTangentSymmetryBroken() override
Definition: data.h:965
void SetLeftTangentSlope(VtValue) override
Definition: data.h:832
type
Definition: core.h:1059
virtual bool ValueTypeSupportsTangents() const =0
Definition: value.h:164
virtual VtValue EvalDerivativeUncached(Ts_Data const *kf2, TsTime time) const =0
VtValue EvalDerivativeUncached(Ts_Data const *kf2, TsTime time) const override
Definition: data.h:550
virtual VtValue EvalUncached(Ts_Data const *kf2, TsTime time) const =0
std::shared_ptr< Ts_UntypedEvalCache > CreateEvalCache(Ts_Data const *kf2) const override
Definition: data.h:510
virtual void SetLeftValue(VtValue)=0