Code refactor: add generic Cycles XML node read and write functions.
[blender.git] / intern / cycles / graph / node_xml.cpp
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "node_xml.h"
18
19 #include "util_foreach.h"
20 #include "util_string.h"
21 #include "util_transform.h"
22
23 CCL_NAMESPACE_BEGIN
24
25 static bool xml_read_boolean(const char *value)
26 {
27         return string_iequals(value, "true") || (atoi(value) != 0);
28 }
29
30 static const char *xml_write_boolean(bool value)
31 {
32         return (value) ? "true" : "false";
33 }
34
35 template<int VECTOR_SIZE, typename T>
36 static void xml_read_float_array(T& value, pugi::xml_attribute attr)
37 {
38         vector<string> tokens;
39         string_split(tokens, attr.value());
40
41         if(tokens.size() % VECTOR_SIZE != 0) {
42                 return;
43         }
44
45         value.resize(tokens.size() / VECTOR_SIZE);
46         for(size_t i = 0; i < value.size(); i++) {
47                 float *value_float = (float*)&value[i];
48
49                 for(size_t j = 0; j < VECTOR_SIZE; j++)
50                         value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str());
51         }
52 }
53
54 void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
55 {
56         pugi::xml_attribute name_attr = xml_node.attribute("name");
57         if(name_attr) {
58                 node->name = ustring(name_attr.value());
59         }
60
61         foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
62                 const SocketType& socket = it.second;
63
64                 if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
65                         continue;
66                 }
67                 if(socket.flags & SocketType::INTERNAL) {
68                         continue;
69                 }
70
71                 pugi::xml_attribute attr = xml_node.attribute(socket.name.c_str());
72
73                 if(!attr) {
74                         continue;
75                 }
76
77                 switch(socket.type)
78                 {
79                         case SocketType::BOOLEAN:
80                         {
81                                 node->set(socket, xml_read_boolean(attr.value()));
82                                 break;
83                         }
84                         case SocketType::BOOLEAN_ARRAY:
85                         {
86                                 vector<string> tokens;
87                                 string_split(tokens, attr.value());
88
89                                 array<bool> value;
90                                 value.resize(tokens.size());
91                                 for(size_t i = 0; i < value.size(); i++)
92                                         value[i] = xml_read_boolean(tokens[i].c_str());
93                                 node->set(socket, value);
94                                 break;
95                         }
96                         case SocketType::FLOAT:
97                         {
98                                 node->set(socket, (float)atof(attr.value()));
99                                 break;
100                         }
101                         case SocketType::FLOAT_ARRAY:
102                         {
103                                 array<float> value;
104                                 xml_read_float_array<1>(value, attr);
105                                 node->set(socket, value);
106                                 break;
107                         }
108                         case SocketType::INT:
109                         {
110                                 node->set(socket, (int)atoi(attr.value()));
111                                 break;
112                         }
113                         case SocketType::INT_ARRAY:
114                         {
115                                 vector<string> tokens;
116                                 string_split(tokens, attr.value());
117
118                                 array<int> value;
119                                 value.resize(tokens.size());
120                                 for(size_t i = 0; i < value.size(); i++)
121                                         value[i] = (int)atoi(attr.value());
122                                 node->set(socket, value);
123                                 break;
124                         }
125                         case SocketType::COLOR:
126                         case SocketType::VECTOR:
127                         case SocketType::POINT:
128                         case SocketType::NORMAL:
129                         {
130                                 array<float> value;
131                                 xml_read_float_array<3>(value, attr);
132                                 if(value.size() == 1) {
133                                         node->set(socket, value[0]);
134                                 }
135                                 break;
136                         }
137                         case SocketType::COLOR_ARRAY:
138                         case SocketType::VECTOR_ARRAY:
139                         case SocketType::POINT_ARRAY:
140                         case SocketType::NORMAL_ARRAY:
141                         {
142                                 array<float3> value;
143                                 xml_read_float_array<3>(value, attr);
144                                 node->set(socket, value);
145                                 break;
146                         }
147                         case SocketType::POINT2:
148                         {
149                                 array<float2> value;
150                                 xml_read_float_array<2>(value, attr);
151                                 if(value.size() == 1) {
152                                         node->set(socket, value[0]);
153                                 }
154                                 break;
155                         }
156                         case SocketType::POINT2_ARRAY:
157                         {
158                                 array<float2> value;
159                                 xml_read_float_array<2>(value, attr);
160                                 node->set(socket, value);
161                                 break;
162                         }
163                         case SocketType::STRING:
164                         case SocketType::ENUM:
165                         {
166                                 node->set(socket, attr.value());
167                                 break;
168                         }
169                         case SocketType::STRING_ARRAY:
170                         {
171                                 vector<string> tokens;
172                                 string_split(tokens, attr.value());
173
174                                 array<ustring> value;
175                                 value.resize(tokens.size());
176                                 for(size_t i = 0; i < value.size(); i++)
177                                         value[i] = ustring(tokens[i]);
178                                 node->set(socket, value);
179                                 break;
180                         }
181                         case SocketType::TRANSFORM:
182                         {
183                                 array<Transform> value;
184                                 xml_read_float_array<16>(value, attr);
185                                 if(value.size() == 1) {
186                                         node->set(socket, value[0]);
187                                 }
188                                 break;
189                         }
190                         case SocketType::TRANSFORM_ARRAY:
191                         {
192                                 array<Transform> value;
193                                 xml_read_float_array<16>(value, attr);
194                                 node->set(socket, value);
195                                 break;
196                         }
197                         case SocketType::NODE:
198                         {
199                                 ustring value(attr.value());
200                                 map<ustring, Node*>::iterator it = reader.node_map.find(value);
201                                 if(it != reader.node_map.end())
202                                 {
203                                         Node *value_node = it->second;
204                                         if(value_node->type == *(socket.node_type))
205                                                 node->set(socket, it->second);
206                                 }
207                                 break;
208                         }
209                         case SocketType::NODE_ARRAY:
210                         {
211                                 vector<string> tokens;
212                                 string_split(tokens, attr.value());
213
214                                 array<Node*> value;
215                                 value.resize(tokens.size());
216                                 for(size_t i = 0; i < value.size(); i++)
217                                 {
218                                         map<ustring, Node*>::iterator it = reader.node_map.find(ustring(tokens[i]));
219                                         if(it != reader.node_map.end())
220                                         {
221                                                 Node *value_node = it->second;
222                                                 value[i] = (value_node->type == *(socket.node_type)) ? value_node : NULL;
223                                         }
224                                         else
225                                         {
226                                                 value[i] = NULL;
227                                         }
228                                 }
229                                 node->set(socket, value);
230                                 break;
231                         }
232                         case SocketType::CLOSURE:
233                         case SocketType::UNDEFINED:
234                                 break;
235                 }
236         }
237
238         if(node->name)
239                 reader.node_map[node->name] = node;
240 }
241
242 pugi::xml_node xml_write_node(Node *node, pugi::xml_node xml_root)
243 {
244         pugi::xml_node xml_node = xml_root.append_child(node->type->name.c_str());
245
246         xml_node.append_attribute("name") = node->name.c_str();
247
248         foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
249                 const SocketType& socket = it.second;
250
251                 if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
252                         continue;
253                 }
254                 if(socket.flags & SocketType::INTERNAL) {
255                         continue;
256                 }
257                 if(node->has_default_value(socket)) {
258                         continue;
259                 }
260
261                 pugi::xml_attribute attr = xml_node.append_attribute(socket.name.c_str());
262
263                 switch(socket.type)
264                 {
265                         case SocketType::BOOLEAN:
266                         {
267                                 attr = xml_write_boolean(node->get_bool(socket));
268                                 break;
269                         }
270                         case SocketType::BOOLEAN_ARRAY:
271                         {
272                                 std::stringstream ss;
273                                 const array<bool>& value = node->get_bool_array(socket);
274                                 for(size_t i = 0; i < value.size(); i++) {
275                                         ss << xml_write_boolean(value[i]);
276                                         if(i != value.size() - 1)
277                                                 ss << " ";
278                                 }
279                                 attr = ss.str().c_str();
280                                 break;
281                         }
282                         case SocketType::FLOAT:
283                         {
284                                 attr = node->get_float(socket);
285                                 break;
286                         }
287                         case SocketType::FLOAT_ARRAY:
288                         {
289                                 std::stringstream ss;
290                                 const array<float>& value = node->get_float_array(socket);
291                                 for(size_t i = 0; i < value.size(); i++) {
292                                         ss << value[i];
293                                         if(i != value.size() - 1) {
294                                                 ss << " ";
295                                         }
296                                 }
297                                 attr = ss.str().c_str();
298                                 break;
299                         }
300                         case SocketType::INT:
301                         {
302                                 attr = node->get_int(socket);
303                                 break;
304                         }
305                         case SocketType::INT_ARRAY:
306                         {
307                                 std::stringstream ss;
308                                 const array<int>& value = node->get_int_array(socket);
309                                 for(size_t i = 0; i < value.size(); i++) {
310                                         ss << value[i];
311                                         if(i != value.size() - 1) {
312                                                 ss << " ";
313                                         }
314                                 }
315                                 attr = ss.str().c_str();
316                                 break;
317                         }
318                         case SocketType::COLOR:
319                         case SocketType::VECTOR:
320                         case SocketType::POINT:
321                         case SocketType::NORMAL:
322                         {
323                                 float3 value = node->get_float3(socket);
324                                 attr = string_printf("%g %g %g", value.x, value.y, value.z).c_str();
325                                 break;
326                         }
327                         case SocketType::COLOR_ARRAY:
328                         case SocketType::VECTOR_ARRAY:
329                         case SocketType::POINT_ARRAY:
330                         case SocketType::NORMAL_ARRAY:
331                         {
332                                 std::stringstream ss;
333                                 const array<float3>& value = node->get_float3_array(socket);
334                                 for(size_t i = 0; i < value.size(); i++) {
335                                         ss << string_printf("%g %g %g", value[i].x, value[i].y, value[i].z);
336                                         if(i != value.size() - 1) {
337                                                 ss << " ";
338                                         }
339                                 }
340                                 attr = ss.str().c_str();
341                                 break;
342                         }
343                         case SocketType::POINT2:
344                         {
345                                 float2 value = node->get_float2(socket);
346                                 attr = string_printf("%g %g", value.x, value.y).c_str();
347                                 break;
348                         }
349                         case SocketType::POINT2_ARRAY:
350                         {
351                                 std::stringstream ss;
352                                 const array<float2>& value = node->get_float2_array(socket);
353                                 for(size_t i = 0; i < value.size(); i++) {
354                                         ss << string_printf("%g %g", value[i].x, value[i].y);
355                                         if(i != value.size() - 1) {
356                                                 ss << " ";
357                                         }
358                                 }
359                                 attr = ss.str().c_str();
360                                 break;
361                         }
362                         case SocketType::STRING:
363                         case SocketType::ENUM:
364                         {
365                                 attr = node->get_string(socket).c_str();
366                                 break;
367                         }
368                         case SocketType::STRING_ARRAY:
369                         {
370                                 std::stringstream ss;
371                                 const array<ustring>& value = node->get_string_array(socket);
372                                 for(size_t i = 0; i < value.size(); i++) {
373                                         ss << value[i];
374                                         if(i != value.size() - 1) {
375                                                 ss << " ";
376                                         }
377                                 }
378                                 attr = ss.str().c_str();
379                                 break;
380                         }
381                         case SocketType::TRANSFORM:
382                         {
383                                 Transform tfm = node->get_transform(socket);
384                                 std::stringstream ss;
385                                 for(int i = 0; i < 4; i++) {
386                                         ss << string_printf("%g %g %g %g", tfm[i][0], tfm[i][1], tfm[i][2], tfm[i][3]);
387                                         if(i != 3) {
388                                                 ss << " ";
389                                         }
390                                 }
391                                 attr = ss.str().c_str();
392                                 break;
393                         }
394                         case SocketType::TRANSFORM_ARRAY:
395                         {
396                                 std::stringstream ss;
397                                 const array<Transform>& value = node->get_transform_array(socket);
398                                 for(size_t j = 0; j < value.size(); j++) {
399                                         const Transform& tfm = value[j];
400
401                                         for(int i = 0; i < 4; i++) {
402                                                 ss << string_printf("%g %g %g %g", tfm[i][0], tfm[i][1], tfm[i][2], tfm[i][3]);
403                                                 if(j != value.size() - 1 || i != 3) {
404                                                         ss << " ";
405                                                 }
406                                         }
407                                 }
408                                 attr = ss.str().c_str();
409                                 break;
410                         }
411                         case SocketType::NODE:
412                         {
413                                 Node *value = node->get_node(socket);
414                                 if(value) {
415                                         attr = value->name.c_str();
416                                 }
417                                 break;
418                         }
419                         case SocketType::NODE_ARRAY:
420                         {
421                                 std::stringstream ss;
422                                 const array<Node*>& value = node->get_node_array(socket);
423                                 for(size_t i = 0; i < value.size(); i++) {
424                                         if(value[i]) {
425                                                 ss << value[i]->name.c_str();
426                                         }
427                                         if(i != value.size() - 1) {
428                                                 ss << " ";
429                                         }
430                                 }
431                                 attr = ss.str().c_str();
432                                 break;
433                         }
434                         case SocketType::CLOSURE:
435                         case SocketType::UNDEFINED:
436                                 break;
437                 }
438         }
439
440         return xml_node;
441 }
442
443 CCL_NAMESPACE_END
444