Code refactor: add generic Cycles node infrastructure.
[blender-staging.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 "node.h"
18 #include "node_type.h"
19
20 #include "util_foreach.h"
21 #include "util_param.h"
22 #include "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         typedef unordered_map<ustring, SocketType, ustringHash> map_type;
40         foreach(const map_type::value_type& it, type->inputs) {
41                 const SocketType& socket = it.second;
42                 const void *src = socket.default_value;
43                 void *dst = ((char*)this) + socket.struct_offset;
44                 memcpy(dst, src, socket.size());
45         }
46 }
47
48 Node::~Node()
49 {
50 }
51
52 template<typename T>
53 static T& get_socket_value(const Node *node, const SocketType& socket)
54 {
55         return (T&)*(((char*)node) + socket.struct_offset);
56 }
57
58 static bool is_socket_float3(const SocketType& socket)
59 {
60         return socket.type == SocketType::COLOR ||
61                socket.type == SocketType::POINT ||
62                    socket.type == SocketType::VECTOR ||
63                    socket.type == SocketType::NORMAL;
64 }
65
66 static bool is_socket_array_float3(const SocketType& socket)
67 {
68         return socket.type == SocketType::COLOR_ARRAY ||
69                socket.type == SocketType::POINT_ARRAY ||
70                    socket.type == SocketType::VECTOR_ARRAY ||
71                    socket.type == SocketType::NORMAL_ARRAY;
72 }
73
74 /* set values */
75 void Node::set(const SocketType& input, bool value)
76 {
77         assert(input.type == SocketType::BOOLEAN);
78         get_socket_value<bool>(this, input) = value;
79 }
80
81 void Node::set(const SocketType& input, int value)
82 {
83         assert((input.type == SocketType::INT || input.type == SocketType::ENUM));
84         get_socket_value<int>(this, input) = value;
85 }
86
87 void Node::set(const SocketType& input, float value)
88 {
89         assert(input.type == SocketType::FLOAT);
90         get_socket_value<float>(this, input) = value;
91 }
92
93 void Node::set(const SocketType& input, float2 value)
94 {
95         assert(input.type == SocketType::FLOAT);
96         get_socket_value<float2>(this, input) = value;
97 }
98
99 void Node::set(const SocketType& input, float3 value)
100 {
101         assert(is_socket_float3(input));
102         get_socket_value<float3>(this, input) = value;
103 }
104
105 void Node::set(const SocketType& input, ustring value)
106 {
107         if(input.type == SocketType::STRING) {
108                 get_socket_value<ustring>(this, input) = value;
109         }
110         else if(input.type == SocketType::ENUM) {
111                 const NodeEnum& enm = *input.enum_values;
112                 if(enm.exists(value)) {
113                         get_socket_value<int>(this, input) = enm[value];
114                 }
115                 else {
116                         assert(0);
117                 }
118         }
119         else {
120                 assert(0);
121         }
122 }
123
124 void Node::set(const SocketType& input, const Transform& value)
125 {
126         assert(input.type == SocketType::TRANSFORM);
127         get_socket_value<Transform>(this, input) = value;
128 }
129
130 void Node::set(const SocketType& input, Node *value)
131 {
132         assert(input.type == SocketType::TRANSFORM);
133         get_socket_value<Node*>(this, input) = value;
134 }
135
136 /* set array values */
137 void Node::set(const SocketType& input, array<bool>& value)
138 {
139         assert(input.type == SocketType::BOOLEAN_ARRAY);
140         get_socket_value<array<bool> >(this, input).steal_data(value);
141 }
142
143 void Node::set(const SocketType& input, array<int>& value)
144 {
145         assert(input.type == SocketType::INT_ARRAY);
146         get_socket_value<array<int> >(this, input).steal_data(value);
147 }
148
149 void Node::set(const SocketType& input, array<float>& value)
150 {
151         assert(input.type == SocketType::FLOAT_ARRAY);
152         get_socket_value<array<float> >(this, input).steal_data(value);
153 }
154
155 void Node::set(const SocketType& input, array<float2>& value)
156 {
157         assert(input.type == SocketType::FLOAT_ARRAY);
158         get_socket_value<array<float2> >(this, input).steal_data(value);
159 }
160
161 void Node::set(const SocketType& input, array<float3>& value)
162 {
163         assert(is_socket_array_float3(input));
164         get_socket_value<array<float3> >(this, input).steal_data(value);
165 }
166
167 void Node::set(const SocketType& input, array<ustring>& value)
168 {
169         assert(input.type == SocketType::STRING_ARRAY);
170         get_socket_value<array<ustring> >(this, input).steal_data(value);
171 }
172
173 void Node::set(const SocketType& input, array<Transform>& value)
174 {
175         assert(input.type == SocketType::TRANSFORM_ARRAY);
176         get_socket_value<array<Transform> >(this, input).steal_data(value);
177 }
178
179 void Node::set(const SocketType& input, array<Node*>& value)
180 {
181         assert(input.type == SocketType::TRANSFORM_ARRAY);
182         get_socket_value<array<Node*> >(this, input).steal_data(value);
183 }
184
185 /* get values */
186 bool Node::get_bool(const SocketType& input) const
187 {
188         assert(input.type == SocketType::BOOLEAN);
189         return get_socket_value<bool>(this, input);
190 }
191
192 int Node::get_int(const SocketType& input) const
193 {
194         assert(input.type == SocketType::INT || input.type == SocketType::ENUM);
195         return get_socket_value<int>(this, input);
196 }
197
198 float Node::get_float(const SocketType& input) const
199 {
200         assert(input.type == SocketType::FLOAT);
201         return get_socket_value<float>(this, input);
202 }
203
204 float2 Node::get_float2(const SocketType& input) const
205 {
206         assert(input.type == SocketType::FLOAT);
207         return get_socket_value<float2>(this, input);
208 }
209
210 float3 Node::get_float3(const SocketType& input) const
211 {
212         assert(is_socket_float3(input));
213         return get_socket_value<float3>(this, input);
214 }
215
216 ustring Node::get_string(const SocketType& input) const
217 {
218         if(input.type == SocketType::STRING) {
219                 return get_socket_value<ustring>(this, input);
220         }
221         else if(input.type == SocketType::ENUM) {
222                 const NodeEnum& enm = *input.enum_values;
223                 int intvalue = get_socket_value<int>(this, input);
224                 return (enm.exists(intvalue)) ? enm[intvalue] : ustring();
225         }
226         else {
227                 assert(0);
228                 return ustring();
229         }
230 }
231
232 Transform Node::get_transform(const SocketType& input) const
233 {
234         assert(input.type == SocketType::TRANSFORM);
235         return get_socket_value<Transform>(this, input);
236 }
237
238 Node *Node::get_node(const SocketType& input) const
239 {
240         assert(input.type == SocketType::NODE);
241         return get_socket_value<Node*>(this, input);
242 }
243
244 /* get array values */
245 const array<bool>& Node::get_bool_array(const SocketType& input) const
246 {
247         assert(input.type == SocketType::BOOLEAN_ARRAY);
248         return get_socket_value<array<bool> >(this, input);
249 }
250
251 const array<int>& Node::get_int_array(const SocketType& input) const
252 {
253         assert(input.type == SocketType::INT_ARRAY);
254         return get_socket_value<array<int> >(this, input);
255 }
256
257 const array<float>& Node::get_float_array(const SocketType& input) const
258 {
259         assert(input.type == SocketType::FLOAT_ARRAY);
260         return get_socket_value<array<float> >(this, input);
261 }
262
263 const array<float2>& Node::get_float2_array(const SocketType& input) const
264 {
265         assert(input.type == SocketType::FLOAT_ARRAY);
266         return get_socket_value<array<float2> >(this, input);
267 }
268
269 const array<float3>& Node::get_float3_array(const SocketType& input) const
270 {
271         assert(is_socket_array_float3(input));
272         return get_socket_value<array<float3> >(this, input);
273 }
274
275 const array<ustring>& Node::get_string_array(const SocketType& input) const
276 {
277         assert(input.type == SocketType::STRING_ARRAY);
278         return get_socket_value<array<ustring> >(this, input);
279 }
280
281 const array<Transform>& Node::get_transform_array(const SocketType& input) const
282 {
283         assert(input.type == SocketType::TRANSFORM_ARRAY);
284         return get_socket_value<array<Transform> >(this, input);
285 }
286
287 const array<Node*>& Node::get_node_array(const SocketType& input) const
288 {
289         assert(input.type == SocketType::NODE_ARRAY);
290         return get_socket_value<array<Node*> >(this, input);
291 }
292
293 /* default values */
294 bool Node::has_default_value(const SocketType& input) const
295 {
296         const void *src = input.default_value;
297         void *dst = &get_socket_value<char>(this, input);
298         return memcmp(dst, src, input.size()) == 0;
299 }
300
301 template<typename T>
302 static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket)
303 {
304         const array<T>* a = (const array<T>*)(((char*)node) + socket.struct_offset);
305         const array<T>* b = (const array<T>*)(((char*)other) + socket.struct_offset);
306         return *a == *b;
307 }
308
309 /* modified */
310 bool Node::modified(const Node& other)
311 {
312         assert(type == other.type);
313
314         typedef unordered_map<ustring, SocketType, ustringHash> map_type;
315         foreach(const map_type::value_type& it, type->inputs) {
316                 const SocketType& socket = it.second;
317
318                 if(socket.is_array()) {
319                         bool equal = true;
320
321                         switch(socket.type)
322                         {
323                                 case SocketType::BOOLEAN_ARRAY: equal = is_array_equal<bool>(this, &other, socket); break;
324                                 case SocketType::FLOAT_ARRAY: equal = is_array_equal<float>(this, &other, socket); break;
325                                 case SocketType::INT_ARRAY: equal = is_array_equal<int>(this, &other, socket); break;
326                                 case SocketType::COLOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
327                                 case SocketType::VECTOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
328                                 case SocketType::POINT_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
329                                 case SocketType::NORMAL_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
330                                 case SocketType::POINT2_ARRAY: equal = is_array_equal<float2>(this, &other, socket); break;
331                                 case SocketType::STRING_ARRAY: equal = is_array_equal<ustring>(this, &other, socket); break;
332                                 case SocketType::TRANSFORM_ARRAY: equal = is_array_equal<Transform>(this, &other, socket); break;
333                                 case SocketType::NODE_ARRAY: equal = is_array_equal<void*>(this, &other, socket); break;
334                                 default: assert(0); break;
335                         }
336
337                         if(!equal) {
338                                 return true;
339                         }
340                 }
341                 else {
342                         const void *a = ((char*)this) + socket.struct_offset;
343                         const void *b = ((char*)&other) + socket.struct_offset;
344                         if(memcmp(a, b, socket.size()) != 0) {
345                                 return true;
346                         }
347                 }
348         }
349
350         return false;
351 }
352
353 CCL_NAMESPACE_END
354