10d91a1e4ef88b94f925c42ead1a38df7bd2d2ff
[blender.git] / intern / cycles / graph / node.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 "graph/node.h"
18 #include "graph/node_type.h"
19
20 #include "util/util_foreach.h"
21 #include "util/util_param.h"
22 #include "util/util_transform.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 /* Node Type */
27
28 Node::Node(const NodeType *type_, ustring name_)
29 : name(name_), type(type_)
30 {
31         assert(type);
32
33         /* assign non-empty name, convenient for debugging */
34         if(name.empty()) {
35                 name = type->name;
36         }
37
38         /* initialize default values */
39         foreach(const SocketType& socket, type->inputs) {
40                 set_default_value(socket);
41         }
42 }
43
44 Node::~Node()
45 {
46 }
47
48 template<typename T>
49 static T& get_socket_value(const Node *node, const SocketType& socket)
50 {
51         return (T&)*(((char*)node) + socket.struct_offset);
52 }
53
54 #ifndef NDEBUG
55 static bool is_socket_float3(const SocketType& socket)
56 {
57         return socket.type == SocketType::COLOR ||
58                socket.type == SocketType::POINT ||
59                    socket.type == SocketType::VECTOR ||
60                    socket.type == SocketType::NORMAL;
61 }
62
63 static bool is_socket_array_float3(const SocketType& socket)
64 {
65         return socket.type == SocketType::COLOR_ARRAY ||
66                socket.type == SocketType::POINT_ARRAY ||
67                    socket.type == SocketType::VECTOR_ARRAY ||
68                    socket.type == SocketType::NORMAL_ARRAY;
69 }
70 #endif
71
72 /* set values */
73 void Node::set(const SocketType& input, bool value)
74 {
75         assert(input.type == SocketType::BOOLEAN);
76         get_socket_value<bool>(this, input) = value;
77 }
78
79 void Node::set(const SocketType& input, int value)
80 {
81         assert((input.type == SocketType::INT || input.type == SocketType::ENUM));
82         get_socket_value<int>(this, input) = value;
83 }
84
85 void Node::set(const SocketType& input, uint value)
86 {
87         assert(input.type == SocketType::UINT);
88         get_socket_value<uint>(this, input) = value;
89 }
90
91 void Node::set(const SocketType& input, float value)
92 {
93         assert(input.type == SocketType::FLOAT);
94         get_socket_value<float>(this, input) = value;
95 }
96
97 void Node::set(const SocketType& input, float2 value)
98 {
99         assert(input.type == SocketType::FLOAT);
100         get_socket_value<float2>(this, input) = value;
101 }
102
103 void Node::set(const SocketType& input, float3 value)
104 {
105         assert(is_socket_float3(input));
106         get_socket_value<float3>(this, input) = value;
107 }
108
109 void Node::set(const SocketType& input, const char *value)
110 {
111         set(input, ustring(value));
112 }
113
114 void Node::set(const SocketType& input, ustring value)
115 {
116         if(input.type == SocketType::STRING) {
117                 get_socket_value<ustring>(this, input) = value;
118         }
119         else if(input.type == SocketType::ENUM) {
120                 const NodeEnum& enm = *input.enum_values;
121                 if(enm.exists(value)) {
122                         get_socket_value<int>(this, input) = enm[value];
123                 }
124                 else {
125                         assert(0);
126                 }
127         }
128         else {
129                 assert(0);
130         }
131 }
132
133 void Node::set(const SocketType& input, const Transform& value)
134 {
135         assert(input.type == SocketType::TRANSFORM);
136         get_socket_value<Transform>(this, input) = value;
137 }
138
139 void Node::set(const SocketType& input, Node *value)
140 {
141         assert(input.type == SocketType::TRANSFORM);
142         get_socket_value<Node*>(this, input) = value;
143 }
144
145 /* set array values */
146 void Node::set(const SocketType& input, array<bool>& value)
147 {
148         assert(input.type == SocketType::BOOLEAN_ARRAY);
149         get_socket_value<array<bool> >(this, input).steal_data(value);
150 }
151
152 void Node::set(const SocketType& input, array<int>& value)
153 {
154         assert(input.type == SocketType::INT_ARRAY);
155         get_socket_value<array<int> >(this, input).steal_data(value);
156 }
157
158 void Node::set(const SocketType& input, array<float>& value)
159 {
160         assert(input.type == SocketType::FLOAT_ARRAY);
161         get_socket_value<array<float> >(this, input).steal_data(value);
162 }
163
164 void Node::set(const SocketType& input, array<float2>& value)
165 {
166         assert(input.type == SocketType::FLOAT_ARRAY);
167         get_socket_value<array<float2> >(this, input).steal_data(value);
168 }
169
170 void Node::set(const SocketType& input, array<float3>& value)
171 {
172         assert(is_socket_array_float3(input));
173         get_socket_value<array<float3> >(this, input).steal_data(value);
174 }
175
176 void Node::set(const SocketType& input, array<ustring>& value)
177 {
178         assert(input.type == SocketType::STRING_ARRAY);
179         get_socket_value<array<ustring> >(this, input).steal_data(value);
180 }
181
182 void Node::set(const SocketType& input, array<Transform>& value)
183 {
184         assert(input.type == SocketType::TRANSFORM_ARRAY);
185         get_socket_value<array<Transform> >(this, input).steal_data(value);
186 }
187
188 void Node::set(const SocketType& input, array<Node*>& value)
189 {
190         assert(input.type == SocketType::TRANSFORM_ARRAY);
191         get_socket_value<array<Node*> >(this, input).steal_data(value);
192 }
193
194 /* get values */
195 bool Node::get_bool(const SocketType& input) const
196 {
197         assert(input.type == SocketType::BOOLEAN);
198         return get_socket_value<bool>(this, input);
199 }
200
201 int Node::get_int(const SocketType& input) const
202 {
203         assert(input.type == SocketType::INT || input.type == SocketType::ENUM);
204         return get_socket_value<int>(this, input);
205 }
206
207 uint Node::get_uint(const SocketType& input) const
208 {
209         assert(input.type == SocketType::UINT);
210         return get_socket_value<uint>(this, input);
211 }
212
213 float Node::get_float(const SocketType& input) const
214 {
215         assert(input.type == SocketType::FLOAT);
216         return get_socket_value<float>(this, input);
217 }
218
219 float2 Node::get_float2(const SocketType& input) const
220 {
221         assert(input.type == SocketType::FLOAT);
222         return get_socket_value<float2>(this, input);
223 }
224
225 float3 Node::get_float3(const SocketType& input) const
226 {
227         assert(is_socket_float3(input));
228         return get_socket_value<float3>(this, input);
229 }
230
231 ustring Node::get_string(const SocketType& input) const
232 {
233         if(input.type == SocketType::STRING) {
234                 return get_socket_value<ustring>(this, input);
235         }
236         else if(input.type == SocketType::ENUM) {
237                 const NodeEnum& enm = *input.enum_values;
238                 int intvalue = get_socket_value<int>(this, input);
239                 return (enm.exists(intvalue)) ? enm[intvalue] : ustring();
240         }
241         else {
242                 assert(0);
243                 return ustring();
244         }
245 }
246
247 Transform Node::get_transform(const SocketType& input) const
248 {
249         assert(input.type == SocketType::TRANSFORM);
250         return get_socket_value<Transform>(this, input);
251 }
252
253 Node *Node::get_node(const SocketType& input) const
254 {
255         assert(input.type == SocketType::NODE);
256         return get_socket_value<Node*>(this, input);
257 }
258
259 /* get array values */
260 const array<bool>& Node::get_bool_array(const SocketType& input) const
261 {
262         assert(input.type == SocketType::BOOLEAN_ARRAY);
263         return get_socket_value<array<bool> >(this, input);
264 }
265
266 const array<int>& Node::get_int_array(const SocketType& input) const
267 {
268         assert(input.type == SocketType::INT_ARRAY);
269         return get_socket_value<array<int> >(this, input);
270 }
271
272 const array<float>& Node::get_float_array(const SocketType& input) const
273 {
274         assert(input.type == SocketType::FLOAT_ARRAY);
275         return get_socket_value<array<float> >(this, input);
276 }
277
278 const array<float2>& Node::get_float2_array(const SocketType& input) const
279 {
280         assert(input.type == SocketType::FLOAT_ARRAY);
281         return get_socket_value<array<float2> >(this, input);
282 }
283
284 const array<float3>& Node::get_float3_array(const SocketType& input) const
285 {
286         assert(is_socket_array_float3(input));
287         return get_socket_value<array<float3> >(this, input);
288 }
289
290 const array<ustring>& Node::get_string_array(const SocketType& input) const
291 {
292         assert(input.type == SocketType::STRING_ARRAY);
293         return get_socket_value<array<ustring> >(this, input);
294 }
295
296 const array<Transform>& Node::get_transform_array(const SocketType& input) const
297 {
298         assert(input.type == SocketType::TRANSFORM_ARRAY);
299         return get_socket_value<array<Transform> >(this, input);
300 }
301
302 const array<Node*>& Node::get_node_array(const SocketType& input) const
303 {
304         assert(input.type == SocketType::NODE_ARRAY);
305         return get_socket_value<array<Node*> >(this, input);
306 }
307
308 /* generic value operations */
309
310 bool Node::has_default_value(const SocketType& input) const
311 {
312         const void *src = input.default_value;
313         void *dst = &get_socket_value<char>(this, input);
314         return memcmp(dst, src, input.size()) == 0;
315 }
316
317 void Node::set_default_value(const SocketType& socket)
318 {
319         const void *src = socket.default_value;
320         void *dst = ((char*)this) + socket.struct_offset;
321         memcpy(dst, src, socket.size());
322 }
323
324 template<typename T>
325 static void copy_array(const Node *node, const SocketType& socket, const Node *other, const SocketType& other_socket)
326 {
327         const array<T>* src = (const array<T>*)(((char*)other) + other_socket.struct_offset);
328         array<T>* dst = (array<T>*)(((char*)node) + socket.struct_offset);
329         *dst = *src;
330 }
331
332 void Node::copy_value(const SocketType& socket, const Node& other, const SocketType& other_socket)
333 {
334         assert(socket.type == other_socket.type);
335
336         if(socket.is_array()) {
337                 switch(socket.type) {
338                         case SocketType::BOOLEAN_ARRAY: copy_array<bool>(this, socket, &other, other_socket); break;
339                         case SocketType::FLOAT_ARRAY: copy_array<float>(this, socket, &other, other_socket); break;
340                         case SocketType::INT_ARRAY: copy_array<int>(this, socket, &other, other_socket); break;
341                         case SocketType::COLOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
342                         case SocketType::VECTOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
343                         case SocketType::POINT_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
344                         case SocketType::NORMAL_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
345                         case SocketType::POINT2_ARRAY: copy_array<float2>(this, socket, &other, other_socket); break;
346                         case SocketType::STRING_ARRAY: copy_array<ustring>(this, socket, &other, other_socket); break;
347                         case SocketType::TRANSFORM_ARRAY: copy_array<Transform>(this, socket, &other, other_socket); break;
348                         case SocketType::NODE_ARRAY: copy_array<void*>(this, socket, &other, other_socket); break;
349                         default: assert(0); break;
350                 }
351         }
352         else {
353                 const void *src = ((char*)&other) + other_socket.struct_offset;
354                 void *dst = ((char*)this) + socket.struct_offset;
355                 memcpy(dst, src, socket.size());
356         }
357 }
358
359 template<typename T>
360 static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket)
361 {
362         const array<T>* a = (const array<T>*)(((char*)node) + socket.struct_offset);
363         const array<T>* b = (const array<T>*)(((char*)other) + socket.struct_offset);
364         return *a == *b;
365 }
366
367 bool Node::equals_value(const Node& other, const SocketType& socket) const
368 {
369         if(socket.is_array()) {
370                 switch(socket.type) {
371                         case SocketType::BOOLEAN_ARRAY: return is_array_equal<bool>(this, &other, socket);
372                         case SocketType::FLOAT_ARRAY: return is_array_equal<float>(this, &other, socket);
373                         case SocketType::INT_ARRAY: return is_array_equal<int>(this, &other, socket);
374                         case SocketType::COLOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
375                         case SocketType::VECTOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
376                         case SocketType::POINT_ARRAY: return is_array_equal<float3>(this, &other, socket);
377                         case SocketType::NORMAL_ARRAY: return is_array_equal<float3>(this, &other, socket);
378                         case SocketType::POINT2_ARRAY: return is_array_equal<float2>(this, &other, socket);
379                         case SocketType::STRING_ARRAY: return is_array_equal<ustring>(this, &other, socket);
380                         case SocketType::TRANSFORM_ARRAY: return is_array_equal<Transform>(this, &other, socket);
381                         case SocketType::NODE_ARRAY: return is_array_equal<void*>(this, &other, socket);
382                         default: assert(0); return true;
383                 }
384         }
385         else {
386                 const void *a = ((char*)this) + socket.struct_offset;
387                 const void *b = ((char*)&other) + socket.struct_offset;
388                 return (memcmp(a, b, socket.size()) == 0);
389         }
390 }
391
392 /* equals */
393
394 bool Node::equals(const Node& other) const
395 {
396         assert(type == other.type);
397
398         foreach(const SocketType& socket, type->inputs) {
399                 if(!equals_value(other, socket))
400                         return false;
401         }
402
403         return true;
404 }
405
406 CCL_NAMESPACE_END
407