Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2008-11-13 00:16:53 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2008-11-13 00:16:53 +0300
commitbdfe7d89e2f1292644577972c716931b4ce3c6c3 (patch)
treed00eb50b749cb001e2b08272c91791e66740b05d /source/blender/blenkernel/intern/node.c
parent78a1c27c4a6abe0ed31ca93ad21910f3df04da56 (diff)
parent7e4db234cee71ead34ee81a12e27da4bd548eb4b (diff)
Merge of trunk into blender 2.5:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416 Issues: * GHOST/X11 had conflicting changes. Some code was added in 2.5, which was later added in trunk also, but reverted partially, specifically revision 16683. I have left out this reversion in the 2.5 branch since I think it is needed there. http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683 * Scons had various conflicting changes, I decided to go with trunk version for everything except priorities and some library renaming. * In creator.c, there were various fixes and fixes for fixes related to the -w -W and -p options. In 2.5 -w and -W is not coded yet, and -p is done differently. Since this is changed so much, and I don't think those fixes would be needed in 2.5, I've left them out. * Also in creator.c: there was code for a python bugfix where the screen was not initialized when running with -P. The code that initializes the screen there I had to disable, that can't work in 2.5 anymore but left it commented as a reminder. Further I had to disable some new function calls. using src/ and python/, as was done already in this branch, disabled function calls: * bpath.c: error reporting * BME_conversions.c: editmesh conversion functions. * SHD_dynamic: disabled almost completely, there is no python/. * KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled. * text.c: clipboard copy call. * object.c: OB_SUPPORT_MATERIAL. * DerivedMesh.c and subsurf_ccg, stipple_quarttone. Still to be done: * Go over files and functions that were moved to a different location but could still use changes that were done in trunk.
Diffstat (limited to 'source/blender/blenkernel/intern/node.c')
-rw-r--r--source/blender/blenkernel/intern/node.c579
1 files changed, 479 insertions, 100 deletions
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 5c9b609bbaf..8d60b1b4359 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -27,6 +27,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#ifndef DISABLE_PYTHON
+#include <Python.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
@@ -34,6 +38,7 @@
#include "DNA_image_types.h"
#include "DNA_node_types.h"
#include "DNA_material_types.h"
+#include "DNA_text_types.h"
#include "DNA_scene_types.h"
#include "BKE_blender.h"
@@ -44,6 +49,7 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_texture.h"
+#include "BKE_text.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
@@ -61,10 +67,12 @@
#include "RE_render_ext.h" /* <- ibuf_sample() */
#include "CMP_node.h"
+#include "intern/CMP_util.h" /* stupid include path... */
+
#include "SHD_node.h"
-/* not very important, but the stack solver likes to know a maximum */
-#define MAX_SOCKET 64
+#include "GPU_extensions.h"
+#include "GPU_material.h"
static ListBase empty_list = {NULL, NULL};
ListBase node_all_composit = {NULL, NULL};
@@ -72,7 +80,7 @@ ListBase node_all_shaders = {NULL, NULL};
/* ************** Type stuff ********** */
-static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup)
+static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
{
if(type==NODE_GROUP) {
if(ngroup && GS(ngroup->id.name)==ID_NT) {
@@ -83,7 +91,7 @@ static bNodeType *node_get_type(bNodeTree *ntree, int type, bNodeTree *ngroup)
else {
bNodeType *ntype = ntree->alltypes.first;
for(; ntype; ntype= ntype->next)
- if(ntype->type==type)
+ if(ntype->type==type && id==ntype->id )
return ntype;
return NULL;
@@ -105,7 +113,27 @@ void ntreeInitTypes(bNodeTree *ntree)
for(node= ntree->nodes.first; node; node= next) {
next= node->next;
- node->typeinfo= node_get_type(ntree, node->type, (bNodeTree *)node->id);
+ if(node->type==NODE_DYNAMIC) {
+ bNodeType *stype= NULL;
+ if(node->id==NULL) { /* empty script node */
+ stype= node_get_type(ntree, node->type, NULL, NULL);
+ } else { /* not an empty script node */
+ stype= node_get_type(ntree, node->type, NULL, node->id);
+ if(!stype) {
+ stype= node_get_type(ntree, node->type, NULL, NULL);
+ /* needed info if the pynode script fails now: */
+ if (node->id) node->storage= ntree;
+ } else {
+ node->custom1= 0;
+ node->custom1= BSET(node->custom1,NODE_DYNAMIC_ADDEXIST);
+ }
+ }
+ node->typeinfo= stype;
+ node->typeinfo->initfunc(node);
+ } else {
+ node->typeinfo= node_get_type(ntree, node->type, (bNodeTree *)node->id, NULL);
+ }
+
if(node->typeinfo==NULL) {
printf("Error: Node type %s doesn't exist anymore, removed\n", node->name);
nodeFreeNode(ntree, node);
@@ -115,6 +143,18 @@ void ntreeInitTypes(bNodeTree *ntree)
ntree->init |= NTREE_TYPE_INIT;
}
+/* updates node with (modified) bNodeType.. this should be done for all trees */
+void ntreeUpdateType(bNodeTree *ntree, bNodeType *ntype)
+{
+ bNode *node;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo== ntype) {
+ nodeUpdateType(ntree, node, ntype);
+ }
+ }
+}
+
/* only used internal... we depend on type definitions! */
static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
{
@@ -137,7 +177,7 @@ static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
if(lb)
BLI_addtail(lb, sock);
-
+
return sock;
}
@@ -483,6 +523,28 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
BLI_addtail(&ngroup->nodes, node);
node->locx-= 0.5f*(min[0]+max[0]);
node->locy-= 0.5f*(min[1]+max[1]);
+
+ /* set selin and selout of the nodetree */
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(sock->flag & SOCK_SEL) {
+ ngroup->selin= sock;
+ break;
+ }
+ }
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(sock->flag & SOCK_SEL) {
+ ngroup->selout= sock;
+ break;
+ }
+ }
+
+ /* set socket own_index to zero since it can still have a value
+ * from being in a group before, otherwise it doesn't get a unique
+ * index in group_verify_own_indices */
+ for(sock= node->inputs.first; sock; sock= sock->next)
+ sock->own_index= 0;
+ for(sock= node->outputs.first; sock; sock= sock->next)
+ sock->own_index= 0;
}
}
@@ -499,7 +561,7 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
ntreeMakeOwnType(ngroup);
/* make group node */
- gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup);
+ gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup, NULL);
gnode->locx= 0.5f*(min[0]+max[0]);
gnode->locy= 0.5f*(min[1]+max[1]);
@@ -538,6 +600,10 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
}
}
}
+
+ /* update node levels */
+ ntreeSolveOrder(ntree);
+
return gnode;
}
@@ -653,7 +719,8 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
}
}
-static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
+/* finds a node based on given socket */
+int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex)
{
bNode *node;
bNodeSocket *tsock;
@@ -671,13 +738,15 @@ static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **n
if(tsock)
break;
}
+
if(node) {
*nodep= node;
- *sockindex= index;
- }
- else {
- *nodep= NULL;
+ if(sockindex) *sockindex= index;
+ return 1;
}
+
+ *nodep= NULL;
+ return 0;
}
/* returns 1 if its OK */
@@ -717,7 +786,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
for(link= ntree->links.first; link; link= link->next) {
if(link->tonode==gnode) {
/* link->tosock->tosock is on the node we look for */
- find_node_with_socket(ngroup, link->tosock->tosock, &nextn, &index);
+ nodeFindNode(ngroup, link->tosock->tosock, &nextn, &index);
if(nextn==NULL) printf("wrong stuff!\n");
else if(nextn->new_node==NULL) printf("wrong stuff too!\n");
else {
@@ -727,7 +796,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
}
else if(link->fromnode==gnode) {
/* link->fromsock->tosock is on the node we look for */
- find_node_with_socket(ngroup, link->fromsock->tosock, &nextn, &index);
+ nodeFindNode(ngroup, link->fromsock->tosock, &nextn, &index);
if(nextn==NULL) printf("1 wrong stuff!\n");
else if(nextn->new_node==NULL) printf("1 wrong stuff too!\n");
else {
@@ -749,30 +818,28 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
return 1;
}
-/* ************** Add stuff ********** */
+void nodeCopyGroup(bNode *gnode)
+{
+ bNodeSocket *sock;
+
+ gnode->id->us--;
+ gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id, 0);
-bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
+ /* new_sock was set in nodeCopyNode */
+ for(sock=gnode->inputs.first; sock; sock=sock->next)
+ if(sock->tosock)
+ sock->tosock= sock->tosock->new_sock;
+
+ for(sock=gnode->outputs.first; sock; sock=sock->next)
+ if(sock->tosock)
+ sock->tosock= sock->tosock->new_sock;
+}
+
+/* ************** Add stuff ********** */
+void nodeAddSockets(bNode *node, bNodeType *ntype)
{
- bNode *node;
- bNodeType *ntype= node_get_type(ntree, type, ngroup);
bNodeSocketType *stype;
-
- node= MEM_callocN(sizeof(bNode), "new node");
- BLI_addtail(&ntree->nodes, node);
- node->typeinfo= ntype;
-
- if(ngroup)
- BLI_strncpy(node->name, ngroup->id.name+2, NODE_MAXSTR);
- else
- BLI_strncpy(node->name, ntype->name, NODE_MAXSTR);
- node->type= ntype->type;
- node->flag= NODE_SELECT|ntype->flag;
- node->width= ntype->width;
- node->miniwidth= 42.0f; /* small value only, allows print of first chars */
-
- if(type==NODE_GROUP)
- node->id= (ID *)ngroup;
-
+
if(ntype->inputs) {
stype= ntype->inputs;
while(stype->type != -1) {
@@ -787,34 +854,111 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
stype++;
}
}
-
+}
+
+
+bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
+{
+ bNode *node= NULL;
+ bNodeType *ntype= NULL;
+
+ if(type>=NODE_DYNAMIC_MENU) {
+ int a=0, idx= type-NODE_DYNAMIC_MENU;
+ ntype= ntree->alltypes.first;
+ while(ntype) {
+ if(ntype->type==NODE_DYNAMIC) {
+ if(a==idx)
+ break;
+ a++;
+ }
+ ntype= ntype->next;
+ }
+ } else
+ ntype= node_get_type(ntree, type, ngroup, id);
+
+ node= MEM_callocN(sizeof(bNode), "new node");
+ BLI_addtail(&ntree->nodes, node);
+ node->typeinfo= ntype;
+ if(type>=NODE_DYNAMIC_MENU)
+ node->custom2= type; /* for node_dynamic_init */
+
+ if(ngroup)
+ BLI_strncpy(node->name, ngroup->id.name+2, NODE_MAXSTR);
+ else if(type>NODE_DYNAMIC_MENU) {
+ BLI_strncpy(node->name, ntype->id->name+2, NODE_MAXSTR);
+ }
+ else
+ BLI_strncpy(node->name, ntype->name, NODE_MAXSTR);
+ node->type= ntype->type;
+ node->flag= NODE_SELECT|ntype->flag;
+ node->width= ntype->width;
+ node->miniwidth= 42.0f; /* small value only, allows print of first chars */
+
+ if(type==NODE_GROUP)
+ node->id= (ID *)ngroup;
+
/* need init handler later? */
- /* got it-bob*/
- if(ntype->initfunc!=NULL)
- ntype->initfunc(node);
+ /* got it-bob*/
+ if(ntype->initfunc!=NULL)
+ ntype->initfunc(node);
+
+ nodeAddSockets(node, ntype);
+
+ return node;
+}
+
+void nodeMakeDynamicType(bNode *node)
+{
+ /* find SH_DYNAMIC_NODE ntype */
+ bNodeType *ntype= node_all_shaders.first;
+ while(ntype) {
+ if(ntype->type==NODE_DYNAMIC && ntype->id==NULL)
+ break;
+ ntype= ntype->next;
+ }
+
+ /* make own type struct to fill */
+ if(ntype) {
+ /*node->typeinfo= MEM_dupallocN(ntype);*/
+ bNodeType *newtype= MEM_callocN(sizeof(bNodeType), "dynamic bNodeType");
+ *newtype= *ntype;
+ newtype->name= BLI_strdup(ntype->name);
+ node->typeinfo= newtype;
+ }
+}
- return node;
+void nodeUpdateType(bNodeTree *ntree, bNode* node, bNodeType *ntype)
+{
+ verify_socket_list(ntree, &node->inputs, ntype->inputs);
+ verify_socket_list(ntree, &node->outputs, ntype->outputs);
}
/* keep socket listorder identical, for copying links */
/* ntree is the target tree */
-bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
+bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal)
{
bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node");
- bNodeSocket *sock;
+ bNodeSocket *sock, *oldsock;
*nnode= *node;
BLI_addtail(&ntree->nodes, nnode);
BLI_duplicatelist(&nnode->inputs, &node->inputs);
- for(sock= nnode->inputs.first; sock; sock= sock->next)
- sock->own_index= 0;
+ oldsock= node->inputs.first;
+ for(sock= nnode->inputs.first; sock; sock= sock->next, oldsock= oldsock->next) {
+ oldsock->new_sock= sock;
+ if(internal)
+ sock->own_index= 0;
+ }
BLI_duplicatelist(&nnode->outputs, &node->outputs);
- for(sock= nnode->outputs.first; sock; sock= sock->next) {
- sock->own_index= 0;
+ oldsock= node->outputs.first;
+ for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) {
+ if(internal)
+ sock->own_index= 0;
sock->stack_index= 0;
sock->ns.data= NULL;
+ oldsock->new_sock= sock;
}
if(nnode->id)
@@ -892,12 +1036,34 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
node->new_node= NULL;
if(internal_select==0 || (node->flag & NODE_SELECT)) {
- nnode= nodeCopyNode(newtree, node); /* sets node->new */
+ nnode= nodeCopyNode(newtree, node, internal_select); /* sets node->new */
if(internal_select) {
node->flag &= ~NODE_SELECT;
nnode->flag |= NODE_SELECT;
}
node->flag &= ~NODE_ACTIVE;
+
+ /* deselect original sockets */
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
+ }
+ for(sock= node->outputs.first; sock; sock= sock->next) {
+ if(sock->flag & SOCK_SEL) sock->flag&= ~SOCK_SEL;
+ }
+
+ /* set tree selin and selout to new sockets */
+ for(sock= nnode->inputs.first; sock; sock= sock->next) {
+ if(sock->flag & SOCK_SEL) {
+ ntree->selin= sock;
+ break;
+ }
+ }
+ for(sock= nnode->outputs.first; sock; sock= sock->next) {
+ if(sock->flag & SOCK_SEL) {
+ ntree->selout= sock;
+ break;
+ }
+ }
}
if(node==last) break;
}
@@ -941,7 +1107,7 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
/* ************** Free stuff ********** */
/* goes over entire tree */
-static void node_unlink_node(bNodeTree *ntree, bNode *node)
+void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
{
bNodeLink *link, *next;
bNodeSocket *sock;
@@ -985,7 +1151,7 @@ static void composit_free_node_cache(bNode *node)
void nodeFreeNode(bNodeTree *ntree, bNode *node)
{
- node_unlink_node(ntree, node);
+ nodeUnlinkNode(ntree, node);
BLI_remlink(&ntree->nodes, node);
/* since it is called while free database, node->id is undefined */
@@ -1003,6 +1169,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
if(node->typeinfo && node->typeinfo->freestoragefunc) {
node->typeinfo->freestoragefunc(node);
}
+
MEM_freeN(node);
}
@@ -1204,11 +1371,21 @@ bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
bNode *node;
if(ntree==NULL) return NULL;
+
+ /* check for group edit */
+ for(node= ntree->nodes.first; node; node= node->next)
+ if(node->flag & NODE_GROUP_EDIT)
+ break;
+
+ if(node)
+ ntree= (bNodeTree*)node->id;
+ /* now find active node with this id */
for(node= ntree->nodes.first; node; node= node->next)
if(node->id && GS(node->id->name)==idtype)
if(node->flag & NODE_ACTIVE_ID)
break;
+
return node;
}
@@ -1629,7 +1806,7 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group)
if(is_group==0) {
for(sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= ntree->stack[0] + sock->stack_index;
+ bNodeStack *ns= ntree->stack + sock->stack_index;
if(sock->ns.data) {
ns->data= sock->ns.data;
@@ -1662,7 +1839,7 @@ static void composit_end_exec(bNodeTree *ntree, int is_group)
bNodeSocket *sock;
for(sock= node->outputs.first; sock; sock= sock->next) {
- ns= ntree->stack[0] + sock->stack_index;
+ ns= ntree->stack + sock->stack_index;
if(ns->data) {
sock->ns.data= ns->data;
ns->data= NULL;
@@ -1680,7 +1857,7 @@ static void composit_end_exec(bNodeTree *ntree, int is_group)
if(is_group==0) {
/* internally, group buffers are not stored */
- for(ns= ntree->stack[0], a=0; a<ntree->stacksize; a++, ns++) {
+ for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) {
if(ns->data) {
printf("freed leftover buffer from stack\n");
free_compbuf(ns->data);
@@ -1721,15 +1898,47 @@ static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack)
/* per tree (and per group) unique indices are created */
/* the index_ext we need to be able to map from groups to the group-node own stack */
+typedef struct bNodeThreadStack {
+ struct bNodeThreadStack *next, *prev;
+ bNodeStack *stack;
+ int used;
+} bNodeThreadStack;
+
+static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread)
+{
+ ListBase *lb= &ntree->threadstack[thread];
+ bNodeThreadStack *nts;
+
+ for(nts=lb->first; nts; nts=nts->next) {
+ if(!nts->used) {
+ nts->used= 1;
+ return nts;
+ }
+ }
+
+ nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
+ nts->stack= MEM_dupallocN(ntree->stack);
+ nts->used= 1;
+ BLI_addtail(lb, nts);
+
+ return nts;
+}
+
+static void ntreeReleaseThreadStack(bNodeThreadStack *nts)
+{
+ nts->used= 0;
+}
+
void ntreeBeginExecTree(bNodeTree *ntree)
{
/* let's make it sure */
if(ntree->init & NTREE_EXEC_INIT)
return;
-
- /* allocate the stack pointer array */
- ntree->stack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(void *), "stack array");
-
+
+ /* allocate the thread stack listbase array */
+ if(ntree->type!=NTREE_COMPOSIT)
+ ntree->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array");
+
/* goes recursive over all groups */
ntree->stacksize= ntree_begin_exec_tree(ntree);
@@ -1739,7 +1948,7 @@ void ntreeBeginExecTree(bNodeTree *ntree)
int a;
/* allocate the base stack */
- ns=ntree->stack[0]= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack");
+ ns=ntree->stack= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack");
/* tag inputs, the get_stack() gives own socket stackdata if not in use */
for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1;
@@ -1749,7 +1958,7 @@ void ntreeBeginExecTree(bNodeTree *ntree)
bNodeSocket *sock;
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->link) {
- ns= ntree->stack[0] + sock->link->fromsock->stack_index;
+ ns= ntree->stack + sock->link->fromsock->stack_index;
ns->hasoutput= 1;
ns->sockettype= sock->link->fromsock->type;
}
@@ -1757,16 +1966,11 @@ void ntreeBeginExecTree(bNodeTree *ntree)
sock->ns.sockettype= sock->type;
}
if(node->type==NODE_GROUP && node->id)
- group_tag_used_outputs(node, ntree->stack[0]);
+ group_tag_used_outputs(node, ntree->stack);
}
- /* composite does 1 node per thread, so no multiple stacks needed */
if(ntree->type==NTREE_COMPOSIT)
composit_begin_exec(ntree, 0);
- else {
- for(a=1; a<BLENDER_MAX_THREADS; a++)
- ntree->stack[a]= MEM_dupallocN(ntree->stack[0]);
- }
}
ntree->init |= NTREE_EXEC_INIT;
@@ -1776,6 +1980,7 @@ void ntreeEndExecTree(bNodeTree *ntree)
{
if(ntree->init & NTREE_EXEC_INIT) {
+ bNodeThreadStack *nts;
int a;
/* another callback candidate! */
@@ -1783,14 +1988,21 @@ void ntreeEndExecTree(bNodeTree *ntree)
composit_end_exec(ntree, 0);
if(ntree->stack) {
- for(a=0; a<BLENDER_MAX_THREADS; a++)
- if(ntree->stack[a])
- MEM_freeN(ntree->stack[a]);
-
MEM_freeN(ntree->stack);
ntree->stack= NULL;
}
+ if(ntree->threadstack) {
+ for(a=0; a<BLENDER_MAX_THREADS; a++) {
+ for(nts=ntree->threadstack[a].first; nts; nts=nts->next)
+ if (nts->stack) MEM_freeN(nts->stack);
+ BLI_freelistN(&ntree->threadstack[a]);
+ }
+
+ MEM_freeN(ntree->threadstack);
+ ntree->threadstack= NULL;
+ }
+
ntree->init &= ~NTREE_EXEC_INIT;
}
}
@@ -1819,12 +2031,20 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
bNodeStack *stack;
+ bNodeThreadStack *nts = NULL;
/* only when initialized */
if((ntree->init & NTREE_EXEC_INIT)==0)
ntreeBeginExecTree(ntree);
- stack= ntree->stack[thread];
+ /* composite does 1 node per thread, so no multiple stacks needed */
+ if(ntree->type==NTREE_COMPOSIT) {
+ stack= ntree->stack;
+ }
+ else {
+ nts= ntreeGetThreadStack(ntree, thread);
+ stack= nts->stack;
+ }
for(node= ntree->nodes.first; node; node= node->next) {
if(node->typeinfo->execfunc) {
@@ -1836,10 +2056,34 @@ void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
node_group_execute(stack, callerdata, node, nsin, nsout);
}
}
+
+ if(nts)
+ ntreeReleaseThreadStack(nts);
}
/* ***************************** threaded version for execute composite nodes ************* */
+/* these are nodes without input, only giving values */
+/* or nodes with only value inputs */
+static int node_only_value(bNode *node)
+{
+ bNodeSocket *sock;
+
+ if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
+ return 1;
+
+ /* doing this for all node types goes wrong. memory free errors */
+ if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
+ int retval= 1;
+ for(sock= node->inputs.first; sock; sock= sock->next) {
+ if(sock->link)
+ retval &= node_only_value(sock->link->fromnode);
+ }
+ return retval;
+ }
+ return 0;
+}
+
/* not changing info, for thread callback */
typedef struct ThreadData {
@@ -1856,7 +2100,14 @@ static void *exec_composite_node(void *node_v)
node_get_stack(node, thd->stack, nsin, nsout);
- if(node->typeinfo->execfunc) {
+ if((node->flag & NODE_MUTED) && (!node_only_value(node))) {
+ /* viewers we execute, for feedback to user */
+ if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
+ else
+ node_compo_pass_on(node, nsin, nsout);
+ }
+ else if(node->typeinfo->execfunc) {
node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
}
else if(node->type==NODE_GROUP && node->id) {
@@ -1867,27 +2118,6 @@ static void *exec_composite_node(void *node_v)
return 0;
}
-/* these are nodes without input, only giving values */
-/* or nodes with only value inputs */
-static int node_only_value(bNode *node)
-{
- bNodeSocket *sock;
-
- if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
- return 1;
-
- /* doing this for all node types goes wrong. memory free errors */
- if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
- int retval= 1;
- for(sock= node->inputs.first; sock; sock= sock->next) {
- if(sock->link)
- retval &= node_only_value(sock->link->fromnode);
- }
- return retval;
- }
- return 0;
-}
-
/* return total of executable nodes, for timecursor */
/* only compositor uses it */
static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd)
@@ -2010,7 +2240,7 @@ static void freeExecutableNode(bNodeTree *ntree)
for(node= ntree->nodes.first; node; node= node->next) {
if(node->exec & NODE_FREEBUFS) {
for(sock= node->outputs.first; sock; sock= sock->next) {
- bNodeStack *ns= ntree->stack[0] + sock->stack_index;
+ bNodeStack *ns= ntree->stack + sock->stack_index;
if(ns->data) {
free_compbuf(ns->data);
ns->data= NULL;
@@ -2064,7 +2294,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
/* setup callerdata for thread callback */
thdata.rd= rd;
- thdata.stack= ntree->stack[0];
+ thdata.stack= ntree->stack;
/* fixed seed, for example noise texture */
BLI_srandom(rd->cfra);
@@ -2128,6 +2358,117 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
ntreeEndExecTree(ntree);
}
+/* GPU material from shader nodes */
+
+static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+ bNodeSocket *sock;
+ int i;
+
+ for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+ memset(&gs[i], 0, sizeof(gs[i]));
+
+ QUATCOPY(gs[i].vec, ns[i]->vec);
+ gs[i].link= ns[i]->data;
+
+ if (sock->type == SOCK_VALUE)
+ gs[i].type= GPU_FLOAT;
+ else if (sock->type == SOCK_VECTOR)
+ gs[i].type= GPU_VEC3;
+ else if (sock->type == SOCK_RGBA)
+ gs[i].type= GPU_VEC4;
+ else
+ gs[i].type= GPU_NONE;
+
+ gs[i].name = "";
+ gs[i].hasinput= ns[i]->hasinput && ns[i]->data;
+ gs[i].hasoutput= ns[i]->hasinput && ns[i]->data;
+ gs[i].sockettype= ns[i]->sockettype;
+ }
+
+ gs[i].type= GPU_NONE;
+}
+
+static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+{
+ bNodeSocket *sock;
+ int i;
+
+ for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
+ ns[i]->data= gs[i].link;
+ ns[i]->hasinput= gs[i].hasinput && gs[i].link;
+ ns[i]->hasoutput= gs[i].hasoutput;
+ ns[i]->sockettype= gs[i].sockettype;
+ }
+}
+
+static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out)
+{
+ bNode *node;
+ bNodeTree *ntree= (bNodeTree *)gnode->id;
+ bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
+ GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+ int doit = 0;
+
+ if(ntree==NULL) return;
+
+ stack+= gnode->stack_index;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->gpufunc) {
+ group_node_get_stack(node, stack, nsin, nsout, in, out);
+
+ doit = 0;
+
+ /* for groups, only execute outputs for edited group */
+ if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+ if(gnode->flag & NODE_GROUP_EDIT)
+ if(node->flag & NODE_DO_OUTPUT)
+ doit = 1;
+ }
+ else
+ doit = 1;
+
+ if(doit) {
+ gpu_from_node_stack(&node->inputs, nsin, gpuin);
+ gpu_from_node_stack(&node->outputs, nsout, gpuout);
+ if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+ data_from_gpu_stack(&node->outputs, nsout, gpuout);
+ }
+ }
+ }
+}
+
+void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
+{
+ bNode *node;
+ bNodeStack *stack;
+ bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
+ GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
+
+ if((ntree->init & NTREE_EXEC_INIT)==0)
+ ntreeBeginExecTree(ntree);
+
+ stack= ntree->stack;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->gpufunc) {
+ node_get_stack(node, stack, nsin, nsout);
+ gpu_from_node_stack(&node->inputs, nsin, gpuin);
+ gpu_from_node_stack(&node->outputs, nsout, gpuout);
+ if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
+ data_from_gpu_stack(&node->outputs, nsout, gpuout);
+ }
+ else if(node->type==NODE_GROUP && node->id) {
+ node_get_stack(node, stack, nsin, nsout);
+ gpu_node_group_execute(stack, mat, node, nsin, nsout);
+ }
+ }
+
+ ntreeEndExecTree(ntree);
+}
/* **************** call to switch lamploop for material node ************ */
@@ -2172,6 +2513,8 @@ static void force_hidden_passes(bNode *node, int passflag)
if(!(passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL;
sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
+ sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
+ if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
}
@@ -2281,12 +2624,12 @@ void ntreeCompositTagGenerators(bNodeTree *ntree)
/* ************* node definition init ********** */
-static bNodeType *is_nodetype_registered(ListBase *typelist, int type)
+static bNodeType *is_nodetype_registered(ListBase *typelist, int type, ID *id)
{
bNodeType *ntype= typelist->first;
for(;ntype; ntype= ntype->next )
- if(ntype->type==type)
+ if(ntype->type==type && ntype->id==id)
return ntype;
return NULL;
@@ -2295,10 +2638,10 @@ static bNodeType *is_nodetype_registered(ListBase *typelist, int type)
/* type can be from a static array, we make copy for duplicate types (like group) */
void nodeRegisterType(ListBase *typelist, const bNodeType *ntype)
{
- bNodeType *found= is_nodetype_registered(typelist, ntype->type);
+ bNodeType *found= is_nodetype_registered(typelist, ntype->type, ntype->id);
if(found==NULL) {
- bNodeType *ntypen= MEM_mallocN(sizeof(bNodeType), "node type");
+ bNodeType *ntypen= MEM_callocN(sizeof(bNodeType), "node type");
*ntypen= *ntype;
BLI_addtail(typelist, ntypen);
}
@@ -2335,6 +2678,8 @@ static void registerCompositNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &cmp_node_filter);
nodeRegisterType(ntypelist, &cmp_node_blur);
+ nodeRegisterType(ntypelist, &cmp_node_dblur);
+ nodeRegisterType(ntypelist, &cmp_node_bilateralblur);
nodeRegisterType(ntypelist, &cmp_node_vecblur);
nodeRegisterType(ntypelist, &cmp_node_dilateerode);
nodeRegisterType(ntypelist, &cmp_node_defocus);
@@ -2352,6 +2697,7 @@ static void registerCompositNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &cmp_node_combyuva);
nodeRegisterType(ntypelist, &cmp_node_sepycca);
nodeRegisterType(ntypelist, &cmp_node_combycca);
+ nodeRegisterType(ntypelist, &cmp_node_premulkey);
nodeRegisterType(ntypelist, &cmp_node_diff_matte);
nodeRegisterType(ntypelist, &cmp_node_chroma);
@@ -2366,7 +2712,6 @@ static void registerCompositNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &cmp_node_crop);
nodeRegisterType(ntypelist, &cmp_node_displace);
nodeRegisterType(ntypelist, &cmp_node_mapuv);
-
nodeRegisterType(ntypelist, &cmp_node_glare);
nodeRegisterType(ntypelist, &cmp_node_tonemap);
nodeRegisterType(ntypelist, &cmp_node_lensdist);
@@ -2393,12 +2738,46 @@ static void registerShaderNodes(ListBase *ntypelist)
nodeRegisterType(ntypelist, &sh_node_value);
nodeRegisterType(ntypelist, &sh_node_rgb);
nodeRegisterType(ntypelist, &sh_node_texture);
+ nodeRegisterType(ntypelist, &node_dynamic_typeinfo);
nodeRegisterType(ntypelist, &sh_node_invert);
nodeRegisterType(ntypelist, &sh_node_seprgb);
nodeRegisterType(ntypelist, &sh_node_combrgb);
nodeRegisterType(ntypelist, &sh_node_hue_sat);
}
+static void remove_dynamic_typeinfos(ListBase *list)
+{
+ bNodeType *ntype= list->first;
+ bNodeType *next= NULL;
+ while(ntype) {
+ next= ntype->next;
+ if(ntype->type==NODE_DYNAMIC && ntype->id!=NULL) {
+ BLI_remlink(list, ntype);
+ if(ntype->inputs) {
+ bNodeSocketType *sock= ntype->inputs;
+ while(sock->type!=-1) {
+ MEM_freeN(sock->name);
+ sock++;
+ }
+ MEM_freeN(ntype->inputs);
+ }
+ if(ntype->outputs) {
+ bNodeSocketType *sock= ntype->outputs;
+ while(sock->type!=-1) {
+ MEM_freeN(sock->name);
+ sock++;
+ }
+ MEM_freeN(ntype->outputs);
+ }
+ if(ntype->name) {
+ MEM_freeN(ntype->name);
+ }
+ MEM_freeN(ntype);
+ }
+ ntype= next;
+ }
+}
+
void init_nodesystem(void)
{
registerCompositNodes(&node_all_composit);
@@ -2407,8 +2786,8 @@ void init_nodesystem(void)
void free_nodesystem(void)
{
+ /*remove_dynamic_typeinfos(&node_all_composit);*/ /* unused for now */
BLI_freelistN(&node_all_composit);
+ remove_dynamic_typeinfos(&node_all_shaders);
BLI_freelistN(&node_all_shaders);
}
-
-