code cleanup: replace MIN2/MAX2 with minf/maxf
[blender.git] / source / blender / nodes / composite / nodes / node_composite_common.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) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
24  * Juho Vepsäläinen
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/nodes/composite/nodes/node_composite_common.c
30  *  \ingroup cmpnodes
31  */
32
33
34 #include "DNA_node_types.h"
35
36 #include "BKE_node.h"
37
38 #include "node_composite_util.h"
39 #include "node_common.h"
40 #include "node_exec.h"
41
42 #if 0
43 static void PRINT_BUFFERS(bNodeTreeExec *exec)
44 {
45         bNodeTree *ntree= exec->nodetree;
46         bNode *node;
47         bNodeSocket *sock;
48         bNodeStack *ns;
49         int i;
50         
51         printf("-------------- DEBUG --------------\n");
52         for (sock=ntree->inputs.first, i=0; sock; sock=sock->next, ++i) {
53                 ns = node_get_socket_stack(exec->stack, sock);
54                 printf("%d. Tree Input %s", i, sock->name);
55                 if (ns->external)
56                         printf(" (external)");
57                 printf(": data=%p\n", ns->data);
58         }
59         for (sock=ntree->outputs.first, i=0; sock; sock=sock->next, ++i) {
60                 ns = node_get_socket_stack(exec->stack, sock);
61                 printf("%d. Tree Output %s", i, sock->name);
62                 if (ns->external)
63                         printf(" (external)");
64                 printf(": data=%p\n", ns->data);
65         }
66         for (node=ntree->nodes.first; node; node=node->next) {
67                 printf("Node %s:\n", node->name);
68                 for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
69                         ns = node_get_socket_stack(exec->stack, sock);
70                         printf("\t%d. Input %s", i, sock->name);
71                         if (ns->external)
72                                 printf(" (external)");
73                         printf(": data=%p\n", ns->data);
74                 }
75                 for (sock=node->outputs.first, i=0; sock; sock=sock->next, ++i) {
76                         ns = node_get_socket_stack(exec->stack, sock);
77                         printf("\t%d. Output %s", i, sock->name);
78                         if (ns->external)
79                                 printf(" (external)");
80                         printf(": data=%p\n", ns->data);
81                 }
82         }
83 }
84 #endif
85
86 static void copy_stack(bNodeStack *to, bNodeStack *from)
87 {
88         if (to != from) {
89                 copy_v4_v4(to->vec, from->vec);
90                 to->data = from->data;
91                 to->datatype = from->datatype;
92                 
93                 /* tag as copy to prevent freeing */
94                 to->is_copy = 1;
95         }
96 }
97
98 static void move_stack(bNodeStack *to, bNodeStack *from)
99 {
100         if (to != from) {
101                 copy_v4_v4(to->vec, from->vec);
102                 to->data = from->data;
103                 to->datatype = from->datatype;
104                 to->is_copy = from->is_copy;
105                 
106                 zero_v4(from->vec);
107                 from->data = NULL;
108                 from->datatype = 0;
109                 from->is_copy = 0;
110         }
111 }
112
113 /**** GROUP ****/
114
115 static void *group_initexec(bNode *node)
116 {
117         bNodeTree *ngroup= (bNodeTree *)node->id;
118         bNodeTreeExec *exec;
119         bNodeSocket *sock;
120         bNodeStack *ns;
121         
122         if (!ngroup)
123                 return NULL;
124         
125         /* initialize the internal node tree execution */
126         exec = ntreeCompositBeginExecTree(ngroup, 0);
127         
128         /* tag group outputs as external to prevent freeing */
129         for (sock=ngroup->outputs.first; sock; sock=sock->next) {
130                 if (!(sock->flag & SOCK_INTERNAL)) {
131                         ns = node_get_socket_stack(exec->stack, sock);
132                         ns->external = 1;
133                 }
134         }
135
136         return exec;
137 }
138
139 static void group_freeexec(bNode *UNUSED(node), void *nodedata)
140 {
141         bNodeTreeExec *gexec= (bNodeTreeExec *)nodedata;
142         
143         if (gexec)
144                 ntreeCompositEndExecTree(gexec, 0);
145 }
146
147 /* Copy inputs to the internal stack.
148  * This is a shallow copy, no buffers are duplicated here!
149  */
150 static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
151 {
152         bNodeSocket *sock;
153         bNodeStack *ns;
154         int a;
155         for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
156                 if (sock->groupsock) {
157                         ns = node_get_socket_stack(gstack, sock->groupsock);
158                         copy_stack(ns, in[a]);
159                 }
160         }
161 }
162
163 /* Copy internal results to the external outputs.
164  */
165 static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
166 {
167         bNodeSocket *sock;
168         bNodeStack *ns;
169         int a;
170         for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
171                 if (sock->groupsock) {
172                         ns = node_get_socket_stack(gstack, sock->groupsock);
173                         move_stack(out[a], ns);
174                 }
175         }
176 }
177
178 /* Free internal buffers */
179 static void group_free_internal(bNodeTreeExec *gexec)
180 {
181         bNodeStack *ns;
182         int i;
183         
184         for (i=0, ns=gexec->stack; i < gexec->stacksize; ++i, ++ns) {
185                 if (!ns->external && !ns->is_copy) {
186                         if (ns->data) {
187                                 free_compbuf(ns->data);
188                                 ns->data = NULL;
189                         }
190                 }
191         }
192 }
193
194 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
195 {
196         bNodeTreeExec *exec= (bNodeTreeExec *)nodedata;
197         
198         if (!exec)
199                 return;
200         
201         /* XXX same behavior as trunk: all nodes inside group are executed.
202          * it's stupid, but just makes it work. compo redesign will do this better.
203          */
204         {
205                 bNode *inode;
206                 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
207                         inode->need_exec = 1;
208         }
209         
210         group_copy_inputs(node, in, exec->stack);
211         ntreeExecNodes(exec, data, thread);
212         group_free_internal(exec);
213         group_move_outputs(node, out, exec->stack);
214 }
215
216 void register_node_type_cmp_group(bNodeTreeType *ttype)
217 {
218         static bNodeType ntype;
219
220         node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
221         node_type_socket_templates(&ntype, NULL, NULL);
222         node_type_size(&ntype, 120, 60, 200);
223         node_type_label(&ntype, node_group_label);
224         node_type_init(&ntype, node_group_init);
225         node_type_valid(&ntype, node_group_valid);
226         node_type_template(&ntype, node_group_template);
227         node_type_update(&ntype, NULL, node_group_verify);
228         node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
229         node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
230         
231         nodeRegisterType(ttype, &ntype);
232 }
233
234
235 /**** FOR LOOP ****/
236
237 #if 0 /* XXX loop nodes don't work nicely with current trees */
238 /* Move the results from the previous iteration back to the input sockets. */
239 static void loop_iteration_reset(bNodeTree *ngroup, bNodeStack *gstack)
240 {
241         bNodeSocket *gin, *gout;
242         bNodeStack *nsin, *nsout;
243         
244         gin = ngroup->inputs.first;
245         gout = ngroup->outputs.first;
246         
247         while (gin && gout) {
248                 /* skip static (non-looping) sockets */
249                 while (gin && !(gin->flag & SOCK_DYNAMIC))
250                         gin=gin->next;
251                 while (gout && !(gout->flag & SOCK_DYNAMIC))
252                         gout=gout->next;
253                 
254                 if (gin && gout) {
255                         nsin = node_get_socket_stack(gstack, gin);
256                         nsout = node_get_socket_stack(gstack, gout);
257                         
258                         move_stack(nsin, nsout);
259                         
260                         gin=gin->next;
261                         gout=gout->next;
262                 }
263         }
264 }
265
266 static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
267 {
268         bNodeTreeExec *exec= (bNodeTreeExec *)nodedata;
269         int totiterations= (int)in[0]->vec[0];
270         bNodeSocket *sock;
271         bNodeStack *ns;
272         int iteration;
273         
274         /* XXX same behavior as trunk: all nodes inside group are executed.
275          * it's stupid, but just makes it work. compo redesign will do this better.
276          */
277         {
278                 bNode *inode;
279                 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
280                         inode->need_exec = 1;
281         }
282         
283         /* "Iteration" socket */
284         sock = exec->nodetree->inputs.first;
285         ns = node_get_socket_stack(exec->stack, sock);
286         
287         group_copy_inputs(node, in, exec->stack);
288         for (iteration=0; iteration < totiterations; ++iteration) {
289                 /* first input contains current iteration counter */
290                 ns->vec[0] = (float)iteration;
291                 
292                 if (iteration > 0)
293                         loop_iteration_reset(exec->nodetree, exec->stack);
294                 ntreeExecNodes(exec, data, thread);
295                 group_free_internal(exec);
296         }
297         group_move_outputs(node, out, exec->stack);
298 }
299
300 void register_node_type_cmp_forloop(bNodeTreeType *ttype)
301 {
302         static bNodeType ntype;
303
304         node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS);
305         node_type_socket_templates(&ntype, NULL, NULL);
306         node_type_size(&ntype, 120, 60, 200);
307         node_type_label(&ntype, node_group_label);
308         node_type_init(&ntype, node_forloop_init);
309         node_type_valid(&ntype, node_group_valid);
310         node_type_template(&ntype, node_forloop_template);
311         node_type_update(&ntype, NULL, node_group_verify);
312         node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree);
313         node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
314         node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute);
315         
316         nodeRegisterType(ttype, &ntype);
317 }
318 #endif
319
320
321 /**** WHILE LOOP ****/
322
323 #if 0 /* XXX loop nodes don't work nicely with current trees */
324 static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
325 {
326         bNodeTreeExec *exec= (bNodeTreeExec *)nodedata;
327         int condition= (in[0]->vec[0] > 0.0f);
328         bNodeSocket *sock;
329         bNodeStack *ns;
330         int iteration;
331         
332         /* XXX same behavior as trunk: all nodes inside group are executed.
333          * it's stupid, but just makes it work. compo redesign will do this better.
334          */
335         {
336                 bNode *inode;
337                 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
338                         inode->need_exec = 1;
339         }
340         
341         /* "Condition" socket */
342         sock = exec->nodetree->outputs.first;
343         ns = node_get_socket_stack(exec->stack, sock);
344         
345         iteration = 0;
346         group_copy_inputs(node, in, exec->stack);
347         while (condition && iteration < node->custom1) {
348                 if (iteration > 0)
349                         loop_iteration_reset(exec->nodetree, exec->stack);
350                 ntreeExecNodes(exec, data, thread);
351                 group_free_internal(exec);
352                 
353 //              PRINT_BUFFERS(exec);
354                 
355                 condition = (ns->vec[0] > 0.0f);
356                 ++iteration;
357         }
358         group_move_outputs(node, out, exec->stack);
359 }
360
361 void register_node_type_cmp_whileloop(bNodeTreeType *ttype)
362 {
363         static bNodeType ntype;
364
365         node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS);
366         node_type_socket_templates(&ntype, NULL, NULL);
367         node_type_size(&ntype, 120, 60, 200);
368         node_type_label(&ntype, node_group_label);
369         node_type_init(&ntype, node_whileloop_init);
370         node_type_valid(&ntype, node_group_valid);
371         node_type_template(&ntype, node_whileloop_template);
372         node_type_update(&ntype, NULL, node_group_verify);
373         node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree);
374         node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
375         node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute);
376         
377         nodeRegisterType(ttype, &ntype);
378 }
379 #endif