Blender V4.5
node_xml.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifdef WITH_PUGIXML
6
7# include "graph/node_xml.h"
8# include "graph/node.h"
9
10# include "util/string.h"
11# include "util/transform.h"
12
14
15static bool xml_read_boolean(const char *value)
16{
17 return string_iequals(value, "true") || (atoi(value) != 0);
18}
19
20static const char *xml_write_boolean(bool value)
21{
22 return (value) ? "true" : "false";
23}
24
25template<int VECTOR_SIZE, typename T>
26static void xml_read_float_array(T &value, xml_attribute attr)
27{
28 vector<string> tokens;
29 string_split(tokens, attr.value());
30
31 if (tokens.size() % VECTOR_SIZE != 0) {
32 return;
33 }
34
35 value.resize(tokens.size() / VECTOR_SIZE);
36 for (size_t i = 0; i < value.size(); i++) {
37 float *value_float = (float *)&value[i];
38
39 for (size_t j = 0; j < VECTOR_SIZE; j++) {
40 value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str());
41 }
42 }
43}
44
45void xml_read_node(XMLReader &reader, Node *node, const xml_node xml_node)
46{
47 const xml_attribute name_attr = xml_node.attribute("name");
48 if (name_attr) {
49 node->name = ustring(name_attr.value());
50 }
51
52 for (const SocketType &socket : node->type->inputs) {
53 if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
54 continue;
55 }
56 if (socket.flags & SocketType::INTERNAL) {
57 continue;
58 }
59
60 const xml_attribute attr = xml_node.attribute(socket.name.c_str());
61
62 if (!attr) {
63 continue;
64 }
65
66 switch (socket.type) {
68 node->set(socket, xml_read_boolean(attr.value()));
69 break;
70 }
72 vector<string> tokens;
73 string_split(tokens, attr.value());
74
75 array<bool> value;
76 value.resize(tokens.size());
77 for (size_t i = 0; i < value.size(); i++) {
78 value[i] = xml_read_boolean(tokens[i].c_str());
79 }
80 node->set(socket, value);
81 break;
82 }
83 case SocketType::FLOAT: {
84 node->set(socket, (float)atof(attr.value()));
85 break;
86 }
88 array<float> value;
89 xml_read_float_array<1>(value, attr);
90 node->set(socket, value);
91 break;
92 }
93 case SocketType::INT: {
94 node->set(socket, atoi(attr.value()));
95 break;
96 }
97 case SocketType::UINT: {
98 node->set(socket, (uint)atoi(attr.value()));
99 break;
100 }
101 case SocketType::UINT64: {
102 node->set(socket, (uint64_t)strtoull(attr.value(), nullptr, 10));
103 break;
104 }
106 vector<string> tokens;
107 string_split(tokens, attr.value());
108
109 array<int> value;
110 value.resize(tokens.size());
111 for (size_t i = 0; i < value.size(); i++) {
112 value[i] = atoi(attr.value());
113 }
114 node->set(socket, value);
115 break;
116 }
120 case SocketType::NORMAL: {
121 array<float3> value;
122 xml_read_float_array<3>(value, attr);
123 if (value.size() == 1) {
124 node->set(socket, value[0]);
125 }
126 break;
127 }
132 array<float3> value;
133 xml_read_float_array<3>(value, attr);
134 node->set(socket, value);
135 break;
136 }
137 case SocketType::POINT2: {
138 array<float2> value;
139 xml_read_float_array<2>(value, attr);
140 if (value.size() == 1) {
141 node->set(socket, value[0]);
142 }
143 break;
144 }
146 array<float2> value;
147 xml_read_float_array<2>(value, attr);
148 node->set(socket, value);
149 break;
150 }
151 case SocketType::STRING: {
152 node->set(socket, attr.value());
153 break;
154 }
155 case SocketType::ENUM: {
156 const ustring value(attr.value());
157 if (socket.enum_values->exists(value)) {
158 node->set(socket, value);
159 }
160 else {
161 fprintf(stderr,
162 "Unknown value \"%s\" for attribute \"%s\".\n",
163 value.c_str(),
164 socket.name.c_str());
165 }
166 break;
167 }
169 vector<string> tokens;
170 string_split(tokens, attr.value());
171
172 array<ustring> value;
173 value.resize(tokens.size());
174 for (size_t i = 0; i < value.size(); i++) {
175 value[i] = ustring(tokens[i]);
176 }
177 node->set(socket, value);
178 break;
179 }
181 array<Transform> value;
182 xml_read_float_array<12>(value, attr);
183 if (value.size() == 1) {
184 node->set(socket, value[0]);
185 }
186 break;
187 }
189 array<Transform> value;
190 xml_read_float_array<12>(value, attr);
191 node->set(socket, value);
192 break;
193 }
194 case SocketType::NODE: {
195 const ustring value(attr.value());
196 const map<ustring, Node *>::iterator it = reader.node_map.find(value);
197 if (it != reader.node_map.end()) {
198 Node *value_node = it->second;
199 if (value_node->is_a(socket.node_type)) {
200 node->set(socket, it->second);
201 }
202 }
203 break;
204 }
206 vector<string> tokens;
207 string_split(tokens, attr.value());
208
209 array<Node *> value;
210 value.resize(tokens.size());
211 for (size_t i = 0; i < value.size(); i++) {
212 const map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i]));
213 if (it != reader.node_map.end()) {
214 Node *value_node = it->second;
215 value[i] = (value_node->is_a(socket.node_type)) ? value_node : nullptr;
216 }
217 else {
218 value[i] = nullptr;
219 }
220 }
221 node->set(socket, value);
222 break;
223 }
227 break;
228 }
229 }
230
231 if (!node->name.empty()) {
232 reader.node_map[node->name] = node;
233 }
234}
235
236xml_node xml_write_node(Node *node, xml_node xml_root)
237{
238 xml_node xml_node = xml_root.append_child(node->type->name.c_str());
239
240 xml_node.append_attribute("name") = node->name.c_str();
241
242 for (const SocketType &socket : node->type->inputs) {
243 if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
244 continue;
245 }
246 if (socket.flags & SocketType::INTERNAL) {
247 continue;
248 }
249 if (node->has_default_value(socket)) {
250 continue;
251 }
252
253 xml_attribute attr = xml_node.append_attribute(socket.name.c_str());
254
255 switch (socket.type) {
256 case SocketType::BOOLEAN: {
257 attr = xml_write_boolean(node->get_bool(socket));
258 break;
259 }
261 std::stringstream ss;
262 const array<bool> &value = node->get_bool_array(socket);
263 for (size_t i = 0; i < value.size(); i++) {
264 ss << xml_write_boolean(value[i]);
265 if (i != value.size() - 1) {
266 ss << " ";
267 }
268 }
269 attr = ss.str().c_str();
270 break;
271 }
272 case SocketType::FLOAT: {
273 attr = (double)node->get_float(socket);
274 break;
275 }
277 std::stringstream ss;
278 const array<float> &value = node->get_float_array(socket);
279 for (size_t i = 0; i < value.size(); i++) {
280 ss << value[i];
281 if (i != value.size() - 1) {
282 ss << " ";
283 }
284 }
285 attr = ss.str().c_str();
286 break;
287 }
288 case SocketType::INT: {
289 attr = node->get_int(socket);
290 break;
291 }
292 case SocketType::UINT: {
293 attr = node->get_uint(socket);
294 break;
295 }
296 case SocketType::UINT64: {
297 attr = node->get_uint64(socket);
298 break;
299 }
301 std::stringstream ss;
302 const array<int> &value = node->get_int_array(socket);
303 for (size_t i = 0; i < value.size(); i++) {
304 ss << value[i];
305 if (i != value.size() - 1) {
306 ss << " ";
307 }
308 }
309 attr = ss.str().c_str();
310 break;
311 }
315 case SocketType::NORMAL: {
316 const float3 value = node->get_float3(socket);
317 attr =
318 string_printf("%g %g %g", (double)value.x, (double)value.y, (double)value.z).c_str();
319 break;
320 }
325 std::stringstream ss;
326 const array<float3> &value = node->get_float3_array(socket);
327 for (size_t i = 0; i < value.size(); i++) {
328 ss << string_printf(
329 "%g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z);
330 if (i != value.size() - 1) {
331 ss << " ";
332 }
333 }
334 attr = ss.str().c_str();
335 break;
336 }
337 case SocketType::POINT2: {
338 const float2 value = node->get_float2(socket);
339 attr = string_printf("%g %g", (double)value.x, (double)value.y).c_str();
340 break;
341 }
343 std::stringstream ss;
344 const array<float2> &value = node->get_float2_array(socket);
345 for (size_t i = 0; i < value.size(); i++) {
346 ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y);
347 if (i != value.size() - 1) {
348 ss << " ";
349 }
350 }
351 attr = ss.str().c_str();
352 break;
353 }
355 case SocketType::ENUM: {
356 attr = node->get_string(socket).c_str();
357 break;
358 }
360 std::stringstream ss;
361 const array<ustring> &value = node->get_string_array(socket);
362 for (size_t i = 0; i < value.size(); i++) {
363 ss << value[i];
364 if (i != value.size() - 1) {
365 ss << " ";
366 }
367 }
368 attr = ss.str().c_str();
369 break;
370 }
372 Transform tfm = node->get_transform(socket);
373 std::stringstream ss;
374 for (int i = 0; i < 3; i++) {
375 ss << string_printf("%g %g %g %g ",
376 (double)tfm[i][0],
377 (double)tfm[i][1],
378 (double)tfm[i][2],
379 (double)tfm[i][3]);
380 }
381 ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
382 attr = ss.str().c_str();
383 break;
384 }
386 std::stringstream ss;
387 const array<Transform> &value = node->get_transform_array(socket);
388 for (size_t j = 0; j < value.size(); j++) {
389 const Transform &tfm = value[j];
390
391 for (int i = 0; i < 3; i++) {
392 ss << string_printf("%g %g %g %g ",
393 (double)tfm[i][0],
394 (double)tfm[i][1],
395 (double)tfm[i][2],
396 (double)tfm[i][3]);
397 }
398 ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
399 if (j != value.size() - 1) {
400 ss << " ";
401 }
402 }
403 attr = ss.str().c_str();
404 break;
405 }
406 case SocketType::NODE: {
407 Node *value = node->get_node(socket);
408 if (value) {
409 attr = value->name.c_str();
410 }
411 break;
412 }
414 std::stringstream ss;
415 const array<Node *> &value = node->get_node_array(socket);
416 for (size_t i = 0; i < value.size(); i++) {
417 if (value[i]) {
418 ss << value[i]->name.c_str();
419 }
420 if (i != value.size() - 1) {
421 ss << " ";
422 }
423 }
424 attr = ss.str().c_str();
425 break;
426 }
430 break;
431 }
432 }
433
434 return xml_node;
435}
436
438
439#endif /* WITH_PUGIXML */
unsigned int uint
unsigned long long int uint64_t
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
size_t size() const
T * resize(const size_t newsize)
static bool xml_read_float_array(vector< float > &value, const xml_node node, const char *name)
#define CCL_NAMESPACE_END
#define T
bool string_iequals(const string &a, const string &b)
Definition string.cpp:55
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
void string_split(vector< string > &tokens, const string &str, const string &separators, bool skip_empty_tokens)
Definition string.cpp:70
bool exists(ustring x) const
Definition node_enum.h:29
vector< SocketType, std::allocator< SocketType > > inputs
Definition node_type.h:125
ustring name
Definition node_type.h:122
bool has_default_value(const SocketType &input) const
const array< float3 > & get_float3_array(const SocketType &input) const
const array< float > & get_float_array(const SocketType &input) const
const array< int > & get_int_array(const SocketType &input) const
float get_float(const SocketType &input) const
Transform get_transform(const SocketType &input) const
void set(const SocketType &input, bool value)
uint64_t get_uint64(const SocketType &input) const
const NodeType * type
Definition graph/node.h:178
float3 get_float3(const SocketType &input) const
const array< bool > & get_bool_array(const SocketType &input) const
const array< Node * > & get_node_array(const SocketType &input) const
ustring name
Definition graph/node.h:177
bool get_bool(const SocketType &input) const
float2 get_float2(const SocketType &input) const
const array< ustring > & get_string_array(const SocketType &input) const
const array< float2 > & get_float2_array(const SocketType &input) const
ustring get_string(const SocketType &input) const
bool is_a(const NodeType *type)
Node * get_node(const SocketType &input) const
uint get_uint(const SocketType &input) const
int get_int(const SocketType &input) const
const array< Transform > & get_transform_array(const SocketType &input) const
ustring name
Definition node_type.h:79
const NodeType * node_type
Definition node_type.h:84
@ BOOLEAN_ARRAY
Definition node_type.h:43
@ TRANSFORM_ARRAY
Definition node_type.h:52
Type type
Definition node_type.h:80
const NodeEnum * enum_values
Definition node_type.h:83
float x
float y
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
i
Definition text_draw.cc:230