diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
commit | bdfe7d89e2f1292644577972c716931b4ce3c6c3 (patch) | |
tree | d00eb50b749cb001e2b08272c91791e66740b05d /source/blender/blenkernel/intern/node.c | |
parent | 78a1c27c4a6abe0ed31ca93ad21910f3df04da56 (diff) | |
parent | 7e4db234cee71ead34ee81a12e27da4bd548eb4b (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.c | 579 |
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); } - - |