Blender V5.0
usd_reader_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 NVIDIA Corporation. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "usd_reader_utils.hh"
6
7#include "BLI_string_ref.hh"
8
9#include "BKE_idprop.hh"
10
11#include <pxr/usd/usd/attribute.h>
12
13#include "CLG_log.h"
14static CLG_LogRef LOG = {"io.usd"};
15
16namespace {
17
18template<typename VECT>
19void set_array_prop(IDProperty *idgroup,
20 const blender::StringRefNull prop_name,
21 const pxr::UsdAttribute &attr,
22 const pxr::UsdTimeCode time)
23{
24 if (!idgroup || !attr) {
25 return;
26 }
27
28 VECT vec;
29 if (!attr.Get<VECT>(&vec, time)) {
30 return;
31 }
32
33 IDPropertyTemplate val = {0};
34 val.array.len = int(vec.dimension);
35
36 if (val.array.len <= 0) {
37 CLOG_WARN(&LOG, "Invalid array length for prop %s", prop_name.c_str());
38 return;
39 }
40
41 if (std::is_same<float, typename VECT::ScalarType>()) {
42 val.array.type = IDP_FLOAT;
43 }
44 else if (std::is_same<pxr::GfHalf, typename VECT::ScalarType>()) {
45 val.array.type = IDP_FLOAT;
46 }
47 else if (std::is_same<double, typename VECT::ScalarType>()) {
48 val.array.type = IDP_DOUBLE;
49 }
50 else if (std::is_same<int, typename VECT::ScalarType>()) {
51 val.array.type = IDP_INT;
52 }
53 else {
54 CLOG_WARN(&LOG, "Couldn't determine array type for prop %s", prop_name.c_str());
55 return;
56 }
57
58 IDProperty *prop = IDP_New(IDP_ARRAY, &val, prop_name);
59
60 if (!prop) {
61 CLOG_WARN(&LOG, "Couldn't create array prop %s", prop_name.c_str());
62 return;
63 }
64
65 if (std::is_same<pxr::GfHalf, typename VECT::ScalarType>()) {
66 float *prop_data = static_cast<float *>(prop->data.pointer);
67 for (int i = 0; i < val.array.len; ++i) {
68 prop_data[i] = vec[i];
69 }
70 }
71 else {
72 std::memcpy(prop->data.pointer, vec.data(), prop->len * sizeof(typename VECT::ScalarType));
73 }
74
75 IDP_AddToGroup(idgroup, prop);
76}
77
78bool equivalent(const pxr::SdfValueTypeName &type_name1, const pxr::SdfValueTypeName &type_name2)
79{
80 return type_name1.GetType().IsA(type_name2.GetType());
81}
82
83} // anonymous namespace
84
85namespace blender::io::usd {
86
87static void set_string_prop(IDProperty *idgroup,
88 const StringRefNull prop_name,
89 const StringRefNull str_val)
90{
91 if (!idgroup) {
92 return;
93 }
94
95 IDPropertyTemplate val = {0};
96 val.string.str = str_val.data();
97 /* Note length includes null terminator. */
98 val.string.len = str_val.size() + 1;
100
101 IDProperty *prop = IDP_New(IDP_STRING, &val, prop_name);
102
103 IDP_AddToGroup(idgroup, prop);
104}
105
106static void set_int_prop(IDProperty *idgroup, const StringRefNull prop_name, const int ival)
107{
108 if (!idgroup) {
109 return;
110 }
111
112 IDPropertyTemplate val = {0};
113 val.i = ival;
114 IDProperty *prop = IDP_New(IDP_INT, &val, prop_name);
115
116 IDP_AddToGroup(idgroup, prop);
117}
118
119static void set_bool_prop(IDProperty *idgroup, const StringRefNull prop_name, const bool bval)
120{
121 if (!idgroup) {
122 return;
123 }
124
125 IDPropertyTemplate val = {0};
126 val.i = bval;
127 IDProperty *prop = IDP_New(IDP_BOOLEAN, &val, prop_name);
128
129 IDP_AddToGroup(idgroup, prop);
130}
131
132static void set_float_prop(IDProperty *idgroup, const StringRefNull prop_name, const float fval)
133{
134 if (!idgroup) {
135 return;
136 }
137
138 IDPropertyTemplate val = {0};
139 val.f = fval;
140 IDProperty *prop = IDP_New(IDP_FLOAT, &val, prop_name);
141
142 IDP_AddToGroup(idgroup, prop);
143}
144
145static void set_double_prop(IDProperty *idgroup, const StringRefNull prop_name, const double dval)
146{
147 if (!idgroup) {
148 return;
149 }
150
151 IDPropertyTemplate val = {0};
152 val.d = dval;
153 IDProperty *prop = IDP_New(IDP_DOUBLE, &val, prop_name);
154
155 IDP_AddToGroup(idgroup, prop);
156}
157
159 const pxr::UsdPrim &prim,
160 const eUSDPropertyImportMode property_import_mode,
161 const pxr::UsdTimeCode time_code)
162{
163 pxr::UsdAttributeVector attribs = prim.GetAuthoredAttributes();
164 if (attribs.empty()) {
165 return;
166 }
167
168 bool all_custom_attrs = (property_import_mode == USD_ATTR_IMPORT_ALL);
169
170 for (const pxr::UsdAttribute &attr : attribs) {
171 if (!attr.IsCustom()) {
172 continue;
173 }
174
175 std::vector<std::string> attr_names = attr.SplitName();
176
177 const bool is_user_prop = attr_names[0] == "userProperties";
178
179 if (attr_names.size() > 2 && is_user_prop && attr_names[1] == "blender") {
180 continue;
181 }
182
183 if (!all_custom_attrs && !is_user_prop) {
184 continue;
185 }
186
187 IDProperty *idgroup = IDP_EnsureProperties(id);
188
189 /* When importing user properties, strip the namespace. */
190 pxr::TfToken attr_name;
191 if (is_user_prop) {
192 /* We strip the userProperties namespace, but leave others in case
193 * someone's custom attribute namespace is important in their pipeline. */
194 const StringRefNull token = "userProperties:";
195 const StringRefNull name = attr.GetName().GetString();
196 attr_name = pxr::TfToken(name.substr(token.size()));
197 }
198 else {
199 attr_name = attr.GetName();
200 }
201
202 pxr::SdfValueTypeName type_name = attr.GetTypeName();
203
204 if (type_name == pxr::SdfValueTypeNames->Int) {
205 int ival = 0;
206 if (attr.Get<int>(&ival, time_code)) {
207 set_int_prop(idgroup, attr_name.GetString(), ival);
208 }
209 }
210 else if (type_name == pxr::SdfValueTypeNames->Float) {
211 float fval = 0.0f;
212 if (attr.Get<float>(&fval, time_code)) {
213 set_float_prop(idgroup, attr_name.GetString(), fval);
214 }
215 }
216 else if (type_name == pxr::SdfValueTypeNames->Double) {
217 double dval = 0.0;
218 if (attr.Get<double>(&dval, time_code)) {
219 set_double_prop(idgroup, attr_name.GetString(), dval);
220 }
221 }
222 else if (type_name == pxr::SdfValueTypeNames->Half) {
223 pxr::GfHalf hval = 0.0f;
224 if (attr.Get<pxr::GfHalf>(&hval, time_code)) {
225 set_float_prop(idgroup, attr_name.GetString(), hval);
226 }
227 }
228 else if (type_name == pxr::SdfValueTypeNames->String) {
229 std::string sval;
230 if (attr.Get<std::string>(&sval, time_code)) {
231 set_string_prop(idgroup, attr_name.GetString(), sval);
232 }
233 }
234 else if (type_name == pxr::SdfValueTypeNames->Token) {
235 pxr::TfToken tval;
236 if (attr.Get<pxr::TfToken>(&tval, time_code)) {
237 set_string_prop(idgroup, attr_name.GetString(), tval.GetString());
238 }
239 }
240 else if (type_name == pxr::SdfValueTypeNames->Asset) {
241 pxr::SdfAssetPath aval;
242 if (attr.Get<pxr::SdfAssetPath>(&aval, time_code)) {
243 set_string_prop(idgroup, attr_name.GetString(), aval.GetAssetPath());
244 }
245 }
246 else if (type_name == pxr::SdfValueTypeNames->Bool) {
247 bool bval = false;
248 if (attr.Get<bool>(&bval, time_code)) {
249 set_bool_prop(idgroup, attr_name.GetString(), bval);
250 }
251 }
252 else if (equivalent(type_name, pxr::SdfValueTypeNames->Float2)) {
253 set_array_prop<pxr::GfVec2f>(idgroup, attr_name.GetString(), attr, time_code);
254 }
255 else if (equivalent(type_name, pxr::SdfValueTypeNames->Float3)) {
256 set_array_prop<pxr::GfVec3f>(idgroup, attr_name.GetString(), attr, time_code);
257 }
258 else if (equivalent(type_name, pxr::SdfValueTypeNames->Float4)) {
259 set_array_prop<pxr::GfVec4f>(idgroup, attr_name.GetString(), attr, time_code);
260 }
261 else if (equivalent(type_name, pxr::SdfValueTypeNames->Double2)) {
262 set_array_prop<pxr::GfVec2d>(idgroup, attr_name.GetString(), attr, time_code);
263 }
264 else if (equivalent(type_name, pxr::SdfValueTypeNames->Double3)) {
265 set_array_prop<pxr::GfVec3d>(idgroup, attr_name.GetString(), attr, time_code);
266 }
267 else if (equivalent(type_name, pxr::SdfValueTypeNames->Double4)) {
268 set_array_prop<pxr::GfVec4d>(idgroup, attr_name.GetString(), attr, time_code);
269 }
270 else if (equivalent(type_name, pxr::SdfValueTypeNames->Int2)) {
271 set_array_prop<pxr::GfVec2i>(idgroup, attr_name.GetString(), attr, time_code);
272 }
273 else if (equivalent(type_name, pxr::SdfValueTypeNames->Int3)) {
274 set_array_prop<pxr::GfVec3i>(idgroup, attr_name.GetString(), attr, time_code);
275 }
276 else if (equivalent(type_name, pxr::SdfValueTypeNames->Int4)) {
277 set_array_prop<pxr::GfVec4i>(idgroup, attr_name.GetString(), attr, time_code);
278 }
279 else if (equivalent(type_name, pxr::SdfValueTypeNames->Half2)) {
280 set_array_prop<pxr::GfVec2h>(idgroup, attr_name.GetString(), attr, time_code);
281 }
282 else if (equivalent(type_name, pxr::SdfValueTypeNames->Half3)) {
283 set_array_prop<pxr::GfVec3h>(idgroup, attr_name.GetString(), attr, time_code);
284 }
285 else if (equivalent(type_name, pxr::SdfValueTypeNames->Half4)) {
286 set_array_prop<pxr::GfVec4h>(idgroup, attr_name.GetString(), attr, time_code);
287 }
288 }
289}
290
291} // namespace blender::io::usd
IDProperty * IDP_New(char type, const IDPropertyTemplate *val, blender::StringRef name, eIDPropertyFlag flags={}) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:1009
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:717
IDProperty * IDP_EnsureProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition idprop.cc:882
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
@ IDP_STRING_SUB_UTF8
@ IDP_DOUBLE
@ IDP_FLOAT
@ IDP_STRING
@ IDP_BOOLEAN
@ IDP_INT
@ IDP_ARRAY
constexpr int64_t size() const
constexpr const char * data() const
constexpr const char * c_str() const
#define LOG(level)
Definition log.h:97
static void set_double_prop(IDProperty *idgroup, const StringRefNull prop_name, const double dval)
static void set_string_prop(IDProperty *idgroup, const StringRefNull prop_name, const StringRefNull str_val)
eUSDPropertyImportMode
Definition usd.hh:54
@ USD_ATTR_IMPORT_ALL
Definition usd.hh:57
static void set_float_prop(IDProperty *idgroup, const StringRefNull prop_name, const float fval)
void set_id_props_from_prim(ID *id, const pxr::UsdPrim &prim, const eUSDPropertyImportMode property_import_mode, const pxr::UsdTimeCode time_code)
static void set_bool_prop(IDProperty *idgroup, const StringRefNull prop_name, const bool bval)
static void set_int_prop(IDProperty *idgroup, const StringRefNull prop_name, const int ival)
const char * name
void * pointer
Definition DNA_ID.h:142
int len
Definition DNA_ID.h:175
IDPropertyData data
Definition DNA_ID.h:169
Definition DNA_ID.h:414
i
Definition text_draw.cc:230
struct IDPropertyTemplate::@032057005265002020267344110225167212360002125060 array
const char * str
Definition BKE_idprop.hh:39
struct IDPropertyTemplate::@306303166102371126056157213146124155011254157272 string