270 lines
7.9 KiB
C
270 lines
7.9 KiB
C
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva,
|
|
* Juho Vepsäläinen
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file blender/nodes/texture/nodes/node_texture_common.c
|
|
* \ingroup texnodes
|
|
*/
|
|
|
|
|
|
#include "DNA_node_types.h"
|
|
|
|
#include "BKE_node.h"
|
|
|
|
#include "node_texture_util.h"
|
|
#include "node_common.h"
|
|
#include "node_exec.h"
|
|
|
|
static void copy_stack(bNodeStack *to, bNodeStack *from)
|
|
{
|
|
if (to != from) {
|
|
copy_v4_v4(to->vec, from->vec);
|
|
to->data = from->data;
|
|
to->datatype = from->datatype;
|
|
|
|
/* tag as copy to prevent freeing */
|
|
to->is_copy = 1;
|
|
}
|
|
}
|
|
|
|
/**** GROUP ****/
|
|
|
|
static void *group_initexec(bNode *node)
|
|
{
|
|
bNodeTree *ngroup= (bNodeTree*)node->id;
|
|
void *exec;
|
|
|
|
/* initialize the internal node tree execution */
|
|
exec = ntreeTexBeginExecTree(ngroup, 0);
|
|
|
|
return exec;
|
|
}
|
|
|
|
static void group_freeexec(bNode *UNUSED(node), void *nodedata)
|
|
{
|
|
bNodeTreeExec*gexec= (bNodeTreeExec*)nodedata;
|
|
|
|
ntreeTexEndExecTree(gexec, 0);
|
|
}
|
|
|
|
/* Copy inputs to the internal stack.
|
|
* This is a shallow copy, no buffers are duplicated here!
|
|
*/
|
|
static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack)
|
|
{
|
|
bNodeSocket *sock;
|
|
bNodeStack *ns;
|
|
int a;
|
|
for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) {
|
|
if (sock->groupsock) {
|
|
ns = node_get_socket_stack(gstack, sock->groupsock);
|
|
copy_stack(ns, in[a]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Copy internal results to the external outputs.
|
|
*/
|
|
static void group_copy_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack)
|
|
{
|
|
bNodeSocket *sock;
|
|
bNodeStack *ns;
|
|
int a;
|
|
for (sock=node->outputs.first, a=0; sock; sock=sock->next, ++a) {
|
|
if (sock->groupsock) {
|
|
ns = node_get_socket_stack(gstack, sock->groupsock);
|
|
copy_stack(out[a], ns);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
|
|
{
|
|
bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
|
|
bNodeThreadStack *nts;
|
|
|
|
/* XXX same behavior as trunk: all nodes inside group are executed.
|
|
* it's stupid, but just makes it work. compo redesign will do this better.
|
|
*/
|
|
{
|
|
bNode *inode;
|
|
for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
|
|
inode->need_exec = 1;
|
|
}
|
|
|
|
nts = ntreeGetThreadStack(exec, thread);
|
|
|
|
group_copy_inputs(node, in, nts->stack);
|
|
ntreeExecThreadNodes(exec, nts, data, thread);
|
|
group_copy_outputs(node, out, nts->stack);
|
|
|
|
ntreeReleaseThreadStack(nts);
|
|
}
|
|
|
|
void register_node_type_tex_group(ListBase *lb)
|
|
{
|
|
static bNodeType ntype;
|
|
|
|
node_type_base(&ntype, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS|NODE_CONST_OUTPUT);
|
|
node_type_socket_templates(&ntype, NULL, NULL);
|
|
node_type_size(&ntype, 120, 60, 200);
|
|
node_type_label(&ntype, node_group_label);
|
|
node_type_init(&ntype, node_group_init);
|
|
node_type_valid(&ntype, node_group_valid);
|
|
node_type_template(&ntype, node_group_template);
|
|
node_type_update(&ntype, NULL, node_group_verify);
|
|
node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
|
|
node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute);
|
|
|
|
nodeRegisterType(lb, &ntype);
|
|
}
|
|
|
|
|
|
/**** FOR LOOP ****/
|
|
|
|
#if 0 /* XXX loop nodes don't work nicely with current trees */
|
|
static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
|
|
{
|
|
bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
|
|
bNodeThreadStack *nts;
|
|
int iterations= (int)in[0]->vec[0];
|
|
bNodeSocket *sock;
|
|
bNodeStack *ns;
|
|
int iteration;
|
|
|
|
/* XXX same behavior as trunk: all nodes inside group are executed.
|
|
* it's stupid, but just makes it work. compo redesign will do this better.
|
|
*/
|
|
{
|
|
bNode *inode;
|
|
for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
|
|
inode->need_exec = 1;
|
|
}
|
|
|
|
nts = ntreeGetThreadStack(exec, thread);
|
|
|
|
/* "Iteration" socket */
|
|
sock = exec->nodetree->inputs.first;
|
|
ns = node_get_socket_stack(nts->stack, sock);
|
|
|
|
// group_copy_inputs(node, in, nts->stack);
|
|
for (iteration=0; iteration < iterations; ++iteration) {
|
|
/* first input contains current iteration counter */
|
|
ns->vec[0] = (float)iteration;
|
|
ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f;
|
|
|
|
// if (iteration > 0)
|
|
// loop_init_iteration(exec->nodetree, nts->stack);
|
|
// ntreeExecThreadNodes(exec, nts, data, thread);
|
|
}
|
|
// loop_copy_outputs(node, in, out, exec->stack);
|
|
|
|
ntreeReleaseThreadStack(nts);
|
|
}
|
|
|
|
void register_node_type_tex_forloop(ListBase *lb)
|
|
{
|
|
static bNodeType ntype;
|
|
|
|
node_type_base(&ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS);
|
|
node_type_socket_templates(&ntype, NULL, NULL);
|
|
node_type_size(&ntype, 120, 60, 200);
|
|
node_type_label(&ntype, node_group_label);
|
|
node_type_init(&ntype, node_forloop_init);
|
|
node_type_valid(&ntype, node_group_valid);
|
|
node_type_template(&ntype, node_forloop_template);
|
|
node_type_update(&ntype, NULL, node_group_verify);
|
|
node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree);
|
|
node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
|
|
node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute);
|
|
|
|
nodeRegisterType(lb, &ntype);
|
|
}
|
|
#endif
|
|
|
|
/**** WHILE LOOP ****/
|
|
|
|
#if 0 /* XXX loop nodes don't work nicely with current trees */
|
|
static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out)
|
|
{
|
|
bNodeTreeExec *exec= (bNodeTreeExec*)nodedata;
|
|
bNodeThreadStack *nts;
|
|
int condition= (in[0]->vec[0] > 0.0f);
|
|
bNodeSocket *sock;
|
|
bNodeStack *ns;
|
|
int iteration;
|
|
|
|
/* XXX same behavior as trunk: all nodes inside group are executed.
|
|
* it's stupid, but just makes it work. compo redesign will do this better.
|
|
*/
|
|
{
|
|
bNode *inode;
|
|
for (inode=exec->nodetree->nodes.first; inode; inode=inode->next)
|
|
inode->need_exec = 1;
|
|
}
|
|
|
|
nts = ntreeGetThreadStack(exec, thread);
|
|
|
|
/* "Condition" socket */
|
|
sock = exec->nodetree->outputs.first;
|
|
ns = node_get_socket_stack(nts->stack, sock);
|
|
|
|
iteration = 0;
|
|
// group_copy_inputs(node, in, nts->stack);
|
|
while (condition && iteration < node->custom1) {
|
|
// if (iteration > 0)
|
|
// loop_init_iteration(exec->nodetree, nts->stack);
|
|
// ntreeExecThreadNodes(exec, nts, data, thread);
|
|
|
|
condition = (ns->vec[0] > 0.0f);
|
|
++iteration;
|
|
}
|
|
// loop_copy_outputs(node, in, out, exec->stack);
|
|
|
|
ntreeReleaseThreadStack(nts);
|
|
}
|
|
|
|
void register_node_type_tex_whileloop(ListBase *lb)
|
|
{
|
|
static bNodeType ntype;
|
|
|
|
node_type_base(&ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS);
|
|
node_type_socket_templates(&ntype, NULL, NULL);
|
|
node_type_size(&ntype, 120, 60, 200);
|
|
node_type_label(&ntype, node_group_label);
|
|
node_type_init(&ntype, node_whileloop_init);
|
|
node_type_valid(&ntype, node_group_valid);
|
|
node_type_template(&ntype, node_whileloop_template);
|
|
node_type_update(&ntype, NULL, node_group_verify);
|
|
node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree);
|
|
node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear);
|
|
node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute);
|
|
|
|
nodeRegisterType(lb, &ntype);
|
|
}
|
|
#endif
|