Blender  V3.3
node_xml.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "graph/node_xml.h"
5 
6 #include "util/foreach.h"
7 #include "util/string.h"
8 #include "util/transform.h"
9 
11 
12 static bool xml_read_boolean(const char *value)
13 {
14  return string_iequals(value, "true") || (atoi(value) != 0);
15 }
16 
17 static const char *xml_write_boolean(bool value)
18 {
19  return (value) ? "true" : "false";
20 }
21 
22 template<int VECTOR_SIZE, typename T>
23 static void xml_read_float_array(T &value, xml_attribute attr)
24 {
25  vector<string> tokens;
26  string_split(tokens, attr.value());
27 
28  if (tokens.size() % VECTOR_SIZE != 0) {
29  return;
30  }
31 
32  value.resize(tokens.size() / VECTOR_SIZE);
33  for (size_t i = 0; i < value.size(); i++) {
34  float *value_float = (float *)&value[i];
35 
36  for (size_t j = 0; j < VECTOR_SIZE; j++)
37  value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str());
38  }
39 }
40 
41 void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
42 {
43  xml_attribute name_attr = xml_node.attribute("name");
44  if (name_attr) {
45  node->name = ustring(name_attr.value());
46  }
47 
48  foreach (const SocketType &socket, node->type->inputs) {
49  if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
50  continue;
51  }
52  if (socket.flags & SocketType::INTERNAL) {
53  continue;
54  }
55 
56  xml_attribute attr = xml_node.attribute(socket.name.c_str());
57 
58  if (!attr) {
59  continue;
60  }
61 
62  switch (socket.type) {
63  case SocketType::BOOLEAN: {
64  node->set(socket, xml_read_boolean(attr.value()));
65  break;
66  }
68  vector<string> tokens;
69  string_split(tokens, attr.value());
70 
71  array<bool> value;
72  value.resize(tokens.size());
73  for (size_t i = 0; i < value.size(); i++)
74  value[i] = xml_read_boolean(tokens[i].c_str());
75  node->set(socket, value);
76  break;
77  }
78  case SocketType::FLOAT: {
79  node->set(socket, (float)atof(attr.value()));
80  break;
81  }
83  array<float> value;
84  xml_read_float_array<1>(value, attr);
85  node->set(socket, value);
86  break;
87  }
88  case SocketType::INT: {
89  node->set(socket, (int)atoi(attr.value()));
90  break;
91  }
92  case SocketType::UINT: {
93  node->set(socket, (uint)atoi(attr.value()));
94  break;
95  }
96  case SocketType::INT_ARRAY: {
97  vector<string> tokens;
98  string_split(tokens, attr.value());
99 
100  array<int> value;
101  value.resize(tokens.size());
102  for (size_t i = 0; i < value.size(); i++) {
103  value[i] = (int)atoi(attr.value());
104  }
105  node->set(socket, value);
106  break;
107  }
108  case SocketType::COLOR:
109  case SocketType::VECTOR:
110  case SocketType::POINT:
111  case SocketType::NORMAL: {
112  array<float3> value;
113  xml_read_float_array<3>(value, attr);
114  if (value.size() == 1) {
115  node->set(socket, value[0]);
116  }
117  break;
118  }
123  array<float3> value;
124  xml_read_float_array<3>(value, attr);
125  node->set(socket, value);
126  break;
127  }
128  case SocketType::POINT2: {
129  array<float2> value;
130  xml_read_float_array<2>(value, attr);
131  if (value.size() == 1) {
132  node->set(socket, value[0]);
133  }
134  break;
135  }
137  array<float2> value;
138  xml_read_float_array<2>(value, attr);
139  node->set(socket, value);
140  break;
141  }
142  case SocketType::STRING: {
143  node->set(socket, attr.value());
144  break;
145  }
146  case SocketType::ENUM: {
147  ustring value(attr.value());
148  if (socket.enum_values->exists(value)) {
149  node->set(socket, value);
150  }
151  else {
152  fprintf(stderr,
153  "Unknown value \"%s\" for attribute \"%s\".\n",
154  value.c_str(),
155  socket.name.c_str());
156  }
157  break;
158  }
160  vector<string> tokens;
161  string_split(tokens, attr.value());
162 
163  array<ustring> value;
164  value.resize(tokens.size());
165  for (size_t i = 0; i < value.size(); i++) {
166  value[i] = ustring(tokens[i]);
167  }
168  node->set(socket, value);
169  break;
170  }
171  case SocketType::TRANSFORM: {
172  array<Transform> value;
173  xml_read_float_array<12>(value, attr);
174  if (value.size() == 1) {
175  node->set(socket, value[0]);
176  }
177  break;
178  }
180  array<Transform> value;
181  xml_read_float_array<12>(value, attr);
182  node->set(socket, value);
183  break;
184  }
185  case SocketType::NODE: {
186  ustring value(attr.value());
187  map<ustring, Node *>::iterator it = reader.node_map.find(value);
188  if (it != reader.node_map.end()) {
189  Node *value_node = it->second;
190  if (value_node->is_a(socket.node_type))
191  node->set(socket, it->second);
192  }
193  break;
194  }
195  case SocketType::NODE_ARRAY: {
196  vector<string> tokens;
197  string_split(tokens, attr.value());
198 
199  array<Node *> value;
200  value.resize(tokens.size());
201  for (size_t i = 0; i < value.size(); i++) {
202  map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i]));
203  if (it != reader.node_map.end()) {
204  Node *value_node = it->second;
205  value[i] = (value_node->is_a(socket.node_type)) ? value_node : NULL;
206  }
207  else {
208  value[i] = NULL;
209  }
210  }
211  node->set(socket, value);
212  break;
213  }
214  case SocketType::CLOSURE:
216  break;
217  }
218  }
219 
220  if (!node->name.empty())
221  reader.node_map[node->name] = node;
222 }
223 
224 xml_node xml_write_node(Node *node, xml_node xml_root)
225 {
226  xml_node xml_node = xml_root.append_child(node->type->name.c_str());
227 
228  xml_node.append_attribute("name") = node->name.c_str();
229 
230  foreach (const SocketType &socket, node->type->inputs) {
231  if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
232  continue;
233  }
234  if (socket.flags & SocketType::INTERNAL) {
235  continue;
236  }
237  if (node->has_default_value(socket)) {
238  continue;
239  }
240 
241  xml_attribute attr = xml_node.append_attribute(socket.name.c_str());
242 
243  switch (socket.type) {
244  case SocketType::BOOLEAN: {
245  attr = xml_write_boolean(node->get_bool(socket));
246  break;
247  }
249  std::stringstream ss;
250  const array<bool> &value = node->get_bool_array(socket);
251  for (size_t i = 0; i < value.size(); i++) {
252  ss << xml_write_boolean(value[i]);
253  if (i != value.size() - 1)
254  ss << " ";
255  }
256  attr = ss.str().c_str();
257  break;
258  }
259  case SocketType::FLOAT: {
260  attr = (double)node->get_float(socket);
261  break;
262  }
264  std::stringstream ss;
265  const array<float> &value = node->get_float_array(socket);
266  for (size_t i = 0; i < value.size(); i++) {
267  ss << value[i];
268  if (i != value.size() - 1) {
269  ss << " ";
270  }
271  }
272  attr = ss.str().c_str();
273  break;
274  }
275  case SocketType::INT: {
276  attr = node->get_int(socket);
277  break;
278  }
279  case SocketType::UINT: {
280  attr = node->get_uint(socket);
281  break;
282  }
283  case SocketType::INT_ARRAY: {
284  std::stringstream ss;
285  const array<int> &value = node->get_int_array(socket);
286  for (size_t i = 0; i < value.size(); i++) {
287  ss << value[i];
288  if (i != value.size() - 1) {
289  ss << " ";
290  }
291  }
292  attr = ss.str().c_str();
293  break;
294  }
295  case SocketType::COLOR:
296  case SocketType::VECTOR:
297  case SocketType::POINT:
298  case SocketType::NORMAL: {
299  float3 value = node->get_float3(socket);
300  attr =
301  string_printf("%g %g %g", (double)value.x, (double)value.y, (double)value.z).c_str();
302  break;
303  }
308  std::stringstream ss;
309  const array<float3> &value = node->get_float3_array(socket);
310  for (size_t i = 0; i < value.size(); i++) {
311  ss << string_printf(
312  "%g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z);
313  if (i != value.size() - 1) {
314  ss << " ";
315  }
316  }
317  attr = ss.str().c_str();
318  break;
319  }
320  case SocketType::POINT2: {
321  float2 value = node->get_float2(socket);
322  attr = string_printf("%g %g", (double)value.x, (double)value.y).c_str();
323  break;
324  }
326  std::stringstream ss;
327  const array<float2> &value = node->get_float2_array(socket);
328  for (size_t i = 0; i < value.size(); i++) {
329  ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y);
330  if (i != value.size() - 1) {
331  ss << " ";
332  }
333  }
334  attr = ss.str().c_str();
335  break;
336  }
337  case SocketType::STRING:
338  case SocketType::ENUM: {
339  attr = node->get_string(socket).c_str();
340  break;
341  }
343  std::stringstream ss;
344  const array<ustring> &value = node->get_string_array(socket);
345  for (size_t i = 0; i < value.size(); i++) {
346  ss << value[i];
347  if (i != value.size() - 1) {
348  ss << " ";
349  }
350  }
351  attr = ss.str().c_str();
352  break;
353  }
354  case SocketType::TRANSFORM: {
355  Transform tfm = node->get_transform(socket);
356  std::stringstream ss;
357  for (int i = 0; i < 3; i++) {
358  ss << string_printf("%g %g %g %g ",
359  (double)tfm[i][0],
360  (double)tfm[i][1],
361  (double)tfm[i][2],
362  (double)tfm[i][3]);
363  }
364  ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
365  attr = ss.str().c_str();
366  break;
367  }
369  std::stringstream ss;
370  const array<Transform> &value = node->get_transform_array(socket);
371  for (size_t j = 0; j < value.size(); j++) {
372  const Transform &tfm = value[j];
373 
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  if (j != value.size() - 1) {
383  ss << " ";
384  }
385  }
386  attr = ss.str().c_str();
387  break;
388  }
389  case SocketType::NODE: {
390  Node *value = node->get_node(socket);
391  if (value) {
392  attr = value->name.c_str();
393  }
394  break;
395  }
396  case SocketType::NODE_ARRAY: {
397  std::stringstream ss;
398  const array<Node *> &value = node->get_node_array(socket);
399  for (size_t i = 0; i < value.size(); i++) {
400  if (value[i]) {
401  ss << value[i]->name.c_str();
402  }
403  if (i != value.size() - 1) {
404  ss << " ";
405  }
406  }
407  attr = ss.str().c_str();
408  break;
409  }
410  case SocketType::CLOSURE:
412  break;
413  }
414  }
415 
416  return xml_node;
417 }
418 
unsigned int uint
Definition: BLI_sys_types.h:67
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
size_t size() const
T * resize(size_t newsize)
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
OperationNode * node
#define T
xml_node xml_write_node(Node *node, xml_node xml_root)
Definition: node_xml.cpp:224
static void xml_read_float_array(T &value, xml_attribute attr)
Definition: node_xml.cpp:23
void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
Definition: node_xml.cpp:41
static const char * xml_write_boolean(bool value)
Definition: node_xml.cpp:17
static CCL_NAMESPACE_BEGIN bool xml_read_boolean(const char *value)
Definition: node_xml.cpp:12
bool string_iequals(const string &a, const string &b)
Definition: string.cpp:54
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
void string_split(vector< string > &tokens, const string &str, const string &separators, bool skip_empty_tokens)
Definition: string.cpp:67
bool exists(ustring x) const
Definition: node_enum.h:28
ustring name
Definition: graph/node.h:174
bool is_a(const NodeType *type)
Definition: graph/node.cpp:758
ustring name
Definition: node_type.h:72
const NodeType * node_type
Definition: node_type.h:77
@ BOOLEAN_ARRAY
Definition: node_type.h:41
@ TRANSFORM_ARRAY
Definition: node_type.h:50
@ NODE_ARRAY
Definition: node_type.h:51
@ POINT2_ARRAY
Definition: node_type.h:48
@ FLOAT_ARRAY
Definition: node_type.h:42
@ NORMAL_ARRAY
Definition: node_type.h:47
@ VECTOR_ARRAY
Definition: node_type.h:45
@ POINT_ARRAY
Definition: node_type.h:46
@ STRING_ARRAY
Definition: node_type.h:49
@ COLOR_ARRAY
Definition: node_type.h:44
Type type
Definition: node_type.h:73
const NodeEnum * enum_values
Definition: node_type.h:76
int flags
Definition: node_type.h:78
map< ustring, Node * > node_map
Definition: node_xml.h:15
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x