[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