Blender V2.61 - r43446

node_composite_common.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
00024  * Juho Vepsäläinen
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "DNA_node_types.h"
00035 
00036 #include "BKE_node.h"
00037 
00038 #include "node_composite_util.h"
00039 #include "node_common.h"
00040 #include "node_exec.h"
00041 
00042 #if 0
00043 static void PRINT_BUFFERS(bNodeTreeExec *exec)
00044 {
00045     bNodeTree *ntree= exec->nodetree;
00046     bNode *node;
00047     bNodeSocket *sock;
00048     bNodeStack *ns;
00049     int i;
00050     
00051     printf("-------------- DEBUG --------------\n");
00052     for (sock=ntree->inputs.first, i=0; sock; sock=sock->next, ++i) {
00053         ns = node_get_socket_stack(exec->stack, sock);
00054         printf("%d. Tree Input %s", i, sock->name);
00055         if (ns->external)
00056             printf(" (external)");
00057         printf(": data=%p\n", ns->data);
00058     }
00059     for (sock=ntree->outputs.first, i=0; sock; sock=sock->next, ++i) {
00060         ns = node_get_socket_stack(exec->stack, sock);
00061         printf("%d. Tree Output %s", i, sock->name);
00062         if (ns->external)
00063             printf(" (external)");
00064         printf(": data=%p\n", ns->data);
00065     }
00066     for (node=ntree->nodes.first; node; node=node->next) {
00067         printf("Node %s:\n", node->name);
00068         for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
00069             ns = node_get_socket_stack(exec->stack, sock);
00070             printf("\t%d. Input %s", i, sock->name);
00071             if (ns->external)
00072                 printf(" (external)");
00073             printf(": data=%p\n", ns->data);
00074         }
00075         for (sock=node->outputs.first, i=0; sock; sock=sock->next, ++i) {
00076             ns = node_get_socket_stack(exec->stack, sock);
00077             printf("\t%d. Output %s", i, sock->name);
00078             if (ns->external)
00079                 printf(" (external)");
00080             printf(": data=%p\n", ns->data);
00081         }
00082     }
00083 }
00084 #endif
00085 
00086 static void copy_stack(bNodeStack *to, bNodeStack *from)
00087 {
00088     if (to != from) {
00089         copy_v4_v4(to->vec, from->vec);
00090         to->data = from->data;
00091         to->datatype = from->datatype;
00092         
00093         /* tag as copy to prevent freeing */
00094         to->is_copy = 1;
00095     }
00096 }
00097 
00098 static void move_stack(bNodeStack *to, bNodeStack *from)
00099 {
00100     if (to != from) {
00101         copy_v4_v4(to->vec, from->vec);
00102         to->data = from->data;
00103         to->datatype = from->datatype;
00104         to->is_copy = from->is_copy;
00105         
00106         zero_v4(from->vec);
00107         from->data = NULL;
00108         from->datatype = 0;
00109         from->is_copy = 0;
00110     }
00111 }
00112 
00113 /**** GROUP ****/
00114 
00115 static void *group_initexec(bNode *node)
00116 {
00117     bNodeTree *ngroup= (bNodeTree*)node->id;
00118     bNodeTreeExec *exec;
00119     bNodeSocket *sock;
00120     bNodeStack *ns;
00121     
00122     if (!ngroup)
00123         return NULL;
00124     
00125     /* initialize the internal node tree execution */
00126     exec = ntreeCompositBeginExecTree(ngroup, 0);
00127     
00128     /* tag group outputs as external to prevent freeing */
00129     for (sock=ngroup->outputs.first; sock; sock=sock->next) {
00130         if (!(sock->flag & SOCK_INTERNAL)) {
00131             ns = node_get_socket_stack(exec->stack, sock);
00132             ns->external = 1;
00133         }
00134     }
00135 
00136     return exec;
00137 }
00138 
00139 static void group_freeexec(bNode *UNUSED(node), void *nodedata)
00140 {
00141     bNodeTreeExec *gexec= (bNodeTreeExec*)nodedata;
00142     
00143     if (gexec)
00144         ntreeCompositEndExecTree(gexec, 0);
00145 }
00146 
00147 /* Copy inputs to the internal stack.
00148  * This is a shallow copy, no buffers are duplicated here!
00149  */
00150 static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
00151 {
00152     bNodeSocket *sock;
00153     bNodeStack *ns;
00154     int a;
00155     for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
00156         if (sock->groupsock) {
00157             ns = node_get_socket_stack(gstack, sock->groupsock);
00158             copy_stack(ns, in[a]);
00159         }
00160     }
00161 }
00162 
00163 /* Copy internal results to the external outputs.
00164  */
00165 static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
00166 {
00167     bNodeSocket *sock;
00168     bNodeStack *ns;
00169     int a;
00170     for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
00171         if (sock->groupsock) {
00172             ns = node_get_socket_stack(gstack, sock->groupsock);
00173             move_stack(out[a], ns);
00174         }
00175     }
00176 }
00177 
00178 /* Free internal buffers */
00179 static void group_free_internal(bNodeTreeExec *gexec)
00180 {
00181     bNodeStack *ns;
00182     int i;
00183     
00184     for (i=0, ns=gexec->stack; i < gexec->stacksize; ++i, ++ns) {
00185         if (!ns->external && !ns->is_copy) {
00186             if (ns->data) {
00187                 free_compbuf(ns->data);
00188                 ns->data = NULL;
00189             }
00190         }
00191     }
00192 }
00193 
00194 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
00195 {
00196     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00197     
00198     if (!exec)
00199         return;
00200     
00201     /* XXX same behavior as trunk: all nodes inside group are executed.
00202      * it's stupid, but just makes it work. compo redesign will do this better.
00203      */
00204     {
00205         bNode *inode;
00206         for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
00207             inode->need_exec = 1;
00208     }
00209     
00210     group_copy_inputs(node, in, exec->stack);
00211     ntreeExecNodes(exec, data, thread);
00212     group_free_internal(exec);
00213     group_move_outputs(node, out, exec->stack);
00214 }
00215 
00216 void register_node_type_cmp_group(bNodeTreeType *ttype)
00217 {
00218     static bNodeType ntype;
00219 
00220     node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
00221     node_type_socket_templates(&ntype, NULL, NULL);
00222     node_type_size(&ntype, 120, 60, 200);
00223     node_type_label(&ntype, node_group_label);
00224     node_type_init(&ntype, node_group_init);
00225     node_type_valid(&ntype, node_group_valid);
00226     node_type_template(&ntype, node_group_template);
00227     node_type_update(&ntype, NULL, node_group_verify);
00228     node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
00229     node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
00230     
00231     nodeRegisterType(ttype, &ntype);
00232 }
00233 
00234 
00235 /**** FOR LOOP ****/
00236 
00237 #if 0 /* XXX loop nodes don't work nicely with current trees */
00238 /* Move the results from the previous iteration back to the input sockets. */
00239 static void loop_iteration_reset(bNodeTree *ngroup, bNodeStack *gstack)
00240 {
00241     bNodeSocket *gin, *gout;
00242     bNodeStack *nsin, *nsout;
00243     
00244     gin = ngroup->inputs.first;
00245     gout = ngroup->outputs.first;
00246     
00247     while (gin && gout) {
00248         /* skip static (non-looping) sockets */
00249         while (gin && !(gin->flag & SOCK_DYNAMIC))
00250             gin=gin->next;
00251         while (gout && !(gout->flag & SOCK_DYNAMIC))
00252             gout=gout->next;
00253         
00254         if (gin && gout) {
00255             nsin = node_get_socket_stack(gstack, gin);
00256             nsout = node_get_socket_stack(gstack, gout);
00257             
00258             move_stack(nsin, nsout);
00259             
00260             gin=gin->next;
00261             gout=gout->next;
00262         }
00263     }
00264 }
00265 
00266 static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
00267 {
00268     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00269     int totiterations= (int)in[0]->vec[0];
00270     bNodeSocket *sock;
00271     bNodeStack *ns;
00272     int iteration;
00273     
00274     /* XXX same behavior as trunk: all nodes inside group are executed.
00275      * it's stupid, but just makes it work. compo redesign will do this better.
00276      */
00277     {
00278         bNode *inode;
00279         for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
00280             inode->need_exec = 1;
00281     }
00282     
00283     /* "Iteration" socket */
00284     sock = exec->nodetree->inputs.first;
00285     ns = node_get_socket_stack(exec->stack, sock);
00286     
00287     group_copy_inputs(node, in, exec->stack);
00288     for (iteration=0; iteration < totiterations; ++iteration) {
00289         /* first input contains current iteration counter */
00290         ns->vec[0] = (float)iteration;
00291         
00292         if (iteration > 0)
00293             loop_iteration_reset(exec->nodetree, exec->stack);
00294         ntreeExecNodes(exec, data, thread);
00295         group_free_internal(exec);
00296     }
00297     group_move_outputs(node, out, exec->stack);
00298 }
00299 
00300 void register_node_type_cmp_forloop(bNodeTreeType *ttype)
00301 {
00302     static bNodeType ntype;
00303 
00304     node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS);
00305     node_type_socket_templates(&ntype, NULL, NULL);
00306     node_type_size(&ntype, 120, 60, 200);
00307     node_type_label(&ntype, node_group_label);
00308     node_type_init(&ntype, node_forloop_init);
00309     node_type_valid(&ntype, node_group_valid);
00310     node_type_template(&ntype, node_forloop_template);
00311     node_type_update(&ntype, NULL, node_group_verify);
00312     node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree);
00313     node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
00314     node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute);
00315     
00316     nodeRegisterType(ttype, &ntype);
00317 }
00318 #endif
00319 
00320 
00321 /**** WHILE LOOP ****/
00322 
00323 #if 0 /* XXX loop nodes don't work nicely with current trees */
00324 static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
00325 {
00326     bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
00327     int condition= (in[0]->vec[0] > 0.0f);
00328     bNodeSocket *sock;
00329     bNodeStack *ns;
00330     int iteration;
00331     
00332     /* XXX same behavior as trunk: all nodes inside group are executed.
00333      * it's stupid, but just makes it work. compo redesign will do this better.
00334      */
00335     {
00336         bNode *inode;
00337         for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
00338             inode->need_exec = 1;
00339     }
00340     
00341     /* "Condition" socket */
00342     sock = exec->nodetree->outputs.first;
00343     ns = node_get_socket_stack(exec->stack, sock);
00344     
00345     iteration = 0;
00346     group_copy_inputs(node, in, exec->stack);
00347     while (condition && iteration < node->custom1) {
00348         if (iteration > 0)
00349             loop_iteration_reset(exec->nodetree, exec->stack);
00350         ntreeExecNodes(exec, data, thread);
00351         group_free_internal(exec);
00352         
00353 //      PRINT_BUFFERS(exec);
00354         
00355         condition = (ns->vec[0] > 0.0f);
00356         ++iteration;
00357     }
00358     group_move_outputs(node, out, exec->stack);
00359 }
00360 
00361 void register_node_type_cmp_whileloop(bNodeTreeType *ttype)
00362 {
00363     static bNodeType ntype;
00364 
00365     node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS);
00366     node_type_socket_templates(&ntype, NULL, NULL);
00367     node_type_size(&ntype, 120, 60, 200);
00368     node_type_label(&ntype, node_group_label);
00369     node_type_init(&ntype, node_whileloop_init);
00370     node_type_valid(&ntype, node_group_valid);
00371     node_type_template(&ntype, node_whileloop_template);
00372     node_type_update(&ntype, NULL, node_group_verify);
00373     node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree);
00374     node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
00375     node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute);
00376     
00377     nodeRegisterType(ttype, &ntype);
00378 }
00379 #endif