Fix T48604: Crash on undo due to bad drawing code.
[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 SocketType& socket, node->type->inputs) {
62                 if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
63                         continue;
64                 }
65                 if(socket.flags & SocketType::INTERNAL) {
66                         continue;
67                 }
68
69                 pugi::xml_attribute attr = xml_node.attribute(socket.name.c_str());
70
71                 if(!attr) {
72                         continue;
73                 }
74
75                 switch(socket.type)
76                 {
77                         case SocketType::BOOLEAN:
78                         {
79                                 node->set(socket, xml_read_boolean(attr.value()));
80                                 break;
81                         }
82                         case SocketType::BOOLEAN_ARRAY:
83                         {
84                                 vector<string> tokens;
85                                 string_split(tokens, attr.value());
86
87                                 array<bool> value;
88                                 value.resize(tokens.size());
89                                 for(size_t i = 0; i < value.size(); i++)
90                                         value[i] = xml_read_boolean(tokens[i].c_str());
91                                 node->set(socket, value);
92                                 break;
93                         }
94                         case SocketType::FLOAT:
95                         {
96                                 node->set(socket, (float)atof(attr.value()));
97                                 break;
98                         }
99                         case SocketType::FLOAT_ARRAY:
100                         {
101                                 array<float> value;
102                                 xml_read_float_array<1>(value, attr);
103                                 node->set(socket, value);
104                                 break;
105                         }
106                         case SocketType::INT:
107                         {
108                                 node->set(socket, (int)atoi(attr.value()));
109                                 break;
110                         }
111                         case SocketType::INT_ARRAY:
112                         {
113                                 vector<string> tokens;
114                                 string_split(tokens, attr.value());
115
116                                 array<int> value;
117                                 value.resize(tokens.size());
118                                 for(size_t i = 0; i < value.size(); i++) {
119                                         value[i] = (int)atoi(attr.value());
120                                 }
121                                 node->set(socket, value);
122                                 break;
123                         }
124                         case SocketType::COLOR:
125                         case SocketType::VECTOR:
126                         case SocketType::POINT:
127                         case SocketType::NORMAL:
128                         {
129                                 array<float3> value;
130                                 xml_read_float_array<3>(value, attr);
131                                 if(value.size() == 1) {
132                                         node->set(socket, value[0]);
133                                 }
134                                 break;
135                         }
136                         case SocketType::COLOR_ARRAY:
137                         case SocketType::VECTOR_ARRAY:
138                         case SocketType::POINT_ARRAY:
139                         case SocketType::NORMAL_ARRAY:
140                         {
141                                 array<float3> value;
142                                 xml_read_float_array<3>(value, attr);
143                                 node->set(socket, value);
144                                 break;
145                         }
146                         case SocketType::POINT2:
147                         {
148                                 array<float2> value;
149                                 xml_read_float_array<2>(value, attr);
150                                 if(value.size() == 1) {
151                                         node->set(socket, value[0]);
152                                 }
153                                 break;
154                         }
155                         case SocketType::POINT2_ARRAY:
156                         {
157                                 array<float2> value;
158                                 xml_read_float_array<2>(value, attr);
159                                 node->set(socket, value);
160                                 break;
161                         }
162                         case SocketType::STRING:
163                         {
164                                 node->set(socket, attr.value());
165                                 break;
166                         }
167                         case SocketType::ENUM:
168                         {
169                                 ustring value(attr.value());
170                                 if(socket.enum_values->exists(value)) {
171                                         node->set(socket, value);
172                                 }
173                                 else {
174                                         fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", value.c_str(), socket.name.c_str());
175                                 }
176                                 break;
177                         }
178                         case SocketType::STRING_ARRAY:
179                         {
180                                 vector<string> tokens;
181                                 string_split(tokens, attr.value());
182
183                                 array<ustring> value;
184                                 value.resize(tokens.size());
185                                 for(size_t i = 0; i < value.size(); i++) {
186                                         value[i] = ustring(tokens[i]);
187                                 }
188                                 node->set(socket, value);
189                                 break;
190                         }
191                         case SocketType::TRANSFORM:
192                         {
193                                 array<Transform> value;
194                                 xml_read_float_array<16>(value, attr);
195                                 if(value.size() == 1) {
196                                         node->set(socket, value[0]);
197                                 }
198                                 break;
199                         }
200                         case SocketType::TRANSFORM_ARRAY:
201                         {
202                                 array<Transform> value;
203                                 xml_read_float_array<16>(value, attr);
204                                 node->set(socket, value);
205                                 break;
206                         }
207                         case SocketType::NODE:
208                         {
209                                 ustring value(attr.value());
210                                 map<ustring, Node*>::iterator it = reader.node_map.find(value);
211                                 if(it != reader.node_map.end())
212                                 {
213                                         Node *value_node = it->second;
214                                         if(value_node->type == *(socket.node_type))
215                                                 node->set(socket, it->second);
216                                 }
217                                 break;
218                         }
219                         case SocketType::NODE_ARRAY:
220                         {
221                                 vector<string> tokens;
222                                 string_split(tokens, attr.value());
223
224                                 array<Node*> value;
225                                 value.resize(tokens.size());
226                                 for(size_t i = 0; i < value.size(); i++)
227                                 {
228                                         map<ustring, Node*>::iterator it = reader.node_map.find(ustring(tokens[i]));
229                                         if(it != reader.node_map.end())
230                                         {
231                                                 Node *value_node = it->second;
232                                                 value[i] = (value_node->type == *(socket.node_type)) ? value_node : NULL;
233                                         }
234                                         else
235                                         {
236                                                 value[i] = NULL;
237                                         }
238                                 }
239                                 node->set(socket, value);
240                                 break;
241                         }
242                         case SocketType::CLOSURE:
243                         case SocketType::UNDEFINED:
244                                 break;
245                 }
246         }
247
248         if(node->name)
249                 reader.node_map[node->name] = node;
250 }
251
252 pugi::xml_node xml_write_node(Node *node, pugi::xml_node xml_root)
253 {
254         pugi::xml_node xml_node = xml_root.append_child(node->type->name.c_str());
255
256         xml_node.append_attribute("name") = node->name.c_str();
257
258         foreach(const SocketType& socket, node->type->inputs) {
259                 if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
260                         continue;
261                 }
262                 if(socket.flags & SocketType::INTERNAL) {
263                         continue;
264                 }
265                 if(node->has_default_value(socket)) {
266                         continue;
267                 }
268
269                 pugi::xml_attribute attr = xml_node.append_attribute(socket.name.c_str());
270
271                 switch(socket.type)
272                 {
273                         case SocketType::BOOLEAN:
274                         {
275                                 attr = xml_write_boolean(node->get_bool(socket));
276                                 break;
277                         }
278                         case SocketType::BOOLEAN_ARRAY:
279                         {
280                                 std::stringstream ss;
281                                 const array<bool>& value = node->get_bool_array(socket);
282                                 for(size_t i = 0; i < value.size(); i++) {
283                                         ss << xml_write_boolean(value[i]);
284                                         if(i != value.size() - 1)
285                                                 ss << " ";
286                                 }
287                                 attr = ss.str().c_str();
288                                 break;
289                         }
290                         case SocketType::FLOAT:
291                         {
292                                 attr = (double)node->get_float(socket);
293                                 break;
294                         }
295                         case SocketType::FLOAT_ARRAY:
296                         {
297                                 std::stringstream ss;
298                                 const array<float>& value = node->get_float_array(socket);
299                                 for(size_t i = 0; i < value.size(); i++) {
300                                         ss << value[i];
301                                         if(i != value.size() - 1) {
302                                                 ss << " ";
303                                         }
304                                 }
305                                 attr = ss.str().c_str();
306                                 break;
307                         }
308                         case SocketType::INT:
309                         {
310                                 attr = node->get_int(socket);
311                                 break;
312                         }
313                         case SocketType::INT_ARRAY:
314                         {
315                                 std::stringstream ss;
316                                 const array<int>& value = node->get_int_array(socket);
317                                 for(size_t i = 0; i < value.size(); i++) {
318                                         ss << value[i];
319                                         if(i != value.size() - 1) {
320                                                 ss << " ";
321                                         }
322                                 }
323                                 attr = ss.str().c_str();
324                                 break;
325                         }
326                         case SocketType::COLOR:
327                         case SocketType::VECTOR:
328                         case SocketType::POINT:
329                         case SocketType::NORMAL:
330                         {
331                                 float3 value = node->get_float3(socket);
332                                 attr = string_printf("%g %g %g", (double)value.x, (double)value.y, (double)value.z).c_str();
333                                 break;
334                         }
335                         case SocketType::COLOR_ARRAY:
336                         case SocketType::VECTOR_ARRAY:
337                         case SocketType::POINT_ARRAY:
338                         case SocketType::NORMAL_ARRAY:
339                         {
340                                 std::stringstream ss;
341                                 const array<float3>& value = node->get_float3_array(socket);
342                                 for(size_t i = 0; i < value.size(); i++) {
343                                         ss << string_printf("%g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z);
344                                         if(i != value.size() - 1) {
345                                                 ss << " ";
346                                         }
347                                 }
348                                 attr = ss.str().c_str();
349                                 break;
350                         }
351                         case SocketType::POINT2:
352                         {
353                                 float2 value = node->get_float2(socket);
354                                 attr = string_printf("%g %g", (double)value.x, (double)value.y).c_str();
355                                 break;
356                         }
357                         case SocketType::POINT2_ARRAY:
358                         {
359                                 std::stringstream ss;
360                                 const array<float2>& value = node->get_float2_array(socket);
361                                 for(size_t i = 0; i < value.size(); i++) {
362                                         ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y);
363                                         if(i != value.size() - 1) {
364                                                 ss << " ";
365                                         }
366                                 }
367                                 attr = ss.str().c_str();
368                                 break;
369                         }
370                         case SocketType::STRING:
371                         case SocketType::ENUM:
372                         {
373                                 attr = node->get_string(socket).c_str();
374                                 break;
375                         }
376                         case SocketType::STRING_ARRAY:
377                         {
378                                 std::stringstream ss;
379                                 const array<ustring>& value = node->get_string_array(socket);
380                                 for(size_t i = 0; i < value.size(); i++) {
381                                         ss << value[i];
382                                         if(i != value.size() - 1) {
383                                                 ss << " ";
384                                         }
385                                 }
386                                 attr = ss.str().c_str();
387                                 break;
388                         }
389                         case SocketType::TRANSFORM:
390                         {
391                                 Transform tfm = node->get_transform(socket);
392                                 std::stringstream ss;
393                                 for(int i = 0; i < 4; i++) {
394                                         ss << string_printf("%g %g %g %g", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]);
395                                         if(i != 3) {
396                                                 ss << " ";
397                                         }
398                                 }
399                                 attr = ss.str().c_str();
400                                 break;
401                         }
402                         case SocketType::TRANSFORM_ARRAY:
403                         {
404                                 std::stringstream ss;
405                                 const array<Transform>& value = node->get_transform_array(socket);
406                                 for(size_t j = 0; j < value.size(); j++) {
407                                         const Transform& tfm = value[j];
408
409                                         for(int i = 0; i < 4; i++) {
410                                                 ss << string_printf("%g %g %g %g", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]);
411                                                 if(j != value.size() - 1 || i != 3) {
412                                                         ss << " ";
413                                                 }
414                                         }
415                                 }
416                                 attr = ss.str().c_str();
417                                 break;
418                         }
419                         case SocketType::NODE:
420                         {
421                                 Node *value = node->get_node(socket);
422                                 if(value) {
423                                         attr = value->name.c_str();
424                                 }
425                                 break;
426                         }
427                         case SocketType::NODE_ARRAY:
428                         {
429                                 std::stringstream ss;
430                                 const array<Node*>& value = node->get_node_array(socket);
431                                 for(size_t i = 0; i < value.size(); i++) {
432                                         if(value[i]) {
433                                                 ss << value[i]->name.c_str();
434                                         }
435                                         if(i != value.size() - 1) {
436                                                 ss << " ";
437                                         }
438                                 }
439                                 attr = ss.str().c_str();
440                                 break;
441                         }
442                         case SocketType::CLOSURE:
443                         case SocketType::UNDEFINED:
444                                 break;
445                 }
446         }
447
448         return xml_node;
449 }
450
451 CCL_NAMESPACE_END
452