[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12970] branches/pynodes/source/blender: Ongoing work mostly to fix pynode setup and memory (de)allocation issues.
Willian Padovani Germano
wpgermano at gmail.com
Fri Dec 21 18:42:39 CET 2007
Revision: 12970
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12970
Author: ianwill
Date: 2007-12-21 18:42:39 +0100 (Fri, 21 Dec 2007)
Log Message:
-----------
Ongoing work mostly to fix pynode setup and memory (de)allocation issues. Brought back the "Update" button in pynodes, but it's not working properly yet (gotta update socket links).
Modified Paths:
--------------
branches/pynodes/source/blender/blenkernel/intern/node.c
branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
branches/pynodes/source/blender/src/drawnode.c
Modified: branches/pynodes/source/blender/blenkernel/intern/node.c
===================================================================
--- branches/pynodes/source/blender/blenkernel/intern/node.c 2007-12-21 10:57:02 UTC (rev 12969)
+++ branches/pynodes/source/blender/blenkernel/intern/node.c 2007-12-21 17:42:39 UTC (rev 12970)
@@ -1088,18 +1088,6 @@
node->typeinfo->freestoragefunc(node);
}
- /* 4PYNODES: even if not node->typeinfo->id, we have
- * to MEM_freeN node->typeinfo), otherwise there's a mem leak
- * Note: fix the if's in this function, no need to check for
- * node->typeinfo more than once. */
- /*if(node->type==NODE_DYNAMIC && node->typeinfo && node->typeinfo->id) {*/
- if(node->type==NODE_DYNAMIC) {
- if(node->typeinfo) {
- /* todo: add ->us support to typeinfo */
- MEM_freeN(node->typeinfo);
- node->typeinfo=NULL;
- }
- }
MEM_freeN(node);
}
@@ -2503,7 +2491,7 @@
while(ntype) {
next= ntype->next;
if(ntype->type==NODE_DYNAMIC && ntype->id!=NULL) {
- BLI_remlink(&node_all_composit, ntype);
+ BLI_remlink(list, ntype);
if(ntype->inputs) {
bNodeSocketType *sock= ntype->inputs;
while(sock->type!=-1) {
@@ -2537,7 +2525,7 @@
void free_nodesystem(void)
{
- remove_dynamic_typeinfos(&node_all_composit);
+ /*remove_dynamic_typeinfos(&node_all_composit);*/ /* unused for now */
BLI_freelistN(&node_all_composit);
remove_dynamic_typeinfos(&node_all_shaders);
BLI_freelistN(&node_all_shaders);
Modified: branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
===================================================================
--- branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c 2007-12-21 10:57:02 UTC (rev 12969)
+++ branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c 2007-12-21 17:42:39 UTC (rev 12970)
@@ -49,77 +49,276 @@
return newscriptdict;
}
+/* unused for now
static void free_dynamicdict(PyObject *dict) {
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;
+static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
+{
+ bNodeType *ntype = list->first;
- node->custom2= 0;
- node->storage= nsd;
- if(type>=NODE_DYNAMIC_MENU) {
- node->custom1= 0;
- if(type==NODE_DYNAMIC_MENU) {
- nodeMakeDynamicType(node);
- node->custom1= BSET(node->custom1, NODE_DYNAMIC_NEW);
- } else {
- node->custom1= BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
+ 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(bNode *node)
+{
+ bNodeSocketType *sock;
+ bNodeType *tinfo = node->typeinfo;
+
+ if (!tinfo) return;
+
+ if (tinfo->inputs) {
+ sock = tinfo->inputs;
+ while (sock->type != -1) {
+ MEM_freeN(sock->name);
+ sock++;
}
- node->id= node->typeinfo->id;
+ MEM_freeN(tinfo->inputs);
+ }
+ if (tinfo->outputs) {
+ sock = tinfo->outputs;
+ while (sock->type != -1) {
+ MEM_freeN(sock->name);
+ sock++;
+ }
+ MEM_freeN(tinfo->outputs);
+ }
+}
+
+static void node_dynamic_free_typeinfo(bNode *node)
+{
+ bNodeType *tinfo = node->typeinfo;
+
+ if (!tinfo) return;
+
+ node_dynamic_free_typeinfo_sockets(node);
+
+ 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);
+}
+
+static void node_dynamic_update_socket_links(bNode *node)
+{
+ Material *ma;
+/*
+ for (ma = G.main->mat.first; ma; ma = ma->id.next) {
+ if (ma->nodetree) {
+ bNode *node;
+ }
+ }
+ */
+ ma = give_current_material(OBACT, OBACT->actcol);
+ if (ma && ma->nodetree)
+ nodeUpdateType(ma->nodetree, node, node->typeinfo);
+ // XXX unfinished
+
+}
+
+static void node_dynamic_free_storage(bNode *node)
+{
+ 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;
+}
+
+/* Disable pynode when its script fails */
+static void node_dynamic_disable(bNode *node)
+{
+ node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_LOADED);
+ node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST);
+ node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
+ node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
+
+ node_dynamic_free_typeinfo_sockets(node);
+ node_dynamic_free_sockets(node);
+ node_dynamic_free_storage(node);
+}
+
+static void node_dynamic_pyerror_print(bNode *node)
+{
+ printf("\nError in dynamic node script \"%s\":\n", node->name);
+
+ if (PyErr_Occurred()) PyErr_Print();
+ else
+ printf("PyObject_Call __call__ failed\n");
+}
+
+static void node_dynamic_setup(bNode *node)
+{
+ NodeScriptDict *nsd = NULL;
+ bNodeType *ntype = NULL;
+
+ /* Possible cases:
+ * READY
+ * NEW
+ * ADDEXIST
+ * LOADED
+ * ERROR
+ */
+
+ /* NEW, but not linked to a script, nothing to do here */
+ if (!node->id)
+ return;
+
+ /* READY or ERROR, no need to be here */
+ if (BTST2(node->custom1, NODE_DYNAMIC_READY, NODE_DYNAMIC_ERROR))
+ return;
+
+ if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) {
+ node_dynamic_free_typeinfo_sockets(node);
+ node_dynamic_free_sockets(node);
+ node_dynamic_update_socket_links(node);
+ node_dynamic_free_storage(node);
+ nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
+ nsd->dict = init_dynamicdict();
+ node->storage = nsd;
+ node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
nodeDynamicParse(node);
- } else {
- if(BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
+ return;
+ }
+
+ if (node->storage)
+ printf("\nPYNODES ERROR: has node storage in node_dynamic_setup\n");
+
+ nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
+ node->storage = nsd;
+
+ /* NEW, but the user already linked it to a script */
+ if (BTST(node->custom1, NODE_DYNAMIC_NEW)) {
+ /* 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 (ntype) { /* if so, reuse it */
+ node->typeinfo = ntype;
+ /* so this is actually an ADDEXIST type */
+ //node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW);
+ node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
+ }
+ else { /* create bNodeType for this pynode */
nodeMakeDynamicType(node);
+ nsd->dict = init_dynamicdict();
nodeDynamicParse(node);
- } else if(BTST(node->custom1, NODE_DYNAMIC_ADDEXIST))
- nodeDynamicParse(node);
+ return;
+ }
}
+
+ if (nsd->dict)
+ printf("\nDEBUG: PYNODES ERROR: has pydict in SHD_dynamic.c 2\n");
+
+ /* ADDEXIST: new pynode linked to an already registered dynamic type */
+ if (BTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
+ nsd->dict = node->typeinfo->pydict;
+ nsd->node = node->typeinfo->pynode;
+ Py_INCREF((PyObject *)(nsd->dict));
+ Py_INCREF((PyObject *)(nsd->node));
+ 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;
+ }
}
-static void node_dynamic_free(bNode *node)
-{
- NodeScriptDict *nsd= (NodeScriptDict *)(node->storage);
- BPy_Node *pynode= nsd->node;
- Py_XDECREF(pynode);
- free_dynamicdict((PyObject *)(nsd->dict));
- MEM_freeN(node->storage);
+static void node_dynamic_init(bNode *node) {
+ int type = node->custom2;
+
+ node->custom2 = 0;
+
+ /* XXX testing if type can be < NODE_DYNAMIC_MENU ? */
+ if (type < NODE_DYNAMIC_MENU)
+ printf("\nTYPE < NODE_DYNAMIC_MENU: %d\n", type);
+
+ 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;
+ }
+
+ if (node->id)
+ node_dynamic_setup(node);
}
static void node_dynamic_copy(bNode *orig_node, bNode *new_node)
{
- NodeScriptDict *nsd= (NodeScriptDict *)(orig_node->storage);
- new_node->storage= MEM_dupallocN(orig_node->storage);
+ 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));
}
+/* When a pynode is updated (REPARSE) we also update all other
+ * pynodes that use the same script (same typeinfo) */
+static void node_dynamic_update_script_links(ID *id)
+{
+ return;
+}
+
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;
+ ShadeInput *shi;
- if(BTST(node->custom1,NODE_DYNAMIC_NEW)) {
- nodeDynamicParse(node);
+ if (!node->id)
return;
- }
- if(BTST(node->custom1,NODE_DYNAMIC_ERROR))
+
+ if(BTST(node->custom1, NODE_DYNAMIC_ERROR))
return;
- if(BTST(node->custom1,NODE_DYNAMIC_REPARSE)) {
- node->custom1= BSET(node->custom1,NODE_DYNAMIC_ERROR);
+ if(BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) {
+ node_dynamic_setup(node);
return;
}
-
- if(BTST2(node->custom1,NODE_DYNAMIC_READY,NODE_DYNAMIC_UPDATED)) {
+ if(BTST2(node->custom1, NODE_DYNAMIC_READY, NODE_DYNAMIC_UPDATED)) {
if(BTST(node->custom1,NODE_DYNAMIC_UPDATED)) {
node->custom1= BCLR(node->custom1,NODE_DYNAMIC_UPDATED);
node->custom1= BSET(node->custom1,NODE_DYNAMIC_READY);
@@ -129,19 +328,16 @@
mynode = (BPy_Node *)(nsd->node);
if(mynode && PyCallable_Check((PyObject *)mynode)) {
- mynode->node= node;
+ 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);
if(!pyresult) {
- if(PyErr_Occurred()) {
- PyErr_Print();
- node->custom1= BSET(node->custom1,NODE_DYNAMIC_ERROR);
- } else {
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list