[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [14546] trunk/blender/source/blender: == PyNodes ==

Willian Padovani Germano wpgermano at gmail.com
Fri Apr 25 18:35:53 CEST 2008


Revision: 14546
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14546
Author:   ianwill
Date:     2008-04-25 18:35:52 +0200 (Fri, 25 Apr 2008)

Log Message:
-----------
== 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.

Modified Paths:
--------------
    trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
    trunk/blender/source/blender/python/api2_2x/Node.c

Modified: trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c
===================================================================
--- trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c	2008-04-25 16:09:16 UTC (rev 14545)
+++ trunk/blender/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c	2008-04-25 16:35:52 UTC (rev 14546)
@@ -160,11 +160,11 @@
 }
 
 /* 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 @@
 	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 @@
 				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 @@
 	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 @@
 	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 @@
 
 	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;
+		Py_DECREF(pynode_data);
+		Py_DECREF(socklists);
+		Py_DECREF(args);
 
-				/* 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);
-					}
-				}
+		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 @@
 			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);

Modified: trunk/blender/source/blender/python/api2_2x/Node.c
===================================================================
--- trunk/blender/source/blender/python/api2_2x/Node.c	2008-04-25 16:09:16 UTC (rev 14545)
+++ trunk/blender/source/blender/python/api2_2x/Node.c	2008-04-25 16:35:52 UTC (rev 14546)
@@ -1379,7 +1379,7 @@
 	PyObject_HEAD_INIT( NULL )  /* required py macro */
 	0,                          /* ob_size */
 	/*  For printing, in format "<module>.<name>" */
-	"Blender.Node.node",             /* char *tp_name; */
+	"Blender.Node.Scripted",    /* char *tp_name; */
 	sizeof( BPy_Node ),         /* int tp_basicsize; */
 	0,                          /* tp_itemsize;  For allocation */
 





More information about the Bf-blender-cvs mailing list