diff options
author | Willian Padovani Germano <wpgermano@gmail.com> | 2008-04-25 20:35:52 +0400 |
---|---|---|
committer | Willian Padovani Germano <wpgermano@gmail.com> | 2008-04-25 20:35:52 +0400 |
commit | 3a4f23aa78b5152c1adc253f48b6a591da0cf8f9 (patch) | |
tree | 014eeaa5adb27619e31d73a5d9750309d8344796 /source/blender/nodes/intern/SHD_nodes | |
parent | feb440c2cd72ef87c79d1bbf1524802d4e82fa88 (diff) |
== 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.
Diffstat (limited to 'source/blender/nodes/intern/SHD_nodes')
-rw-r--r-- | source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c | 136 |
1 files changed, 90 insertions, 46 deletions
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); |