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_texture_util.h" 00039 #include "node_common.h" 00040 #include "node_exec.h" 00041 00042 static void copy_stack(bNodeStack *to, bNodeStack *from) 00043 { 00044 if (to != from) { 00045 copy_v4_v4(to->vec, from->vec); 00046 to->data = from->data; 00047 to->datatype = from->datatype; 00048 00049 /* tag as copy to prevent freeing */ 00050 to->is_copy = 1; 00051 } 00052 } 00053 00054 /**** GROUP ****/ 00055 00056 static void *group_initexec(bNode *node) 00057 { 00058 bNodeTree *ngroup= (bNodeTree*)node->id; 00059 void *exec; 00060 00061 /* initialize the internal node tree execution */ 00062 exec = ntreeTexBeginExecTree(ngroup, 0); 00063 00064 return exec; 00065 } 00066 00067 static void group_freeexec(bNode *UNUSED(node), void *nodedata) 00068 { 00069 bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata; 00070 00071 ntreeTexEndExecTree(gexec, 0); 00072 } 00073 00074 /* Copy inputs to the internal stack. 00075 * This is a shallow copy, no buffers are duplicated here! 00076 */ 00077 static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack) 00078 { 00079 bNodeSocket *sock; 00080 bNodeStack *ns; 00081 int a; 00082 for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { 00083 if (sock->groupsock) { 00084 ns = node_get_socket_stack(gstack, sock->groupsock); 00085 copy_stack(ns, in[a]); 00086 } 00087 } 00088 } 00089 00090 /* Copy internal results to the external outputs. 00091 */ 00092 static void group_copy_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack) 00093 { 00094 bNodeSocket *sock; 00095 bNodeStack *ns; 00096 int a; 00097 for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) { 00098 if (sock->groupsock) { 00099 ns = node_get_socket_stack(gstack, sock->groupsock); 00100 copy_stack(out[a], ns); 00101 } 00102 } 00103 } 00104 00105 static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) 00106 { 00107 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00108 bNodeThreadStack *nts; 00109 00110 /* XXX same behavior as trunk: all nodes inside group are executed. 00111 * it's stupid, but just makes it work. compo redesign will do this better. 00112 */ 00113 { 00114 bNode *inode; 00115 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) 00116 inode->need_exec = 1; 00117 } 00118 00119 nts = ntreeGetThreadStack(exec, thread); 00120 00121 group_copy_inputs(node, in, nts->stack); 00122 ntreeExecThreadNodes(exec, nts, data, thread); 00123 group_copy_outputs(node, out, nts->stack); 00124 00125 ntreeReleaseThreadStack(nts); 00126 } 00127 00128 void register_node_type_tex_group(bNodeTreeType *ttype) 00129 { 00130 static bNodeType ntype; 00131 00132 node_type_base(ttype, &ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT); 00133 node_type_socket_templates(&ntype, NULL, NULL); 00134 node_type_size(&ntype, 120, 60, 200); 00135 node_type_label(&ntype, node_group_label); 00136 node_type_init(&ntype, node_group_init); 00137 node_type_valid(&ntype, node_group_valid); 00138 node_type_template(&ntype, node_group_template); 00139 node_type_update(&ntype, NULL, node_group_verify); 00140 node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); 00141 node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute); 00142 00143 nodeRegisterType(ttype, &ntype); 00144 } 00145 00146 00147 /**** FOR LOOP ****/ 00148 00149 #if 0 /* XXX loop nodes don't work nicely with current trees */ 00150 static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) 00151 { 00152 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00153 bNodeThreadStack *nts; 00154 int iterations= (int)in[0]->vec[0]; 00155 bNodeSocket *sock; 00156 bNodeStack *ns; 00157 int iteration; 00158 00159 /* XXX same behavior as trunk: all nodes inside group are executed. 00160 * it's stupid, but just makes it work. compo redesign will do this better. 00161 */ 00162 { 00163 bNode *inode; 00164 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) 00165 inode->need_exec = 1; 00166 } 00167 00168 nts = ntreeGetThreadStack(exec, thread); 00169 00170 /* "Iteration" socket */ 00171 sock = exec->nodetree->inputs.first; 00172 ns = node_get_socket_stack(nts->stack, sock); 00173 00174 // group_copy_inputs(node, in, nts->stack); 00175 for (iteration=0; iteration < iterations; ++iteration) { 00176 /* first input contains current iteration counter */ 00177 ns->vec[0] = (float)iteration; 00178 ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f; 00179 00180 // if (iteration > 0) 00181 // loop_init_iteration(exec->nodetree, nts->stack); 00182 // ntreeExecThreadNodes(exec, nts, data, thread); 00183 } 00184 // loop_copy_outputs(node, in, out, exec->stack); 00185 00186 ntreeReleaseThreadStack(nts); 00187 } 00188 00189 void register_node_type_tex_forloop(bNodeTreeType *ttype) 00190 { 00191 static bNodeType ntype; 00192 00193 node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS); 00194 node_type_socket_templates(&ntype, NULL, NULL); 00195 node_type_size(&ntype, 120, 60, 200); 00196 node_type_label(&ntype, node_group_label); 00197 node_type_init(&ntype, node_forloop_init); 00198 node_type_valid(&ntype, node_group_valid); 00199 node_type_template(&ntype, node_forloop_template); 00200 node_type_update(&ntype, NULL, node_group_verify); 00201 node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree); 00202 node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); 00203 node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute); 00204 00205 nodeRegisterType(ttype, &ntype); 00206 } 00207 #endif 00208 00209 /**** WHILE LOOP ****/ 00210 00211 #if 0 /* XXX loop nodes don't work nicely with current trees */ 00212 static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) 00213 { 00214 bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; 00215 bNodeThreadStack *nts; 00216 int condition= (in[0]->vec[0] > 0.0f); 00217 bNodeSocket *sock; 00218 bNodeStack *ns; 00219 int iteration; 00220 00221 /* XXX same behavior as trunk: all nodes inside group are executed. 00222 * it's stupid, but just makes it work. compo redesign will do this better. 00223 */ 00224 { 00225 bNode *inode; 00226 for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) 00227 inode->need_exec = 1; 00228 } 00229 00230 nts = ntreeGetThreadStack(exec, thread); 00231 00232 /* "Condition" socket */ 00233 sock = exec->nodetree->outputs.first; 00234 ns = node_get_socket_stack(nts->stack, sock); 00235 00236 iteration = 0; 00237 // group_copy_inputs(node, in, nts->stack); 00238 while (condition && iteration < node->custom1) { 00239 // if (iteration > 0) 00240 // loop_init_iteration(exec->nodetree, nts->stack); 00241 // ntreeExecThreadNodes(exec, nts, data, thread); 00242 00243 condition = (ns->vec[0] > 0.0f); 00244 ++iteration; 00245 } 00246 // loop_copy_outputs(node, in, out, exec->stack); 00247 00248 ntreeReleaseThreadStack(nts); 00249 } 00250 00251 void register_node_type_tex_whileloop(bNodeTreeType *ttype) 00252 { 00253 static bNodeType ntype; 00254 00255 node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS); 00256 node_type_socket_templates(&ntype, NULL, NULL); 00257 node_type_size(&ntype, 120, 60, 200); 00258 node_type_label(&ntype, node_group_label); 00259 node_type_init(&ntype, node_whileloop_init); 00260 node_type_valid(&ntype, node_group_valid); 00261 node_type_template(&ntype, node_whileloop_template); 00262 node_type_update(&ntype, NULL, node_group_verify); 00263 node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree); 00264 node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); 00265 node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute); 00266 00267 nodeRegisterType(ttype, &ntype); 00268 } 00269 #endif