[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [13491] branches/pynodes/source/blender: = = PyNodes ==

Willian Padovani Germano wpgermano at gmail.com
Thu Jan 31 03:36:20 CET 2008


Revision: 13491
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=13491
Author:   ianwill
Date:     2008-01-31 03:36:16 +0100 (Thu, 31 Jan 2008)

Log Message:
-----------
== PyNodes ==

Another small update to fix possible crashes and memory leaks, in particular here for the case when working pynodes are saved but get corrupted for some reason (*) and fail when loaded from the .blend.

(*) Exs: users changing the script text and saving again or a bug that makes a script fail in some circunstances or the possibility of a future API update breaking things, for example.

Modified Paths:
--------------
    branches/pynodes/source/blender/blenkernel/intern/node.c
    branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c

Modified: branches/pynodes/source/blender/blenkernel/intern/node.c
===================================================================
--- branches/pynodes/source/blender/blenkernel/intern/node.c	2008-01-31 01:49:15 UTC (rev 13490)
+++ branches/pynodes/source/blender/blenkernel/intern/node.c	2008-01-31 02:36:16 UTC (rev 13491)
@@ -116,6 +116,8 @@
 				stype= node_get_type(ntree, node->type, NULL, node->id);
 				if(!stype) {
 					stype= node_get_type(ntree, node->type, NULL, NULL);
+					/* needed info if the pynode script fails now: */
+					if (node->id) node->storage= ntree;
 				} else {
 					node->custom1= 0;
 					node->custom1= BSET(node->custom1,NODE_DYNAMIC_ADDEXIST);

Modified: branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
===================================================================
--- branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c	2008-01-31 01:49:15 UTC (rev 13490)
+++ branches/pynodes/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c	2008-01-31 02:36:16 UTC (rev 13491)
@@ -130,18 +130,23 @@
  * 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)
+static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree)
 {
-	Material *ma;
+	if (ntree) {
+		bNode *nd;
+		for (nd= ntree->nodes.first; nd; nd = nd->next) {
+			if (nd == node) nodeVerifyType(ntree, node);
+		}
+	}
+	else {
+		Material *ma;
 
-	/* can't get from OBACT because OBACT can still be of context on
-	 * program startup */
-	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);
+		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);
+				}
 			}
 		}
 	}
@@ -175,13 +180,29 @@
 	node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
 }
 
+/* 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. */
+static void node_dynamic_reset(bNode *node, bNodeTree *ntree)
+{
+	node_dynamic_free_typeinfo_sockets(node);
+	if (!ntree) { node_dynamic_free_sockets(node); }
+	node_dynamic_update_socket_links(node, ntree);
+	node_dynamic_free_storage_cb(node);
+	node_dynamic_free_typeinfo(node);
+	node->typeinfo =
+			node_dynamic_find_typeinfo(&node_all_shaders, NULL);
+}
+
 static void node_dynamic_pyerror_print(bNode *node)
 {
 	fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
 	if (PyErr_Occurred()) PyErr_Print();
 }
 
-static void node_dynamic_parse(struct bNode *node)
+static int node_dynamic_parse(struct bNode *node)
 {
 	PyObject *dict= NULL;
 	PyObject *key= NULL;
@@ -194,11 +215,11 @@
 	int pos = 0, is_valid_script = 0;
 
 	if (!node->id || !node->storage)
-		return;
+		return 0;
 
 	/* READY, no need to be here */
 	if (BTST(node->custom1, NODE_DYNAMIC_READY))
-		return;
+		return 0;
 
 	nsd = (NodeScriptDict *)node->storage;
 
@@ -212,8 +233,7 @@
 	if (!pyresult) {
 		node_dynamic_disable(node);
 		node_dynamic_pyerror_print(node);
-		node_dynamic_setup(node);
-		return;
+		return -1;
 	}
 
 	Py_DECREF(pyresult);
@@ -267,8 +287,10 @@
 	if (!is_valid_script) { /* not a valid pynode script */
 		node_dynamic_disable(node);
 		node_dynamic_pyerror_print(node);
-		node_dynamic_setup(node);
+		return -1;
 	}
+
+	return 0;
 }
 
 /* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY)
@@ -276,6 +298,7 @@
 static void node_dynamic_setup(bNode *node)
 {
 	NodeScriptDict *nsd = NULL;
+	bNodeTree *nodetree = NULL;
 
 	/* Possible cases:
 	 * NEW
@@ -299,13 +322,7 @@
 
 	/* ERROR, reset to (empty) defaults */
 	if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) {
-		node_dynamic_free_typeinfo_sockets(node);
-		node_dynamic_free_sockets(node);
-		node_dynamic_update_socket_links(node);
-		node_dynamic_free_storage_cb(node);
-		node_dynamic_free_typeinfo(node);
-		node->typeinfo =
-				node_dynamic_find_typeinfo(&node_all_shaders, NULL);
+		node_dynamic_reset(node, NULL);
 		return;
 	}
 
@@ -313,11 +330,10 @@
 	if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) {
 		if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
 			nodeMakeDynamicType(node);
-			//wnode->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR);
 			node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE);
 		} else {
 			node_dynamic_free_typeinfo_sockets(node);
-			node_dynamic_update_socket_links(node);
+			node_dynamic_update_socket_links(node, NULL);
 			node_dynamic_free_storage_cb(node);
 		}
 		nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
@@ -328,9 +344,17 @@
 		node_dynamic_parse(node);
 		return;
 	}
+	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->storage) /* XXX */
-		fprintf(stderr, "\nDEBUG: PYNODES ERROR: has node storage in node_dynamic_setup\n");
+	if (node->storage)
+		fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n");
 
 	nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
 	node->storage = nsd;
@@ -351,7 +375,9 @@
 		else { /* create bNodeType for this pynode */
 			nodeMakeDynamicType(node);
 			nsd->dict = init_dynamicdict();
-			node_dynamic_parse(node);
+			if ((node_dynamic_parse(node) == -1) && nodetree) {
+				node_dynamic_reset(node, nodetree);
+			}
 			return;
 		}
 	}
@@ -362,10 +388,12 @@
 	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);
 
@@ -376,7 +404,8 @@
  * 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 */
+ *  > NODE_DYNAMIC_MENU: for the new types defined by scripts
+*/
 static void node_dynamic_init_cb(bNode *node) {
 	int type = node->custom2;
 
@@ -430,8 +459,10 @@
 		return;
 	}
 
-	if (BTST(node->custom1, NODE_DYNAMIC_ERROR))
+	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;





More information about the Bf-blender-cvs mailing list