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