Fix T39597: Missing entries in VSE Preview menu
[blender.git] / source / blender / nodes / intern / node_util.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Nathan Letwory.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/intern/node_util.c
29  *  \ingroup nodes
30  */
31
32 #include <limits.h>
33 #include <string.h>
34
35 #include "DNA_action_types.h"
36 #include "DNA_node_types.h"
37
38 #include "BLI_listbase.h"
39 #include "BLI_string.h"
40 #include "BLI_utildefines.h"
41
42 #include "BLF_translation.h"
43
44 #include "BKE_colortools.h"
45 #include "BKE_node.h"
46
47 #include "RNA_access.h"
48 #include "RNA_enum_types.h"
49
50 #include "MEM_guardedalloc.h"
51
52 #include "node_util.h"
53
54 /**** Storage Data ****/
55
56 void node_free_curves(bNode *node)
57 {
58         curvemapping_free(node->storage);
59 }
60
61 void node_free_standard_storage(bNode *node)
62 {
63         if (node->storage) {
64                 MEM_freeN(node->storage);
65         }
66 }
67
68 void node_copy_curves(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
69 {
70         dest_node->storage = curvemapping_copy(src_node->storage);
71 }
72
73 void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
74 {
75         dest_node->storage = MEM_dupallocN(src_node->storage);
76 }
77
78 void *node_initexec_curves(bNodeExecContext *UNUSED(context), bNode *node, bNodeInstanceKey UNUSED(key))
79 {
80         curvemapping_initialize(node->storage);
81         return NULL;  /* unused return */
82 }
83
84
85 /**** Labels ****/
86
87 void node_blend_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
88 {
89         const char *name;
90         RNA_enum_name(ramp_blend_items, node->custom1, &name);
91         BLI_strncpy(label, IFACE_(name), maxlen);
92 }
93
94 void node_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
95 {
96         const char *name;
97         RNA_enum_name(node_math_items, node->custom1, &name);
98         BLI_strncpy(label, IFACE_(name), maxlen);
99 }
100
101 void node_vect_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
102 {
103         const char *name;
104         RNA_enum_name(node_vec_math_items, node->custom1, &name);
105         BLI_strncpy(label, IFACE_(name), maxlen);
106 }
107
108 void node_filter_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
109 {
110         const char *name;
111         RNA_enum_name(node_filter_items, node->custom1, &name);
112         BLI_strncpy(label, IFACE_(name), maxlen);
113 }
114
115
116 /**** Internal Links (mute and disconnect) ****/
117
118 /* common datatype priorities, works for compositor, shader and texture nodes alike
119  * defines priority of datatype connection based on output type (to):
120  *   < 0  : never connect these types
121  *   >= 0 : priority of connection (higher values chosen first)
122  */
123 static int node_datatype_priority(eNodeSocketDatatype from, eNodeSocketDatatype to)
124 {
125         switch (to) {
126                 case SOCK_RGBA:
127                         switch (from) {
128                                 case SOCK_RGBA:     return 4;
129                                 case SOCK_FLOAT:    return 3;
130                                 case SOCK_INT:      return 2;
131                                 case SOCK_BOOLEAN:  return 1;
132                                 default: return -1;
133                         }
134                 case SOCK_VECTOR:
135                         switch (from) {
136                                 case SOCK_VECTOR:   return 4;
137                                 case SOCK_FLOAT:    return 3;
138                                 case SOCK_INT:      return 2;
139                                 case SOCK_BOOLEAN:  return 1;
140                                 default:            return -1;
141                         }
142                 case SOCK_FLOAT:
143                         switch (from) {
144                                 case SOCK_FLOAT:    return 5;
145                                 case SOCK_INT:      return 4;
146                                 case SOCK_BOOLEAN:  return 3;
147                                 case SOCK_RGBA:     return 2;
148                                 case SOCK_VECTOR:   return 1;
149                                 default:            return -1;
150                         }
151                 case SOCK_INT:
152                         switch (from) {
153                                 case SOCK_INT:      return 5;
154                                 case SOCK_FLOAT:    return 4;
155                                 case SOCK_BOOLEAN:  return 3;
156                                 case SOCK_RGBA:     return 2;
157                                 case SOCK_VECTOR:   return 1;
158                                 default:            return -1;
159                         }
160                 case SOCK_BOOLEAN:
161                         switch (from) {
162                                 case SOCK_BOOLEAN:  return 5;
163                                 case SOCK_INT:      return 4;
164                                 case SOCK_FLOAT:    return 3;
165                                 case SOCK_RGBA:     return 2;
166                                 case SOCK_VECTOR:   return 1;
167                                 default:            return -1;
168                         }
169                 case SOCK_SHADER:
170                         switch (from) {
171                                 case SOCK_SHADER:   return 1;
172                                 default:            return -1;
173                         }
174                 case SOCK_STRING:
175                         switch (from) {
176                                 case SOCK_STRING:   return 1;
177                                 default:            return -1;
178                         }
179                 default: return -1;
180         }
181 }
182
183 /* select a suitable input socket for an output */
184 static bNodeSocket *select_internal_link_input(bNode *node, bNodeSocket *output)
185 {
186         bNodeSocket *selected = NULL, *input;
187         int i;
188         int sel_priority = -1;
189         bool sel_is_linked = false;
190         
191         for (input = node->inputs.first, i = 0; input; input = input->next, ++i) {
192                 int priority = node_datatype_priority(input->type, output->type);
193                 bool is_linked = (input->link != NULL);
194                 bool preferred;
195                 
196                 if (nodeSocketIsHidden(input) ||                /* ignore hidden sockets */
197                     input->flag & SOCK_NO_INTERNAL_LINK ||      /* ignore if input is not allowed for internal connections */
198                     priority < 0 ||                             /* ignore incompatible types */
199                     priority < sel_priority)                    /* ignore if we already found a higher priority input */
200                 {
201                         continue;
202                 }
203                 
204                 /* determine if this input is preferred over the currently selected */
205                 preferred = (priority > sel_priority) ||    /* prefer higher datatype priority */
206                             (is_linked && !sel_is_linked);  /* prefer linked over unlinked */
207                 
208                 if (preferred) {
209                         selected = input;
210                         sel_is_linked = is_linked;
211                         sel_priority = priority;
212                 }
213         }
214         
215         return selected;
216 }
217
218 void node_update_internal_links_default(bNodeTree *ntree, bNode *node)
219 {
220         bNodeLink *link;
221         bNodeSocket *output, *input;
222         
223         /* sanity check */
224         if (!ntree)
225                 return;
226         
227         /* use link pointer as a tag for handled sockets (for outputs is unused anyway) */
228         for (output = node->outputs.first; output; output = output->next)
229                 output->link = NULL;
230         
231         for (link = ntree->links.first; link; link = link->next) {
232                 if (nodeLinkIsHidden(link))
233                         continue;
234                 
235                 output = link->fromsock;
236                 if (link->fromnode != node || output->link)
237                         continue;
238                 if (nodeSocketIsHidden(output) || output->flag & SOCK_NO_INTERNAL_LINK)
239                         continue;
240                 output->link = link; /* not really used, just for tagging handled sockets */
241                 
242                 /* look for suitable input */
243                 input = select_internal_link_input(node, output);
244                 
245                 if (input) {
246                         bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link");
247                         ilink->fromnode = node;
248                         ilink->fromsock = input;
249                         ilink->tonode = node;
250                         ilink->tosock = output;
251                         /* internal link is always valid */
252                         ilink->flag |= NODE_LINK_VALID;
253                         BLI_addtail(&node->internal_links, ilink);
254                 }
255         }
256         
257         /* clean up */
258         for (output = node->outputs.first; output; output = output->next)
259                 output->link = NULL;
260 }
261
262
263 /**** Default value RNA access ****/
264
265 float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
266 {
267         PointerRNA ptr;
268         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
269         return RNA_float_get(&ptr, "default_value");
270 }
271
272 void node_socket_set_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float value)
273 {
274         PointerRNA ptr;
275         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
276         RNA_float_set(&ptr, "default_value", value);
277 }
278
279 void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
280 {
281         PointerRNA ptr;
282         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
283         RNA_float_get_array(&ptr, "default_value", value);
284 }
285
286 void node_socket_set_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
287 {
288         PointerRNA ptr;
289         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
290         RNA_float_set_array(&ptr, "default_value", value);
291 }
292
293 void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
294 {
295         PointerRNA ptr;
296         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
297         RNA_float_get_array(&ptr, "default_value", value);
298 }
299
300 void node_socket_set_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, const float *value)
301 {
302         PointerRNA ptr;
303         RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
304         RNA_float_set_array(&ptr, "default_value", value);
305 }