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