Loading...
Searching...
No Matches
valueTransform.h
1//
2// Copyright 2025 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7
8#ifndef PXR_BASE_VT_VALUE_TRANSFORM_H
9#define PXR_BASE_VT_VALUE_TRANSFORM_H
10
11#include "pxr/pxr.h"
12
14#include "pxr/base/vt/types.h"
15#include "pxr/base/vt/value.h"
16#include "pxr/base/vt/valueRef.h"
17
18#include <optional>
19
20PXR_NAMESPACE_OPEN_SCOPE
21
22class Vt_TransformImpl
23{
24private:
25 template <class Xf>
26 friend bool
27 VtValueCanTransform(VtValueRef obj, Xf const &xfObj);
28
29 template <class Xf>
30 friend VtValue
31 VtValueTryTransform(VtValueRef obj, Xf const &xfObj);
32
33 VT_API
34 static bool
35 Can(VtValueRef obj, std::type_info const &xfType);
36
37 VT_API
38 static VtValue
39 Try(VtValueRef x, std::type_info const &xfType, void const *xfObj,
41};
42
49template <class Xf>
50bool
51VtValueCanTransform(VtValueRef obj, Xf const &xfObj)
52{
53 if (obj.IsEmpty() || !obj.CanTransform()) {
54 return false;
55 }
56 return Vt_TransformImpl::Can(obj, typeid(xfObj));
57}
58
62template <class Xf>
64VtValueTryTransform(VtValueRef obj, Xf const &xfObj)
65{
66 if (obj.IsEmpty() || !obj.CanTransform()) {
67 return {};
68 }
69 // Helper for type-erased transforms.
70 auto erasedXf = [&xfObj](VtValueRef in) -> VtValue {
71 return VtValueTryTransform(in, xfObj);
72 };
73 return Vt_TransformImpl
74 ::Try(obj, typeid(xfObj),
75 static_cast<void const *>(std::addressof(xfObj)), erasedXf);
76}
77
78// Registration helper.
79VT_API void
80Vt_RegisterTypedTransform(
81 std::type_info const &objType,
82 std::type_info const &xfType,
83 void (*voidFn)(),
84 VtValue (*xform)(VtValueRef, void const *, void (*)()));
85
86template <bool RegisterForArrays, class T, class Xf>
87void
88Vt_RegisterTransformImpl(T (*fn)(T const &obj, Xf const &xform))
89{
90 static_assert(!VtIsKnownValueType<T>(),
91 "Unexpected transform registration for one of the "
92 "known value types");
93
95 "Use VT_VALUE_TYPE_CAN_TRANSFORM or directly specialize "
96 "VtValueTypeCanTransform<> before registering transform "
97 "functionality");
98
99 using TypedFn = T (*)(T const &, Xf const &);
100 using VoidFn = void (*)();
101
102 VoidFn voidFn = reinterpret_cast<VoidFn>(fn);
103 Vt_RegisterTypedTransform(
104 typeid(T), typeid(Xf), voidFn,
105 [](VtValueRef obj, void const *xf, void (*vFn)()) {
106 TypedFn tFn = reinterpret_cast<TypedFn>(vFn);
107 TF_DEV_AXIOM(obj.IsHolding<T>());
108 return VtValue {
109 tFn(obj.UncheckedGet<T>(), *static_cast<Xf const *>(xf))
110 };
111 });
112
113 // Register array & array edit xforms of the same, if requested.
114 if constexpr (RegisterForArrays) {
115 // Arrays.
116 Vt_RegisterTypedTransform(
117 typeid(VtArray<T>), typeid(Xf), voidFn,
118 [](VtValueRef obj, void const *xf, void (*vFn)()) {
119 TypedFn tFn = reinterpret_cast<TypedFn>(vFn);
121 VtArray<T> const &src = obj.UncheckedGet<VtArray<T>>();
122 VtArray<T> xformed;
123 T const *srcPtr = src.cdata();
124 Xf const &xform = *static_cast<Xf const *>(xf);
125 xformed.resize(src.size(), [&](T *first, T *last) {
126 while (first != last) {
127 new (first++) T { tFn(*srcPtr++, xform) };
128 }
129 });
130 return VtValue::Take(xformed);
131 });
132
133 // Array Edits.
134 Vt_RegisterTypedTransform(
135 typeid(VtArrayEdit<T>), typeid(Xf), voidFn,
136 [](VtValueRef obj, void const *xf, void (*vFn)()) {
137 TypedFn tFn = reinterpret_cast<TypedFn>(vFn);
139 VtArrayEdit<T> const &src = obj.UncheckedGet<VtArrayEdit<T>>();
140 VtArrayEdit<T> xformed = src;
141 Xf const &xform = *static_cast<Xf const *>(xf);
142 for (T &elem: xformed.GetMutableLiterals()) {
143 elem = tFn(elem, xform);
144 }
145 return VtValue::Take(xformed);
146 });
147 }
148}
149
153template <class T, class Xf>
154void
155VtRegisterTransformNoArrays(T (*fn)(T const &obj, Xf const &xform))
156{
157 Vt_RegisterTransformImpl</*RegisterForArrays=*/false>(fn);
158}
159
164template <class T, class Xf>
165void
166VtRegisterTransform(T (*fn)(T const &obj, Xf const &xform))
167{
168 Vt_RegisterTransformImpl</*RegisterForArrays=*/true>(fn);
169}
170
171VT_API void
172Vt_RegisterErasedTransform(
173 std::type_info const &objType,
174 void (*voidFn)(),
175 VtValue (*xform)(VtValueRef, void (*)(),
177
182template <class T>
183void
184VtRegisterErasedTransform(
185 std::optional<T> (*fn)(T const &obj, TfFunctionRef<VtValue (VtValueRef)>))
186{
187 static_assert(!VtIsKnownValueType<T>(),
188 "Unexpected transform registration for one of the "
189 "known value types");
190
192 "Use VT_VALUE_TYPE_CAN_TRANSFORM or specialize "
193 "VtValueTypeCanTransform<> before registering transform "
194 "functionality");
195
196 using TypedFn = std::optional<T> (*)(
197 T const &, TfFunctionRef<VtValue (VtValueRef)>);
198 using VoidFn = void (*)();
199
200 VoidFn voidFn = reinterpret_cast<VoidFn>(fn);
201 Vt_RegisterErasedTransform(
202 typeid(T), voidFn,
203 [](VtValueRef obj, VoidFn vFn,
205 TypedFn tFn = reinterpret_cast<TypedFn>(vFn);
206 TF_DEV_AXIOM(obj.IsHolding<T>());
207 std::optional<T> optT = tFn(obj.UncheckedGet<T>(), xform);
208 VtValue ret;
209 if (optT) {
210 ret = std::move(*optT);
211 }
212 return ret;
213 });
214}
215
216PXR_NAMESPACE_CLOSE_SCOPE
217
218#endif // PXR_BASE_VT_VALUE_TRANSFORM_H
Defines all the types "TYPED" for which Vt creates a VtTYPEDArray typedef.
This class provides a non-owning reference to a type-erased callable object with a specified signatur...
Definition: functionRef.h:19
An array edit represents a sequence of per-element modifications to a VtArray.
Definition: arrayEdit.h:52
TfSpan< ElementType > GetMutableLiterals()
Return a mutable view of the literal elements that this edit makes use of.
Definition: arrayEdit.h:87
Represents an arbitrary dimensional rectangular container class.
Definition: array.h:213
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:90
static VtValue Take(T &obj)
Create a new VtValue, taking its contents from obj.
Definition: value.h:869
A non-owning type-erased view of a value, interoperating with VtValue.
Definition: valueRef.h:65
bool IsEmpty() const
Returns true iff this value is empty.
Definition: valueRef.h:515
bool CanTransform() const
Return true if this value holds a type that has been declared to support value transforms at compile ...
Definition: valueRef.h:544
_TypeInfoFor< T >::GetObjResultType UncheckedGet() const
Return a const reference to the viewed object if the viewed object is of type T.
Definition: valueRef.h:452
bool IsHolding() const
Return true if this value is viewing an object of type T, false otherwise.
Definition: valueRef.h:403
const_pointer cdata() const
Return a const pointer to the data held by this array.
Definition: array.h:407
size_t size() const
Return the total number of elements in this array.
Definition: array.h:474
void resize(size_t newSize)
Resize this array.
Definition: array.h:545
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
Definition: diagnostic.h:205
A trait indicating whether VtValue transform functionality can be registered for a type.
Definition: traits.h:147