[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