Blender V2.61 - r43446
|
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