From 16514e3ddb8500242931650c93f1397147442eba Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sat, 9 Feb 2008 23:17:15 +0000 Subject: * Merge of PyNodes to trunk. Finally! See http://wiki.blender.org/index.php/BlenderDev/PyNodes and http://wiki.blender.org/index.php/BlenderDev/PyNodes/API For current documentation. Very very big thanks go to William Germano for fixing the memory issues left and for improving on the code. In the coming time documentation will be finalised and further stabilising of PyNodes is to be expected. --- .../blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 645 ++++++++++++++++----- 1 file changed, 513 insertions(+), 132 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 1ba777a0533..c198e73a3bf 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -34,6 +34,7 @@ #include "DNA_text_types.h" #include "BKE_text.h" +#include "BKE_utildefines.h" #include "api2_2x/Node.h" #include "api2_2x/gen_utils.h" @@ -41,6 +42,9 @@ #include "../SHD_util.h" +static void node_dynamic_setup(bNode *node); +static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out); + static PyObject *init_dynamicdict(void) { PyObject *newscriptdict= PyDict_New(); PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins()); @@ -48,198 +52,575 @@ static PyObject *init_dynamicdict(void) { return newscriptdict; } +/* unused for now static void free_dynamicdict(PyObject *dict) { - if(dict!=NULL) { + if (dict!=NULL) { Py_DECREF(dict); } } +*/ -static void node_dynamic_init(bNode *node) { - NodeScriptDict *nsd= MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); - int type= node->custom2; - node->custom2= 0; - node->storage= nsd; - if(type>=NODE_DYNAMIC_MENU) { - if(type==NODE_DYNAMIC_MENU) { - nodeMakeDynamicType(node); - node->custom1= SH_NODE_DYNAMIC_NEW; - } else { - node->custom1= SH_NODE_DYNAMIC_ADDEXIST; +static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id) +{ + bNodeType *ntype = list->first; + + while(ntype) { + if (ntype->type == NODE_DYNAMIC && ntype->id == id) + break; + ntype = ntype->next; + } + + return ntype; /* NULL if doesn't exist */ +} + +static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo) +{ + bNodeSocketType *sock; + + if (!tinfo) return; + + if (tinfo->inputs) { + sock = tinfo->inputs; + while (sock->type != -1) { + MEM_freeN(sock->name); + sock++; + } + MEM_freeN(tinfo->inputs); + tinfo->inputs = NULL; + } + if (tinfo->outputs) { + sock = tinfo->outputs; + while (sock->type != -1) { + MEM_freeN(sock->name); + sock++; + } + MEM_freeN(tinfo->outputs); + tinfo->outputs = NULL; + } +} + +static void node_dynamic_free_typeinfo(bNodeType *tinfo) +{ + if (!tinfo) return; + + node_dynamic_free_typeinfo_sockets(tinfo); + + if (tinfo->name) { MEM_freeN(tinfo->name); } + + MEM_freeN(tinfo); +} + +static void node_dynamic_free_sockets(bNode *node) +{ + BLI_freelistN(&node->inputs); + BLI_freelistN(&node->outputs); +} + +/* For now we just remove the socket links. It's the safest + * route, since an update in the script may change completely the + * inputs and outputs. Trying to recreate the node links would be + * nicer for pynode authors, though. */ +static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree) +{ + if (ntree) { + nodeVerifyType(ntree, node); + } + else { + Material *ma; + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd == node) nodeVerifyType(ma->nodetree, node); + } + } } - node->id= node->typeinfo->id; - nodeDynamicParse(node); - } else { - if(node->custom1== SH_NODE_DYNAMIC_LOADED) { - nodeMakeDynamicType(node); - nodeDynamicParse(node); - } else if(node->custom1== SH_NODE_DYNAMIC_ADDEXIST) - nodeDynamicParse(node); } } -static void node_dynamic_free(bNode *node) +static void node_dynamic_free_storage_cb(bNode *node) { - NodeScriptDict *nsd= (NodeScriptDict *)(node->storage); - BPy_Node *pynode= nsd->node; - Py_XDECREF(pynode); - free_dynamicdict((PyObject *)(nsd->dict)); + NodeScriptDict *nsd; + PyObject *pydict; + BPy_Node *pynode; + + if (!node->storage) return; + + nsd = (NodeScriptDict *)(node->storage); + pydict = nsd->dict; + if (pydict) { + Py_DECREF(pydict); + } + pynode = nsd->node; + if (pynode) { + Py_DECREF(pynode); + } MEM_freeN(node->storage); + node->storage = NULL; } -static void node_dynamic_copy(bNode *orig_node, bNode *new_node) +/* Disable pynode when its script fails */ +static void node_dynamic_disable(bNode *node) { - NodeScriptDict *nsd= (NodeScriptDict *)(orig_node->storage); - new_node->storage= MEM_dupallocN(orig_node->storage); - if(nsd->node) - Py_INCREF((PyObject *)(nsd->node)); - if(nsd->dict) - Py_INCREF((PyObject *)(nsd->dict)); + node->custom1 = 0; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR); } -static void node_dynamic_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { - BPy_Node *mynode = NULL; - NodeScriptDict *nsd = NULL; - PyObject *pyresult = NULL; - PyObject *args = NULL; - ShadeInput *shi= ((ShaderCallData *)data)->shi; +/* Disable all pynodes using the given text (script) id */ +static void node_dynamic_disable_all_by_id(ID *id) +{ + Material *ma; /* XXX hardcoded for shaders */ - if(node->custom1==SH_NODE_DYNAMIC_NEW) { - nodeDynamicParse(node); - return; + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + bNodeTree *ntree = ma->nodetree; + for (nd= ntree->nodes.first; nd; nd= nd->next) { + if (nd->id == id) { + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR); + } + } + } } +} - if(node->custom2<0) - return; +static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb) +{ + bNodeLink *link, *next; + bNodeSocket *sock; - if(node->custom1==SH_NODE_DYNAMIC_READY || node->custom1==SH_NODE_DYNAMIC_UPDATED) { - if(node->custom1== SH_NODE_DYNAMIC_UPDATED) - node->custom1= SH_NODE_DYNAMIC_READY; + if (!lb) return; - nsd = (NodeScriptDict *)node->storage; + for (sock= lb->first; sock; sock= sock->next) { + for (link= ntree->links.first; link; link= next) { + next= link->next; + if (link->fromsock==sock || link->tosock==sock) { + nodeRemLink(ntree, link); + } + } + } +} - mynode = (BPy_Node *)(nsd->node); - if(mynode && PyCallable_Check((PyObject *)mynode)) { - mynode->node= node; - Node_SetStack(mynode, in, NODE_INPUTSTACK); - Node_SetStack(mynode, out, NODE_OUTPUTSTACK); - Node_SetShi(mynode, shi); - args=Py_BuildValue("()"); - pyresult= PyObject_Call((PyObject *)mynode, args, NULL); - if(!pyresult) { - if(PyErr_Occurred()) { - PyErr_Print(); - node->custom2= -1; - } else { - printf("PyObject_Call __call__ failed\n"); +/* XXX hardcoded for shaders */ +static void node_dynamic_rem_all_links(bNodeType *tinfo) +{ + Material *ma; + int in, out; + + in = tinfo->inputs ? 1 : 0; + out = tinfo->outputs ? 1 : 0; + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + bNodeTree *ntree = ma->nodetree; + for (nd= ntree->nodes.first; nd; nd= nd->next) { + if (nd->typeinfo == tinfo) { + if (in) + node_rem_socklist_links(ntree, &nd->inputs); + if (out) + node_rem_socklist_links(ntree, &nd->outputs); + } + } + } + } +} + +/* node_dynamic_reset: clean a pynode, getting rid of all + * data dynamically created for it. + * ntree is used only in a special case: for working pynodes + * that were saved on a .blend but fail for some reason when + * the file is opened. We need it because pynodes are initialized + * before G.main. */ +static void node_dynamic_reset(bNode *node, bNodeTree *ntree) +{ + bNodeType *tinfo, *tinfo_default; + Material *ma; + + tinfo = node->typeinfo; + tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL); + + node_dynamic_rem_all_links(tinfo); + node_dynamic_free_typeinfo_sockets(tinfo); + + if (!ntree) { node_dynamic_free_sockets(node); } + + //wnode_dynamic_update_socket_links(node, ntree); + node_dynamic_free_storage_cb(node); + + /* XXX hardcoded for shaders: */ + if (node->typeinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } + + node->typeinfo = tinfo_default; + + /* reset all other XXX shader nodes sharing this typeinfo */ + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd->typeinfo == tinfo) { + node_dynamic_free_storage_cb(nd); + node_dynamic_free_sockets(nd); + nd->typeinfo = tinfo_default; } } - Py_XDECREF(pyresult); - Py_DECREF(args); } } + + node_dynamic_free_typeinfo(tinfo); } -void nodeDynamicParse(struct bNode *node) +int nodeDynamicUnlinkText(ID *txtid) { + Material *ma; + int unlinked= 0; + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd, *nd2 = NULL; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) { + nd->id = NULL; + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); + BLI_strncpy(nd->name, "Dynamic", 8); + nd2 = nd; /* so we have a ptr to one of them */ + unlinked++; + } + } + /* clean uneeded dynamic data from all nodes that shared + * this text: */ + if (nd2) node_dynamic_reset(nd2, NULL); + } + } + + return unlinked; +} + +static void node_dynamic_pyerror_print(bNode *node) +{ + fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name); + if (PyErr_Occurred()) { PyErr_Print(); } + else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); } +} + +static int node_dynamic_parse(struct bNode *node) { - BPy_Node *pynode= NULL; PyObject *dict= NULL; PyObject *key= NULL; PyObject *value= NULL; - PyObject *testinst= NULL; + PyObject *pynode= NULL; PyObject *args= NULL; - int pos = 0; - NodeScriptDict *nsd= NULL; + NodeScriptDict *nsd = NULL; PyObject *pyresult = NULL; - PyObject *pycompiled = NULL; - Text *txt = NULL; - char *buf= NULL; + char *buf = NULL; + int pos = 0, is_valid_script = 0; + + if (!node->id || !node->storage) + return 0; - if(! node->id) { + /* READY, no need to be here */ + if (BTST(node->custom1, NODE_DYNAMIC_READY)) + return 0; + + nsd = (NodeScriptDict *)node->storage; + + dict = (PyObject *)(nsd->dict); + buf = txt_to_buf((Text *)node->id); + + pyresult = PyRun_String(buf, Py_file_input, dict, dict); + + MEM_freeN(buf); + + if (!pyresult) { + node_dynamic_disable(node); + node_dynamic_pyerror_print(node); + return -1; + } + + Py_DECREF(pyresult); + + while (PyDict_Next( (PyObject *)(nsd->dict), &pos, &key, &value)) { + /* look for the node object */ + if (PyObject_TypeCheck(value, &PyType_Type)==1) { + BPy_NodeSockets *sockets = Node_CreateSockets(node); + + args = Py_BuildValue("(O)", sockets); + + /* init it to get the input and output sockets */ + pynode = PyObject_Call(value, args, NULL); + + Py_DECREF(sockets); + Py_DECREF(args); + + if (!PyErr_Occurred() && pynode && PyObject_TypeCheck(pynode, &Node_Type)==1) { + InitNode((BPy_Node *)(pynode), node); + nsd->node = pynode; + node->typeinfo->execfunc = node_dynamic_exec_cb; + is_valid_script = 1; + + /* for NEW, LOADED, REPARSE */ + if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { + node->typeinfo->pydict = dict; + node->typeinfo->pynode = pynode; + node->typeinfo->id = node->id; + nodeAddSockets(node, node->typeinfo); + if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE)) { + nodeRegisterType(&node_all_shaders, node->typeinfo); + /* nodeRegisterType copied it to a new one, so we + * free the typeinfo itself, but not what it + * points to: */ + MEM_freeN(node->typeinfo); + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id); + MEM_freeN(node->typeinfo->name); + node->typeinfo->name = BLI_strdup(node->name); + } + } + + node->custom1 = 0; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); + break; + } + break; + } + } + + if (!is_valid_script) { /* not a valid pynode script */ + node_dynamic_disable(node); + node_dynamic_pyerror_print(node); + return -1; + } + + return 0; +} + +/* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY) + * pynodes already linked to a script (node->id != NULL). */ +static void node_dynamic_setup(bNode *node) +{ + NodeScriptDict *nsd = NULL; + bNodeTree *nodetree = NULL; + bNodeType *ntype = NULL; + + /* Possible cases: + * NEW + * ADDEXIST + * LOADED + * REPARSE + * ERROR + * READY + */ + + /* NEW, but not linked to a script: link default (empty) typeinfo */ + if (!node->id) { + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, + NULL); return; } - if(node->custom1!=SH_NODE_DYNAMIC_READY) { - txt = (Text *)node->id; - nsd = (NodeScriptDict *)node->storage; + /* READY, no need to be here */ + if (BTST(node->custom1, NODE_DYNAMIC_READY)) + return; - if(nsd->dict==NULL && (node->custom1==SH_NODE_DYNAMIC_NEW||node->custom1==SH_NODE_DYNAMIC_LOADED)) { - nsd->dict= init_dynamicdict(); - } else if(nsd->dict==NULL && node->custom1==SH_NODE_DYNAMIC_ADDEXIST) { - nsd->dict= node->typeinfo->pydict; - nsd->node= node->typeinfo->pynode; - Py_INCREF((PyObject *)(nsd->dict)); - Py_INCREF((PyObject *)(nsd->node)); - node->custom1= SH_NODE_DYNAMIC_READY; + /* ERROR, reset to (empty) defaults */ + if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) { + node_dynamic_reset(node, NULL); + return; + } + + /* User asked to update this pynode, prepare it for reparsing */ + if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) { + int needs_parsing = 1; + + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); + + if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE); + ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id); + + if (ntype) { + node->typeinfo = ntype; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR); + needs_parsing = 0; + } + else { nodeMakeDynamicType(node); } + + } else { + node_dynamic_free_typeinfo_sockets(node->typeinfo); + node_dynamic_update_socket_links(node, NULL); + node_dynamic_free_storage_cb(node); + } + + if (needs_parsing) { + nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); + nsd->dict = init_dynamicdict(); + node->storage = nsd; + /* prepared, now reparse: */ + node_dynamic_parse(node); return; } - dict= (PyObject *)(nsd->dict); + } + else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) { + /* when loading from a .blend we don't have G.main yet, so we + * quickly abuse node->storage in ntreeInitTypes (node.c) to have + * our nodetree ptr (needed if a pynode script that worked before + * saving the .blend for some reason fails upon loading): */ + nodetree = (bNodeTree *)node->storage; + node->storage = NULL; + } - if(node->custom1!=SH_NODE_DYNAMIC_ADDEXIST) { - buf = txt_to_buf( txt ); - /*printf("Running script (%s, %d)...", node->name, node->custom1);*/ - pyresult = PyRun_String(buf, Py_file_input, dict, dict); - /*printf(" done\n");*/ + if (node->storage) + fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n"); - MEM_freeN(buf); + nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); + node->storage = nsd; + + /* NEW, LOADED or REPARSE */ + if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { + /* check if there's already a bNodeType linked to this script */ + /* (XXX hardcoded for shader nodes for now) */ + ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id); - if(!pyresult) { - if(PyErr_Occurred()) { - PyErr_Print(); - } - Py_XDECREF(pyresult); - return; + if (ntype) { /* if so, reuse it */ + node->typeinfo = ntype; + /* so this is actually an ADDEXIST type */ + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); + } + else { /* create bNodeType for this pynode */ + nodeMakeDynamicType(node); + nsd->dict = init_dynamicdict(); + if ((node_dynamic_parse(node) == -1) && nodetree) { + node_dynamic_reset(node, nodetree); } + return; + } + } - Py_DECREF(pyresult); + /* ADDEXIST: new pynode linked to an already registered dynamic type, + * we just reuse existing py dict and pynode */ + nsd->dict = node->typeinfo->pydict; + nsd->node = node->typeinfo->pynode; + Py_INCREF((PyObject *)(nsd->dict)); + Py_INCREF((PyObject *)(nsd->node)); - while(PyDict_Next( (PyObject *)(nsd->dict), &pos, &key, &value) ) { - if(PyObject_TypeCheck(value, &PyType_Type)==1) { - BPy_DefinitionMap *outputdef= Node_CreateOutputDefMap(node); - BPy_DefinitionMap *inputdef= Node_CreateInputDefMap(node); - - args= Py_BuildValue("(OO)", inputdef, outputdef); - testinst= PyObject_Call(value, args, NULL); - - Py_DECREF(outputdef); - Py_DECREF(inputdef); - if(testinst && PyObject_TypeCheck(testinst, &Node_Type)==1) { - Py_INCREF(testinst); - Py_INCREF(dict); - InitNode((BPy_Node *)(testinst), node); - nsd->node= testinst; - node->typeinfo->execfunc= node_dynamic_exec; - if(node->custom1== SH_NODE_DYNAMIC_NEW || node->custom1== SH_NODE_DYNAMIC_LOADED) { - node->typeinfo->pynode= testinst; - node->typeinfo->pydict= nsd->dict; - node->typeinfo->id= node->id; - nodeAddSockets(node, node->typeinfo); - nodeRegisterType(&node_all_shaders, node->typeinfo); - node->custom1= SH_NODE_DYNAMIC_READY; - } - break; - } - Py_DECREF(args); - } - } + if (BTST(node->custom1, NODE_DYNAMIC_NEW)) { + nodeAddSockets(node, node->typeinfo); + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW); + } + + node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST); + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); + + return; +} + +/* node_dynamic_init_cb callback: called when a pynode is created. + * The pynode type is passed via node->custom2. It can be: + * 0: for loaded empty nodes + * NODE_DYNAMIC_MENU: for the default Dynamic node type + * > NODE_DYNAMIC_MENU: for the new types defined by scripts +*/ +static void node_dynamic_init_cb(bNode *node) { + int type = node->custom2; + + node->custom2 = 0; + + if (type >= NODE_DYNAMIC_MENU) { + node->custom1 = 0; + + if (type == NODE_DYNAMIC_MENU) { + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); + return; } + + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); + node->id = node->typeinfo->id; } + + node_dynamic_setup(node); } +/* node_dynamic_copy_cb: pynode copy callback */ +static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) +{ + NodeScriptDict *nsd; + + if (!orig_node->storage) return; + + nsd = (NodeScriptDict *)(orig_node->storage); + new_node->storage = MEM_dupallocN(orig_node->storage); + + if (nsd->node) + Py_INCREF((PyObject *)(nsd->node)); + if (nsd->dict) + Py_INCREF((PyObject *)(nsd->dict)); +} + +/* node_dynamic_exec_cb: the execution callback called per pixel + * during rendering. */ +static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { + BPy_Node *mynode = NULL; + NodeScriptDict *nsd = NULL; + PyObject *pyresult = NULL; + PyObject *args = NULL; + ShadeInput *shi; + + if (!node->id) + return; + + if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) { + node_dynamic_setup(node); + return; + } + + if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { + if (node->storage) node_dynamic_setup(node); + return; + } + + if (BTST(node->custom1, NODE_DYNAMIC_READY)) { + nsd = (NodeScriptDict *)node->storage; + + mynode = (BPy_Node *)(nsd->node); + if (mynode && PyCallable_Check((PyObject *)mynode)) { + mynode->node = node; + shi = ((ShaderCallData *)data)->shi; + + Node_SetStack(mynode, in, NODE_INPUTSTACK); + Node_SetStack(mynode, out, NODE_OUTPUTSTACK); + Node_SetShi(mynode, shi); + + args=Py_BuildValue("()"); + pyresult= PyObject_Call((PyObject *)mynode, args, NULL); + Py_DECREF(args); + + if (!pyresult) { + node_dynamic_disable_all_by_id(node->id); + node_dynamic_pyerror_print(node); + node_dynamic_setup(node); + return; + } + Py_DECREF(pyresult); + } + } +} -bNodeType sh_node_dynamic = { +bNodeType node_dynamic_typeinfo = { /* next, prev */ NULL, NULL, - /* type code */ SH_NODE_DYNAMIC, + /* type code */ NODE_DYNAMIC, /* name */ "Dynamic", /* width+range */ 150, 60, 300, /* class+opts */ NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS, /* input sock */ NULL, /* output sock */ NULL, /* storage */ "NodeScriptDict", - /* execfunc */ node_dynamic_exec, + /* execfunc */ node_dynamic_exec_cb, /* butfunc */ NULL, - /* initfunc */ node_dynamic_init, - /* freefunc */ node_dynamic_free, - /* copyfunc */ node_dynamic_copy, + /* initfunc */ node_dynamic_init_cb, + /* freefunc */ node_dynamic_free_storage_cb, + /* copyfunc */ node_dynamic_copy_cb, /* id */ NULL }; -- cgit v1.2.3 From f46fcf7aab30fa2c905840e4ad0d4f1486994285 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Sun, 10 Feb 2008 03:40:24 +0000 Subject: == PyNodes == 1) Including the Add->Dynamic submenu in the Nodes window header. Previously pynodes could only be added via toolbox. 2) Disabling pynodes execution when using more than one thread for rendering. This prevents the crashes while a proper fix isn't implemented. --- source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index c198e73a3bf..9c15877e478 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -570,6 +570,9 @@ static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNode if (!node->id) return; + if (G.scene->r.threads > 1) + return; + if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) { node_dynamic_setup(node); return; -- cgit v1.2.3 From 9d7ef684e3ad699bd8aeb3324cfae2c98871e5e3 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 10 Feb 2008 18:48:29 +0000 Subject: * remove redundant define. --- source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 9c15877e478..3b9ef5ceb55 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -27,8 +27,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef USE_PYNODES /* note: won't work without patch */ - #include #include @@ -627,5 +625,3 @@ bNodeType node_dynamic_typeinfo = { /* id */ NULL }; -#endif /* USE_PYNODES */ - -- cgit v1.2.3 From a4e27a689ac197935dcd08d1917fb0f328ba3989 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 10 Feb 2008 20:16:35 +0000 Subject: added PyNode includes for Makefiles --- source/blender/nodes/intern/SHD_nodes/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index 0ab6134ac93..04e042cee76 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -38,6 +38,8 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I../../../python CPPFLAGS += -I../../../blenkernel CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../../makesdna -- cgit v1.2.3 From 9615532ccb8290492bf076cdc7ad7a6ecb9d9311 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Sun, 10 Feb 2008 21:12:44 +0000 Subject: == Pynodes == 1) Trying to bring back compatibility with Python2.3. 2) Adding some stubs to compile blender player again on linux. Please tell me if Blender still doesn't compile with py 2.3 or if the player isn't compiling. There was a binreloc related stub I needed to add, so probably the player wasn't compiling before the pynodes commit. Thanks PanzerMKZ for reporting and testing part of the fix to py 2.3. --- source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 3b9ef5ceb55..4c4044f6bce 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -28,6 +28,7 @@ */ #include +#include #include #include "DNA_text_types.h" @@ -352,7 +353,7 @@ static int node_dynamic_parse(struct bNode *node) Py_DECREF(sockets); Py_DECREF(args); - if (!PyErr_Occurred() && pynode && PyObject_TypeCheck(pynode, &Node_Type)==1) { + if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) { InitNode((BPy_Node *)(pynode), node); nsd->node = pynode; node->typeinfo->execfunc = node_dynamic_exec_cb; -- cgit v1.2.3 From df0d81f3c7ae91cad0bc612cdf49753ea661299b Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 12 Feb 2008 18:56:32 +0000 Subject: * fix provided by Stefan Birgmeier (qwequ777): int pos may lead to crashes on 64-bit systems. PyDict_Next takes a Py_ssize_t, not an int (tsk tsk). --- source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 4c4044f6bce..1d1cf3d7e23 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -314,7 +314,8 @@ static int node_dynamic_parse(struct bNode *node) NodeScriptDict *nsd = NULL; PyObject *pyresult = NULL; char *buf = NULL; - int pos = 0, is_valid_script = 0; + Py_ssize_t pos = 0; + int is_valid_script = 0; if (!node->id || !node->storage) return 0; -- cgit v1.2.3 From 012f0a336c84b22c3e20716e4820f3342afef5d3 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sat, 23 Feb 2008 12:05:28 +0000 Subject: === PyNodes === * Make PyNodes work with threaded renderer. This patch is by Willian. He has worked hard on getting this sorted out - now you should be able to render with PyNodes AND multiple threads. --- .../blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 176 +++++++++++++++++---- 1 file changed, 142 insertions(+), 34 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 1d1cf3d7e23..ec3a9f3e5d6 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -43,11 +43,19 @@ static void node_dynamic_setup(bNode *node); static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out); +static void node_dynamic_free_storage_cb(bNode *node); static PyObject *init_dynamicdict(void) { - PyObject *newscriptdict= PyDict_New(); + PyObject *newscriptdict; + PyGILState_STATE gilstate = PyGILState_Ensure(); + + newscriptdict= PyDict_New(); + PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins()); EXPP_dict_set_item_str(newscriptdict, "__name__", PyString_FromString("__main__")); + + PyGILState_Release(gilstate); + return newscriptdict; } @@ -228,12 +236,8 @@ static void node_dynamic_rem_all_links(bNodeType *tinfo) } /* node_dynamic_reset: clean a pynode, getting rid of all - * data dynamically created for it. - * ntree is used only in a special case: for working pynodes - * that were saved on a .blend but fail for some reason when - * the file is opened. We need it because pynodes are initialized - * before G.main. */ -static void node_dynamic_reset(bNode *node, bNodeTree *ntree) + * data dynamically created for it. */ +static void node_dynamic_reset(bNode *node, int unlink_text) { bNodeType *tinfo, *tinfo_default; Material *ma; @@ -244,16 +248,6 @@ static void node_dynamic_reset(bNode *node, bNodeTree *ntree) node_dynamic_rem_all_links(tinfo); node_dynamic_free_typeinfo_sockets(tinfo); - if (!ntree) { node_dynamic_free_sockets(node); } - - //wnode_dynamic_update_socket_links(node, ntree); - node_dynamic_free_storage_cb(node); - - /* XXX hardcoded for shaders: */ - if (node->typeinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } - - node->typeinfo = tinfo_default; - /* reset all other XXX shader nodes sharing this typeinfo */ for (ma= G.main->mat.first; ma; ma= ma->id.next) { if (ma->nodetree) { @@ -263,45 +257,129 @@ static void node_dynamic_reset(bNode *node, bNodeTree *ntree) node_dynamic_free_storage_cb(nd); node_dynamic_free_sockets(nd); nd->typeinfo = tinfo_default; + if (unlink_text) { + nd->id = NULL; + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); + BLI_strncpy(nd->name, "Dynamic", 8); + } } } } } + /* XXX hardcoded for shaders: */ + if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } + node_dynamic_free_typeinfo(tinfo); +} + +/* Special case of the above function: for working pynodes + * that were saved on a .blend but fail for some reason when + * the file is opened. We need this because pynodes are initialized + * before G.main. */ +static void node_dynamic_reset_loaded(bNode *node) +{ + bNodeType *tinfo = node->typeinfo; + + node_dynamic_rem_all_links(tinfo); + node_dynamic_free_typeinfo_sockets(tinfo); + node_dynamic_free_storage_cb(node); + /* XXX hardcoded for shaders: */ + if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } + node_dynamic_free_typeinfo(tinfo); + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL); } int nodeDynamicUnlinkText(ID *txtid) { Material *ma; - int unlinked= 0; + bNode *nd; + /* find one node that uses this text */ for (ma= G.main->mat.first; ma; ma= ma->id.next) { if (ma->nodetree) { - bNode *nd, *nd2 = NULL; for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) { - nd->id = NULL; + node_dynamic_reset(nd, 1); /* found, reset all */ + return 1; + } + } + } + } + return 0; /* no pynodes used this text */ +} + +/* +static void node_dynamic_free_all_typeinfos(ListBase *list) +{ + bNodeType *ntype, *ntnext; + + ntype = list->first; + + while (ntype) { + ntnext = ntype->next; + if (ntype->type == NODE_DYNAMIC && ntype->id) { + BLI_remlink(list, ntype); + node_dynamic_free_typeinfo_sockets(ntype); + node_dynamic_free_typeinfo(ntype); + } + ntype = ntnext; + } +} +*/ +/* Unload all pynodes: since the Game Engine restarts Python, we need + * to recreate pynodes dicts and objects. First we get rid of them here: */ +/* +void nodeDynamicUnloadAll(void) +{ + Material *ma; + bNode *nd; + PyGILState_STATE gilstate = PyGILState_Ensure(); + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if ((nd->type == NODE_DYNAMIC) && nd->id) { + node_dynamic_free_storage_cb(nd); + nd->typeinfo = NULL; nd->custom1 = 0; - nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); - BLI_strncpy(nd->name, "Dynamic", 8); - nd2 = nd; /* so we have a ptr to one of them */ - unlinked++; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_LOADED); } } - /* clean uneeded dynamic data from all nodes that shared - * this text: */ - if (nd2) node_dynamic_reset(nd2, NULL); } } - return unlinked; + node_dynamic_free_all_typeinfos(&node_all_shaders); + + PyGILState_Release(gilstate); +} + +void nodeDynamicReloadAll(void) +{ + Material *ma; + bNode *nd; + + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if ((nd->type == NODE_DYNAMIC) && nd->id) { + node_dynamic_setup(nd); + } + } + } + } } +*/ static void node_dynamic_pyerror_print(bNode *node) { + PyGILState_STATE gilstate = PyGILState_Ensure(); + fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name); if (PyErr_Occurred()) { PyErr_Print(); } else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); } + + PyGILState_Release(gilstate); } static int node_dynamic_parse(struct bNode *node) @@ -316,6 +394,7 @@ static int node_dynamic_parse(struct bNode *node) char *buf = NULL; Py_ssize_t pos = 0; int is_valid_script = 0; + PyGILState_STATE gilstate; if (!node->id || !node->storage) return 0; @@ -324,6 +403,9 @@ static int node_dynamic_parse(struct bNode *node) if (BTST(node->custom1, NODE_DYNAMIC_READY)) return 0; + /* for threading */ + gilstate = PyGILState_Ensure(); + nsd = (NodeScriptDict *)node->storage; dict = (PyObject *)(nsd->dict); @@ -336,6 +418,7 @@ static int node_dynamic_parse(struct bNode *node) if (!pyresult) { node_dynamic_disable(node); node_dynamic_pyerror_print(node); + PyGILState_Release(gilstate); return -1; } @@ -365,7 +448,8 @@ static int node_dynamic_parse(struct bNode *node) node->typeinfo->pydict = dict; node->typeinfo->pynode = pynode; node->typeinfo->id = node->id; - nodeAddSockets(node, node->typeinfo); + if (BNTST(node->custom1, NODE_DYNAMIC_LOADED)) + nodeAddSockets(node, node->typeinfo); if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE)) { nodeRegisterType(&node_all_shaders, node->typeinfo); /* nodeRegisterType copied it to a new one, so we @@ -386,6 +470,8 @@ static int node_dynamic_parse(struct bNode *node) } } + PyGILState_Release(gilstate); + if (!is_valid_script) { /* not a valid pynode script */ node_dynamic_disable(node); node_dynamic_pyerror_print(node); @@ -402,6 +488,7 @@ static void node_dynamic_setup(bNode *node) NodeScriptDict *nsd = NULL; bNodeTree *nodetree = NULL; bNodeType *ntype = NULL; + PyGILState_STATE gilstate; /* Possible cases: * NEW @@ -423,9 +510,12 @@ static void node_dynamic_setup(bNode *node) if (BTST(node->custom1, NODE_DYNAMIC_READY)) return; + gilstate = PyGILState_Ensure(); + /* ERROR, reset to (empty) defaults */ if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) { - node_dynamic_reset(node, NULL); + node_dynamic_reset(node, 0); + PyGILState_Release(gilstate); return; } @@ -459,6 +549,7 @@ static void node_dynamic_setup(bNode *node) node->storage = nsd; /* prepared, now reparse: */ node_dynamic_parse(node); + PyGILState_Release(gilstate); return; } } @@ -492,8 +583,9 @@ static void node_dynamic_setup(bNode *node) nodeMakeDynamicType(node); nsd->dict = init_dynamicdict(); if ((node_dynamic_parse(node) == -1) && nodetree) { - node_dynamic_reset(node, nodetree); + node_dynamic_reset_loaded(node); } + PyGILState_Release(gilstate); return; } } @@ -502,6 +594,7 @@ static void node_dynamic_setup(bNode *node) * we just reuse existing py dict and pynode */ nsd->dict = node->typeinfo->pydict; nsd->node = node->typeinfo->pynode; + Py_INCREF((PyObject *)(nsd->dict)); Py_INCREF((PyObject *)(nsd->node)); @@ -513,6 +606,8 @@ static void node_dynamic_setup(bNode *node) node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST); node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); + PyGILState_Release(gilstate); + return; } @@ -546,16 +641,21 @@ static void node_dynamic_init_cb(bNode *node) { static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) { NodeScriptDict *nsd; + PyGILState_STATE gilstate; if (!orig_node->storage) return; nsd = (NodeScriptDict *)(orig_node->storage); new_node->storage = MEM_dupallocN(orig_node->storage); + gilstate = PyGILState_Ensure(); + if (nsd->node) Py_INCREF((PyObject *)(nsd->node)); if (nsd->dict) Py_INCREF((PyObject *)(nsd->dict)); + + PyGILState_Release(gilstate); } /* node_dynamic_exec_cb: the execution callback called per pixel @@ -566,12 +666,13 @@ static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNode PyObject *pyresult = NULL; PyObject *args = NULL; ShadeInput *shi; + PyGILState_STATE gilstate; if (!node->id) return; - if (G.scene->r.threads > 1) - return; + /*if (G.scene->r.threads > 1) + return;*/ if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) { node_dynamic_setup(node); @@ -585,9 +686,13 @@ static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNode if (BTST(node->custom1, NODE_DYNAMIC_READY)) { nsd = (NodeScriptDict *)node->storage; - mynode = (BPy_Node *)(nsd->node); + + if (mynode && PyCallable_Check((PyObject *)mynode)) { + + gilstate = PyGILState_Ensure(); + mynode->node = node; shi = ((ShaderCallData *)data)->shi; @@ -600,12 +705,14 @@ static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNode Py_DECREF(args); if (!pyresult) { + PyGILState_Release(gilstate); node_dynamic_disable_all_by_id(node->id); node_dynamic_pyerror_print(node); node_dynamic_setup(node); return; } Py_DECREF(pyresult); + PyGILState_Release(gilstate); } } } @@ -627,3 +734,4 @@ bNodeType node_dynamic_typeinfo = { /* id */ NULL }; + -- cgit v1.2.3 From dae503187c9c77a6f51bc4cb7bad81e78590b692 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Sun, 16 Mar 2008 17:24:29 +0000 Subject: == PyNodes == Ongoing updates to the Blender.Node Python API: - Changed Blender.Node.node to Blender.Node.Scripted to be more specific and conform to bpython API. - Added a Blender.Node.Socket type to be used to define node sockets in a PyNode script. Also, socket type is inferred from the value(s) passed in, instead of also being defined by the script author. - Added attr access to input and output sockets in the __call__ method. Ex: an input socket called 'color' can be accessed as self.input.color now. These changes break existing pynode scripts, which shouldn't be a problem yet, of course, since we're still finishing this feature for 2.46. The wiki page and sample .blends have already been updated: http://wiki.blender.org/index.php/BlenderDev/PyNodes http://wiki.blender.org/index.php/BlenderDev/PyNodes/API --- .../blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 80 ++-------------------- 1 file changed, 6 insertions(+), 74 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index ec3a9f3e5d6..36a3bd5b171 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -59,14 +59,6 @@ static PyObject *init_dynamicdict(void) { return newscriptdict; } -/* unused for now -static void free_dynamicdict(PyObject *dict) { - if (dict!=NULL) { - Py_DECREF(dict); - } -} -*/ - static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id) { bNodeType *ntype = list->first; @@ -309,68 +301,6 @@ int nodeDynamicUnlinkText(ID *txtid) { return 0; /* no pynodes used this text */ } -/* -static void node_dynamic_free_all_typeinfos(ListBase *list) -{ - bNodeType *ntype, *ntnext; - - ntype = list->first; - - while (ntype) { - ntnext = ntype->next; - if (ntype->type == NODE_DYNAMIC && ntype->id) { - BLI_remlink(list, ntype); - node_dynamic_free_typeinfo_sockets(ntype); - node_dynamic_free_typeinfo(ntype); - } - ntype = ntnext; - } -} -*/ -/* Unload all pynodes: since the Game Engine restarts Python, we need - * to recreate pynodes dicts and objects. First we get rid of them here: */ -/* -void nodeDynamicUnloadAll(void) -{ - Material *ma; - bNode *nd; - PyGILState_STATE gilstate = PyGILState_Ensure(); - - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->nodetree) { - for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { - if ((nd->type == NODE_DYNAMIC) && nd->id) { - node_dynamic_free_storage_cb(nd); - nd->typeinfo = NULL; - nd->custom1 = 0; - nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_LOADED); - } - } - } - } - - node_dynamic_free_all_typeinfos(&node_all_shaders); - - PyGILState_Release(gilstate); -} - -void nodeDynamicReloadAll(void) -{ - Material *ma; - bNode *nd; - - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->nodetree) { - for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { - if ((nd->type == NODE_DYNAMIC) && nd->id) { - node_dynamic_setup(nd); - } - } - } - } -} -*/ - static void node_dynamic_pyerror_print(bNode *node) { PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -426,15 +356,17 @@ static int node_dynamic_parse(struct bNode *node) while (PyDict_Next( (PyObject *)(nsd->dict), &pos, &key, &value)) { /* look for the node object */ + if (strcmp("Socket", PyString_AsString(key)) == 0) + continue; /* XXX ugly, fix it */ if (PyObject_TypeCheck(value, &PyType_Type)==1) { - BPy_NodeSockets *sockets = Node_CreateSockets(node); + BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node); - args = Py_BuildValue("(O)", sockets); + args = Py_BuildValue("(O)", socklists); /* init it to get the input and output sockets */ pynode = PyObject_Call(value, args, NULL); - Py_DECREF(sockets); + Py_DECREF(socklists); Py_DECREF(args); if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) { @@ -466,7 +398,7 @@ static int node_dynamic_parse(struct bNode *node) node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); break; } - break; + //break; } } -- cgit v1.2.3 From 5d0a207ecb843c4c73be897cfccbf3a0d2db574b Mon Sep 17 00:00:00 2001 From: Chris Want Date: Wed, 16 Apr 2008 22:40:48 +0000 Subject: Patch from GSR that a) fixes a whole bunch of GPL/BL license blocks that were previously missed; and b) greatly increase my ohloh stats! --- source/blender/nodes/intern/SHD_nodes/Makefile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index 04e042cee76..1917e9ba15c 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -1,15 +1,12 @@ # # $Id$ # -# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# ***** 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. The Blender -# Foundation also sells licenses for use in proprietary software under -# the Blender License. See http://www.blender.org/BL/ for information -# about this. +# 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 @@ -27,7 +24,7 @@ # # Contributor(s): none yet. # -# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# ***** END GPL LICENSE BLOCK ***** # # -- cgit v1.2.3 From 3a4f23aa78b5152c1adc253f48b6a591da0cf8f9 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Fri, 25 Apr 2008 16:35:52 +0000 Subject: == PyNodes == 1) Added support for a var called "__node__" in pynode scripts, that can be used to point to the desired pynode object, to make sure it is chosen. 2) Fixed a semi-obscure crash that could happen when reparsing a pynode script that was used by multiple nodes in different scenes. Memory corruption would happen if the reparsing failed during the recreation of the pynode object, not when executing it. --- .../blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 136 ++++++++++++++------- 1 file changed, 90 insertions(+), 46 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 36a3bd5b171..37bbb68ba03 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -160,11 +160,11 @@ static void node_dynamic_free_storage_cb(bNode *node) } /* Disable pynode when its script fails */ -static void node_dynamic_disable(bNode *node) +/*static void node_dynamic_disable(bNode *node) { node->custom1 = 0; node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR); -} +}*/ /* Disable all pynodes using the given text (script) id */ static void node_dynamic_disable_all_by_id(ID *id) @@ -211,6 +211,8 @@ static void node_dynamic_rem_all_links(bNodeType *tinfo) in = tinfo->inputs ? 1 : 0; out = tinfo->outputs ? 1 : 0; + if (!in && !out) return; + for (ma= G.main->mat.first; ma; ma= ma->id.next) { if (ma->nodetree) { bNode *nd; @@ -248,6 +250,7 @@ static void node_dynamic_reset(bNode *node, int unlink_text) if (nd->typeinfo == tinfo) { node_dynamic_free_storage_cb(nd); node_dynamic_free_sockets(nd); + //node_dynamic_update_socket_links(nd, ma->nodetree); nd->typeinfo = tinfo_default; if (unlink_text) { nd->id = NULL; @@ -312,17 +315,69 @@ static void node_dynamic_pyerror_print(bNode *node) PyGILState_Release(gilstate); } +static void node_dynamic_register_type(bNode *node) +{ + nodeRegisterType(&node_all_shaders, node->typeinfo); + /* nodeRegisterType copied it to a new one, so we + * free the typeinfo itself, but not what it + * points to: */ + MEM_freeN(node->typeinfo); + node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id); + MEM_freeN(node->typeinfo->name); + node->typeinfo->name = BLI_strdup(node->name); +} + +/* node_dynamic_get_pynode: + * Find the pynode definition from the script */ +static PyObject *node_dynamic_get_pynode(PyObject *dict) +{ + PyObject *key= NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; + + /* script writer specified a node? */ + value = PyDict_GetItemString(dict, "__node__"); + + if (value) { + if (PyObject_TypeCheck(value, &PyType_Type)) { + Py_INCREF(value); + return value; + } + else { + PyErr_SetString(PyExc_TypeError, + "expected class object derived from Scripted node"); + return NULL; + } + } + + /* case not, search for it in the script's global dictionary */ + while (PyDict_Next(dict, &pos, &key, &value)) { + /* skip names we know belong to other available objects */ + if (strcmp("Socket", PyString_AsString(key)) == 0) + continue; + else if (strcmp("Scripted", PyString_AsString(key)) == 0) + continue; + /* naive: we grab the first ob of type 'type': */ + else if (PyObject_TypeCheck(value, &PyType_Type)) { + Py_INCREF(value); + return value; + } + } + + PyErr_SetString(PyExc_TypeError, + "no PyNode definition found in the script!"); + return NULL; +} + static int node_dynamic_parse(struct bNode *node) { PyObject *dict= NULL; - PyObject *key= NULL; - PyObject *value= NULL; + PyObject *pynode_data= NULL; PyObject *pynode= NULL; PyObject *args= NULL; NodeScriptDict *nsd = NULL; PyObject *pyresult = NULL; char *buf = NULL; - Py_ssize_t pos = 0; int is_valid_script = 0; PyGILState_STATE gilstate; @@ -346,7 +401,7 @@ static int node_dynamic_parse(struct bNode *node) MEM_freeN(buf); if (!pyresult) { - node_dynamic_disable(node); + node_dynamic_disable_all_by_id(node->id); node_dynamic_pyerror_print(node); PyGILState_Release(gilstate); return -1; @@ -354,58 +409,46 @@ static int node_dynamic_parse(struct bNode *node) Py_DECREF(pyresult); - while (PyDict_Next( (PyObject *)(nsd->dict), &pos, &key, &value)) { - /* look for the node object */ - if (strcmp("Socket", PyString_AsString(key)) == 0) - continue; /* XXX ugly, fix it */ - if (PyObject_TypeCheck(value, &PyType_Type)==1) { - BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node); + pynode_data = node_dynamic_get_pynode(dict); - args = Py_BuildValue("(O)", socklists); + if (pynode_data) { + BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node); - /* init it to get the input and output sockets */ - pynode = PyObject_Call(value, args, NULL); + args = Py_BuildValue("(O)", socklists); - Py_DECREF(socklists); - Py_DECREF(args); + /* init it to get the input and output sockets */ + pynode = PyObject_Call(pynode_data, args, NULL); - if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) { - InitNode((BPy_Node *)(pynode), node); - nsd->node = pynode; - node->typeinfo->execfunc = node_dynamic_exec_cb; - is_valid_script = 1; - - /* for NEW, LOADED, REPARSE */ - if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { - node->typeinfo->pydict = dict; - node->typeinfo->pynode = pynode; - node->typeinfo->id = node->id; - if (BNTST(node->custom1, NODE_DYNAMIC_LOADED)) - nodeAddSockets(node, node->typeinfo); - if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE)) { - nodeRegisterType(&node_all_shaders, node->typeinfo); - /* nodeRegisterType copied it to a new one, so we - * free the typeinfo itself, but not what it - * points to: */ - MEM_freeN(node->typeinfo); - node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id); - MEM_freeN(node->typeinfo->name); - node->typeinfo->name = BLI_strdup(node->name); - } - } + Py_DECREF(pynode_data); + Py_DECREF(socklists); + Py_DECREF(args); + + if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) { + InitNode((BPy_Node *)(pynode), node); + nsd->node = pynode; + node->typeinfo->execfunc = node_dynamic_exec_cb; + is_valid_script = 1; - node->custom1 = 0; - node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); - break; + /* for NEW, LOADED, REPARSE */ + if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { + node->typeinfo->pydict = dict; + node->typeinfo->pynode = pynode; + node->typeinfo->id = node->id; + if (BNTST(node->custom1, NODE_DYNAMIC_LOADED)) + nodeAddSockets(node, node->typeinfo); + if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE)) + node_dynamic_register_type(node); } - //break; + + node->custom1 = 0; + node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); } } PyGILState_Release(gilstate); if (!is_valid_script) { /* not a valid pynode script */ - node_dynamic_disable(node); + node_dynamic_disable_all_by_id(node->id); node_dynamic_pyerror_print(node); return -1; } @@ -470,6 +513,7 @@ static void node_dynamic_setup(bNode *node) else { nodeMakeDynamicType(node); } } else { + node_dynamic_rem_all_links(node->typeinfo); node_dynamic_free_typeinfo_sockets(node->typeinfo); node_dynamic_update_socket_links(node, NULL); node_dynamic_free_storage_cb(node); -- cgit v1.2.3 From 5ad6b3f8dda50f86a5441b48539643a00a8914b8 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Fri, 2 May 2008 20:41:33 +0000 Subject: == PyNodes == More bug fixing, reports by Juho (bebraw) Vepsalainen (thanks!) #10340: a recent fix I made broke handling of pynodes with buggy scripts when loaded from a .blend. (This may have been the reason for #10341, too, caused by saving buggy typeinfo.) http://projects.blender.org/tracker/?func=detail&atid=125&aid=10340&group_id=9 --- source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 37bbb68ba03..78f780c43b1 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -160,11 +160,11 @@ static void node_dynamic_free_storage_cb(bNode *node) } /* Disable pynode when its script fails */ -/*static void node_dynamic_disable(bNode *node) +static void node_dynamic_disable(bNode *node) { node->custom1 = 0; node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR); -}*/ +} /* Disable all pynodes using the given text (script) id */ static void node_dynamic_disable_all_by_id(ID *id) @@ -401,7 +401,11 @@ static int node_dynamic_parse(struct bNode *node) MEM_freeN(buf); if (!pyresult) { + if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) { + node_dynamic_disable(node); + } else { node_dynamic_disable_all_by_id(node->id); + } node_dynamic_pyerror_print(node); PyGILState_Release(gilstate); return -1; -- cgit v1.2.3 From ad38297a08b3f6901bfdefdca56b1f0e4f8ac58d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 May 2008 19:57:10 +0000 Subject: Fix for bug #11005: hue-sat-value node was doing unnecessary clamping, which not only is suboptimal for working with hdr images, it was also doing the clamping incorrect. --- source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c index 8c07a2d1dc8..67dfc619080 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c @@ -54,9 +54,7 @@ static void do_hue_sat_fac(bNode *node, float *out, float *hue, float *sat, floa hsv[0]+= (*hue - 0.5f); if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0; hsv[1]*= *sat; - if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0; hsv[2]*= *val; - if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); out[0]= mfac*in[0] + *fac*col[0]; -- cgit v1.2.3 From 5f70682f6a622b2832e50860cc2699c67d9b7e65 Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Fri, 23 May 2008 16:31:02 +0000 Subject: == PyNodes == Fixing bug #11737 reported by Daniel Salazar (Zanqdo, thanks!): assigning as pynode a text that failed to parse as a pynode script, then deleting that text would crash Blender. http://projects.blender.org/tracker/?func=detail&atid=125&aid=11737&group_id=9 --- source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 78f780c43b1..49473b213ce 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -239,6 +239,27 @@ static void node_dynamic_reset(bNode *node, int unlink_text) tinfo = node->typeinfo; tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL); + if ((tinfo == tinfo_default) && unlink_text) { + ID *textID = node->id; + /* already at default (empty) state, which happens if this node's + * script failed to parse at the first stage: definition. We're here + * because its text was removed from Blender. */ + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd->id == textID) { + nd->id = NULL; + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); + BLI_strncpy(nd->name, "Dynamic", 8); + return; + } + } + } + } + } + node_dynamic_rem_all_links(tinfo); node_dynamic_free_typeinfo_sockets(tinfo); -- cgit v1.2.3 From 4c391a0c30018917f6173d1200efcb93c02211f5 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Tue, 17 Jun 2008 04:18:34 +0000 Subject: * Simple addition to math node (comp and shading): Greater Than and Less Than modes. --- source/blender/nodes/intern/SHD_nodes/SHD_math.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c index 95162e508d5..2e156cf12bf 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c @@ -174,7 +174,23 @@ bNodeStack **out) else out[0]->vec[0]= (int)(in[1]->vec[0] + 0.5f); } - break; + break; + case 15: /* Less Than */ + { + if( in[0]->vec[0] < in[1]->vec[0] ) + out[0]->vec[0]= 1.0f; + else + out[0]->vec[0]= 0.0f; + } + break; + case 16: /* Greater Than */ + { + if( in[0]->vec[0] > in[1]->vec[0] ) + out[0]->vec[0]= 1.0f; + else + out[0]->vec[0]= 0.0f; + } + break; } } -- cgit v1.2.3 From 846ae7a187a630e0fc413a272917c08cd9fde8af Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Fri, 25 Jul 2008 01:17:37 +0000 Subject: * Fix for bug #9450 'Problems with Extended Material node with AmbCol socket' It turns out the material AmbCol property was never working properly, or even supported in the renderer, so I've removed it. Also included is a fix to make the 'Amb' input work properly too. --- source/blender/nodes/intern/SHD_nodes/SHD_material.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index bdceb134c0d..9396410f850 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -54,7 +54,6 @@ static bNodeSocketType sh_node_material_ext_in[]= { { SOCK_VALUE, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 1, "AmbCol", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "Emit", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "SpecTra", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, @@ -117,8 +116,6 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, if (node->type == SH_NODE_MATERIAL_EXT) { if(in[MAT_IN_MIR]->hasinput) nodestack_get_vec(&shi->mirr, SOCK_VECTOR, in[MAT_IN_MIR]); - if(in[MAT_IN_AMBCOL]->hasinput) - nodestack_get_vec(&shi->ambr, SOCK_VECTOR, in[MAT_IN_AMBCOL]); if(in[MAT_IN_AMB]->hasinput) nodestack_get_vec(&shi->amb, SOCK_VALUE, in[MAT_IN_AMB]); if(in[MAT_IN_EMIT]->hasinput) -- cgit v1.2.3 From cb89decfdcf5e6b2f26376d416633f4ccf0c532d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 4 Sep 2008 20:51:28 +0000 Subject: Merge of first part of changes from the apricot branch, especially the features that are needed to run the game. Compile tested with scons, make, but not cmake, that seems to have an issue not related to these changes. The changes include: * GLSL support in the viewport and game engine, enable in the game menu in textured draw mode. * Synced and merged part of the duplicated blender and gameengine/ gameplayer drawing code. * Further refactoring of game engine drawing code, especially mesh storage changed a lot. * Optimizations in game engine armatures to avoid recomputations. * A python function to get the framerate estimate in game. * An option take object color into account in materials. * An option to restrict shadow casters to a lamp's layers. * Increase from 10 to 18 texture slots for materials, lamps, word. An extra texture slot shows up once the last slot is used. * Memory limit for undo, not enabled by default yet because it needs the .B.blend to be changed. * Multiple undo for image painting. * An offset for dupligroups, so not all objects in a group have to be at the origin. --- source/blender/nodes/intern/SHD_nodes/Makefile | 2 + source/blender/nodes/intern/SHD_nodes/SHD_camera.c | 10 ++- source/blender/nodes/intern/SHD_nodes/SHD_curves.c | 24 ++++++- source/blender/nodes/intern/SHD_nodes/SHD_geom.c | 16 ++++- .../blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c | 9 ++- source/blender/nodes/intern/SHD_nodes/SHD_invert.c | 8 ++- .../blender/nodes/intern/SHD_nodes/SHD_mapping.c | 17 ++++- .../blender/nodes/intern/SHD_nodes/SHD_material.c | 79 ++++++++++++++++++++-- source/blender/nodes/intern/SHD_nodes/SHD_math.c | 43 +++++++++++- source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c | 14 +++- source/blender/nodes/intern/SHD_nodes/SHD_normal.c | 11 ++- source/blender/nodes/intern/SHD_nodes/SHD_output.c | 16 ++++- source/blender/nodes/intern/SHD_nodes/SHD_rgb.c | 11 ++- .../nodes/intern/SHD_nodes/SHD_sepcombRGB.c | 16 ++++- .../blender/nodes/intern/SHD_nodes/SHD_squeeze.c | 8 ++- .../blender/nodes/intern/SHD_nodes/SHD_texture.c | 17 ++++- .../blender/nodes/intern/SHD_nodes/SHD_valToRgb.c | 20 +++++- source/blender/nodes/intern/SHD_nodes/SHD_value.c | 9 ++- .../blender/nodes/intern/SHD_nodes/SHD_vectMath.c | 31 ++++++++- 19 files changed, 336 insertions(+), 25 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index 1917e9ba15c..ae3cae029d2 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -44,4 +44,6 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I../../../gpu +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c index 63260ff91ed..20136d75540 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c @@ -46,8 +46,13 @@ static void node_shader_exec_camera(void *data, bNode *node, bNodeStack **in, bN VECCOPY(out[0]->vec, shi->co); /* get view vector */ out[1]->vec[0]= fabs(shi->co[2]); /* get view z-depth */ out[2]->vec[0]= Normalize(out[0]->vec); /* get view distance */ - } } +} + +static int gpu_shader_camera(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION)); +} bNodeType sh_node_camera= { /* *next,*prev */ NULL, NULL, @@ -63,6 +68,7 @@ bNodeType sh_node_camera= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_camera }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c index b6f1f8d52cd..d277547b636 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c @@ -56,6 +56,15 @@ static void node_shader_init_curve_vec(bNode* node) node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); } +static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_curve_vec= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_VEC, @@ -70,7 +79,8 @@ bNodeType sh_node_curve_vec= { /* initfunc */ node_shader_init_curve_vec, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_curve_vec }; @@ -100,6 +110,15 @@ static void node_shader_init_curve_rgb(bNode *node) node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } +static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_curve_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_RGB, @@ -114,6 +133,7 @@ bNodeType sh_node_curve_rgb= { /* initfunc */ node_shader_init_curve_rgb, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_curve_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c index 24395059c60..bc345759b98 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c @@ -29,6 +29,7 @@ #include "../SHD_util.h" +#include "DNA_customdata_types.h" /* **************** GEOMETRY ******************** */ @@ -124,6 +125,18 @@ static void node_shader_init_geometry(bNode *node) node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); } +static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname); + GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname); + + return GPU_stack_link(mat, "geom", in, out, + GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol); +} + /* node type definition */ bNodeType sh_node_geom= { /* *next,*prev */ NULL, NULL, @@ -139,6 +152,7 @@ bNodeType sh_node_geom= { /* initfunc */ node_shader_init_geometry, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_geom }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c index 67dfc619080..1b7b2dfb8e7 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c @@ -71,6 +71,12 @@ static void node_shader_exec_hue_sat(void *data, bNode *node, bNodeStack **in, b do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec); } + +static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "hue_sat", in, out); +} + bNodeType sh_node_hue_sat= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_HUE_SAT, @@ -85,7 +91,8 @@ bNodeType sh_node_hue_sat= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_hue_sat }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c index 4d1ce282fce..72ee1483ecf 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c @@ -64,6 +64,11 @@ bNodeStack **out) VECCOPY(out[0]->vec, col); } +static int gpu_shader_invert(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "invert", in, out); +} + bNodeType sh_node_invert= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_INVERT, @@ -78,6 +83,7 @@ bNodeType sh_node_invert= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_invert }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c index 589954c8f7b..c081929a2fc 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c @@ -69,6 +69,20 @@ static void node_shader_init_mapping(bNode *node) node->storage= add_mapping(); } +static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + TexMapping *texmap= node->storage; + float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; + float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0; + GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat); + GPUNodeLink *tmin = GPU_uniform(texmap->min); + GPUNodeLink *tmax = GPU_uniform(texmap->max); + GPUNodeLink *tdomin = GPU_uniform(&domin); + GPUNodeLink *tdomax = GPU_uniform(&domax); + + return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax); +} + bNodeType sh_node_mapping= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MAPPING, @@ -83,7 +97,8 @@ bNodeType sh_node_mapping= { /* initfunc */ node_shader_init_mapping, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_mapping }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index 9396410f850..c0a2534ac4a 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -182,6 +182,77 @@ static void node_shader_init_material(bNode* node) node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; } +static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + if(node->id) { + GPUShadeInput shi; + GPUShadeResult shr; + + GPU_shadeinput_set(mat, (Material*)node->id, &shi); + + /* write values */ + if(in[MAT_IN_COLOR].hasinput) + shi.rgb = in[MAT_IN_COLOR].link; + + if(in[MAT_IN_SPEC].hasinput) + shi.specrgb = in[MAT_IN_SPEC].link; + + if(in[MAT_IN_REFL].hasinput) + shi.refl = in[MAT_IN_REFL].link; + + /* retrieve normal */ + if(in[MAT_IN_NORMAL].hasinput) { + GPUNodeLink *tmp; + shi.vn = in[MAT_IN_NORMAL].link; + GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); + } + + /* custom option to flip normal */ + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + + if (node->type == SH_NODE_MATERIAL_EXT) { + if(in[MAT_IN_AMB].hasinput) + shi.amb= in[MAT_IN_AMB].link; + if(in[MAT_IN_EMIT].hasinput) + shi.emit= in[MAT_IN_EMIT].link; + if(in[MAT_IN_ALPHA].hasinput) + shi.alpha= in[MAT_IN_ALPHA].link; + } + + GPU_shaderesult_set(&shi, &shr); /* clears shr */ + + /* write to outputs */ + if(node->custom1 & SH_NODE_MAT_DIFF) { + if(node->custom1 & SH_NODE_MAT_SPEC) + out[MAT_OUT_COLOR].link= shr.combined; + else + out[MAT_OUT_COLOR].link= shr.diff; + } + else if(node->custom1 & SH_NODE_MAT_SPEC) { + out[MAT_OUT_COLOR].link= shr.spec; + } + else + GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); + + GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); + + out[MAT_OUT_ALPHA].link = shr.alpha; // + + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + out[MAT_OUT_NORMAL].link = shi.vn; + + if (node->type == SH_NODE_MATERIAL_EXT) { + out[MAT_OUT_DIFFUSE].link = shr.diff; + out[MAT_OUT_SPEC].link = shr.spec; + } + + return 1; + } + + return 0; +} bNodeType sh_node_material= { /* *next,*prev */ NULL, NULL, @@ -197,8 +268,8 @@ bNodeType sh_node_material= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL - + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_material }; bNodeType sh_node_material_ext= { @@ -215,7 +286,7 @@ bNodeType sh_node_material_ext= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL - + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_material }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c index 2e156cf12bf..050c2cdcc95 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c @@ -194,6 +194,46 @@ bNodeStack **out) } } +static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"math_add", "math_subtract", "math_multiply", + "math_divide", "math_sine", "math_cosine", "math_tangnet", "math_asin", + "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", + "math_round", "math_less_than", "math_greater_than"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 10: + case 11: + case 12: + case 13: + case 15: + case 16: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 14: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + bNodeType sh_node_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MATH, @@ -208,6 +248,7 @@ bNodeType sh_node_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_math }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c index dba70253fda..2da1dee5623 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c @@ -60,6 +60,17 @@ static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, b VECCOPY(out[0]->vec, col); } +static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", + "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", + "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", + "mix_val", "mix_color"}; + + return GPU_stack_link(mat, names[node->custom1], in, out); +} + + bNodeType sh_node_mix_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MIX_RGB, @@ -74,6 +85,7 @@ bNodeType sh_node_mix_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_mix_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c index f1ffd3446af..9d4ea1ccf67 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c @@ -57,6 +57,14 @@ static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bN out[1]->vec[0]= -INPR(out[0]->vec, vec); } +static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + + return GPU_stack_link(mat, "normal", in, out, vec); +} + bNodeType sh_node_normal= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_NORMAL, @@ -71,6 +79,7 @@ bNodeType sh_node_normal= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_normal }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_output.c b/source/blender/nodes/intern/SHD_nodes/SHD_output.c index 0a9a30c452b..76856cfd2e8 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_output.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_output.c @@ -62,6 +62,19 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN } } +static int gpu_shader_output(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + GPUNodeLink *outlink; + + /*if(in[1].hasinput) + GPU_material_enable_alpha(mat);*/ + + GPU_stack_link(mat, "output_node", in, out, &outlink); + GPU_material_output_link(mat, outlink); + + return 1; +} + bNodeType sh_node_output= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_OUTPUT, @@ -76,7 +89,8 @@ bNodeType sh_node_output= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_output }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c index 4e56e26d3ad..1aa1a2ffc33 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c @@ -42,6 +42,14 @@ static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNode VECCOPY(out[0]->vec, sock->ns.vec); } +static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + + return GPU_stack_link(mat, "set_rgba", in, out, vec); +} + bNodeType sh_node_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGB, @@ -56,6 +64,7 @@ bNodeType sh_node_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c index 2b52a8e2229..6d5df2a1321 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c @@ -48,6 +48,11 @@ static void node_shader_exec_seprgb(void *data, bNode *node, bNodeStack **in, bN out[2]->vec[0] = in[0]->vec[2]; } +static int gpu_shader_seprgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "separate_rgb", in, out); +} + bNodeType sh_node_seprgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SEPRGB, @@ -62,7 +67,8 @@ bNodeType sh_node_seprgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_seprgb }; @@ -86,6 +92,11 @@ static void node_shader_exec_combrgb(void *data, bNode *node, bNodeStack **in, b out[0]->vec[2] = in[2]->vec[0]; } +static int gpu_shader_combrgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "combine_rgb", in, out); +} + bNodeType sh_node_combrgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_COMBRGB, @@ -100,6 +111,7 @@ bNodeType sh_node_combrgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_combrgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c index 30abad666c4..d3480a6ae9d 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c @@ -54,6 +54,11 @@ bNodeStack **out) out[0]->vec[0] = 1.0f / (1.0f + pow(2.71828183,-((vec[0]-vec[2])*vec[1]))) ; } +static int gpu_shader_squeeze(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "squeeze", in, out); +} + bNodeType sh_node_squeeze= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SQUEEZE, @@ -68,6 +73,7 @@ bNodeType sh_node_squeeze= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_squeeze }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c index ace11a20d42..31dbde940fd 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c @@ -27,6 +27,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "DNA_texture_types.h" + #include "../SHD_util.h" /* **************** TEXTURE ******************** */ @@ -110,6 +112,18 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b } } +static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + Tex *tex = (Tex*)node->id; + + if(tex && tex->type == TEX_IMAGE && tex->ima) { + GPUNodeLink *texlink = GPU_image(tex->ima, NULL); + return GPU_stack_link(mat, "texture_image", in, out, texlink); + } + else + return 0; +} + bNodeType sh_node_texture= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_TEXTURE, @@ -124,7 +138,8 @@ bNodeType sh_node_texture= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_texture }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c index cf7e33d9dca..301c0cb7031 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c @@ -59,6 +59,15 @@ static void node_shader_init_valtorgb(bNode *node) node->storage= add_colorband(1); } +static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + colorband_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_valtorgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VALTORGB, @@ -73,7 +82,8 @@ bNodeType sh_node_valtorgb= { /* initfunc */ node_shader_init_valtorgb, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_valtorgb }; @@ -96,6 +106,11 @@ static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, b out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f; } +static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "rgbtobw", in, out); +} + bNodeType sh_node_rgbtobw= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGBTOBW, @@ -110,7 +125,8 @@ bNodeType sh_node_rgbtobw= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_rgbtobw }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_value.c b/source/blender/nodes/intern/SHD_nodes/SHD_value.c index 57ef7226066..768ef3cda3d 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_value.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_value.c @@ -42,7 +42,13 @@ static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNo out[0]->vec[0]= sock->ns.vec[0]; } +static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + return GPU_stack_link(mat, "set_value", in, out, vec); +} bNodeType sh_node_value= { /* *next,*prev */ NULL, NULL, @@ -58,7 +64,8 @@ bNodeType sh_node_value= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_value }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c index 8d0a4b3abe3..96db8db18a6 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c @@ -99,6 +99,34 @@ static void node_shader_exec_vect_math(void *data, bNode *node, bNodeStack **in, } +static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"vec_math_add", "vec_math_subtract", + "vec_math_average", "vec_math_dot", "vec_math_cross", + "vec_math_normalize"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 4: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 5: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + bNodeType sh_node_vect_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VECT_MATH, @@ -113,6 +141,7 @@ bNodeType sh_node_vect_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_vect_math }; -- cgit v1.2.3 From ac4ff83ca6b5795f4451a7e743d3975aeb17ae3b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 28 Oct 2008 18:47:13 +0000 Subject: added scons option BF_WITH_PYTHON (defined as DISABLE_PYTHON) --- .../blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'source/blender/nodes/intern/SHD_nodes') diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 49473b213ce..2065ac2ed33 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -27,17 +27,21 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifndef DISABLE_PYTHON #include #include #include +#endif #include "DNA_text_types.h" #include "BKE_text.h" #include "BKE_utildefines.h" +#ifndef DISABLE_PYTHON #include "api2_2x/Node.h" #include "api2_2x/gen_utils.h" #include "BPY_extern.h" +#endif #include "../SHD_util.h" @@ -45,6 +49,7 @@ static void node_dynamic_setup(bNode *node); static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out); static void node_dynamic_free_storage_cb(bNode *node); +#ifndef DISABLE_PYTHON static PyObject *init_dynamicdict(void) { PyObject *newscriptdict; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -58,6 +63,7 @@ static PyObject *init_dynamicdict(void) { return newscriptdict; } +#endif static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id) { @@ -140,12 +146,12 @@ static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree) static void node_dynamic_free_storage_cb(bNode *node) { +#ifndef DISABLE_PYTHON NodeScriptDict *nsd; PyObject *pydict; BPy_Node *pynode; if (!node->storage) return; - nsd = (NodeScriptDict *)(node->storage); pydict = nsd->dict; if (pydict) { @@ -155,6 +161,7 @@ static void node_dynamic_free_storage_cb(bNode *node) if (pynode) { Py_DECREF(pynode); } +#endif MEM_freeN(node->storage); node->storage = NULL; } @@ -169,6 +176,7 @@ static void node_dynamic_disable(bNode *node) /* Disable all pynodes using the given text (script) id */ static void node_dynamic_disable_all_by_id(ID *id) { +#ifndef DISABLE_PYTHON Material *ma; /* XXX hardcoded for shaders */ for (ma= G.main->mat.first; ma; ma= ma->id.next) { @@ -183,6 +191,7 @@ static void node_dynamic_disable_all_by_id(ID *id) } } } +#endif } static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb) @@ -327,6 +336,7 @@ int nodeDynamicUnlinkText(ID *txtid) { static void node_dynamic_pyerror_print(bNode *node) { +#ifndef DISABLE_PYTHON PyGILState_STATE gilstate = PyGILState_Ensure(); fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name); @@ -334,6 +344,7 @@ static void node_dynamic_pyerror_print(bNode *node) else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); } PyGILState_Release(gilstate); +#endif } static void node_dynamic_register_type(bNode *node) @@ -348,6 +359,7 @@ static void node_dynamic_register_type(bNode *node) node->typeinfo->name = BLI_strdup(node->name); } +#ifndef DISABLE_PYTHON /* node_dynamic_get_pynode: * Find the pynode definition from the script */ static PyObject *node_dynamic_get_pynode(PyObject *dict) @@ -389,9 +401,13 @@ static PyObject *node_dynamic_get_pynode(PyObject *dict) "no PyNode definition found in the script!"); return NULL; } +#endif /* DISABLE_PYTHON */ static int node_dynamic_parse(struct bNode *node) { +#ifdef DISABLE_PYTHON + return -1; +#else PyObject *dict= NULL; PyObject *pynode_data= NULL; PyObject *pynode= NULL; @@ -479,12 +495,14 @@ static int node_dynamic_parse(struct bNode *node) } return 0; +#endif } /* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY) * pynodes already linked to a script (node->id != NULL). */ static void node_dynamic_setup(bNode *node) { +#ifndef DISABLE_PYTHON NodeScriptDict *nsd = NULL; bNodeTree *nodetree = NULL; bNodeType *ntype = NULL; @@ -608,7 +626,7 @@ static void node_dynamic_setup(bNode *node) node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); PyGILState_Release(gilstate); - +#endif /* DISABLE_PYTHON */ return; } @@ -641,6 +659,9 @@ static void node_dynamic_init_cb(bNode *node) { /* node_dynamic_copy_cb: pynode copy callback */ static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) { +#ifdef DISABLE_PYTHON + return; +#else NodeScriptDict *nsd; PyGILState_STATE gilstate; @@ -657,11 +678,15 @@ static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) Py_INCREF((PyObject *)(nsd->dict)); PyGILState_Release(gilstate); +#endif } /* node_dynamic_exec_cb: the execution callback called per pixel * during rendering. */ static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { +#ifdef DISABLE_PYTHON + return; +#else BPy_Node *mynode = NULL; NodeScriptDict *nsd = NULL; PyObject *pyresult = NULL; @@ -716,6 +741,7 @@ static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNode PyGILState_Release(gilstate); } } +#endif } bNodeType node_dynamic_typeinfo = { -- cgit v1.2.3