4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2007 Blender Foundation.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): Nathan Letwory
27 * ***** END GPL LICENSE BLOCK *****
30 /* TODO, support python3.x */
39 #include "DNA_text_types.h"
46 #include "api2_2x/Node.h"
47 #include "api2_2x/gen_utils.h"
48 #include "BPY_extern.h"
52 #include "../SHD_util.h"
56 static void node_dynamic_setup(bNode *node);
57 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out);
58 static void node_dynamic_free_storage_cb(bNode *node);
61 static PyObject *init_dynamicdict(void) {
62 PyObject *newscriptdict, *item;
63 PyGILState_STATE gilstate = PyGILState_Ensure();
65 newscriptdict= PyDict_New();
67 PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins());
68 item= PyString_FromString("__main__");
69 PyDict_SetItemString(newscriptdict, "__name__", item);
72 PyGILState_Release(gilstate);
78 static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
80 bNodeType *ntype = list->first;
83 if (ntype->type == NODE_DYNAMIC && ntype->id == id)
88 return ntype; /* NULL if doesn't exist */
91 static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo)
93 bNodeSocketType *sock;
99 while (sock->type != -1) {
100 MEM_freeN(sock->name);
103 MEM_freeN(tinfo->inputs);
104 tinfo->inputs = NULL;
106 if (tinfo->outputs) {
107 sock = tinfo->outputs;
108 while (sock->type != -1) {
109 MEM_freeN(sock->name);
112 MEM_freeN(tinfo->outputs);
113 tinfo->outputs = NULL;
117 static void node_dynamic_free_typeinfo(bNodeType *tinfo)
121 node_dynamic_free_typeinfo_sockets(tinfo);
123 if (tinfo->name) { MEM_freeN(tinfo->name); }
128 static void node_dynamic_free_sockets(bNode *node)
130 BLI_freelistN(&node->inputs);
131 BLI_freelistN(&node->outputs);
134 /* For now we just remove the socket links. It's the safest
135 * route, since an update in the script may change completely the
136 * inputs and outputs. Trying to recreate the node links would be
137 * nicer for pynode authors, though. */
138 static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree)
141 nodeVerifyType(ntree, node);
146 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
149 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
150 if (nd == node) nodeVerifyType(ma->nodetree, node);
157 static void node_dynamic_free_storage_cb(bNode *node)
164 if (!node->storage) return;
165 nsd = (NodeScriptDict *)(node->storage);
175 MEM_freeN(node->storage);
176 node->storage = NULL;
179 /* Disable pynode when its script fails */
180 static void node_dynamic_disable(bNode *node)
183 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
186 /* Disable all pynodes using the given text (script) id */
187 static void node_dynamic_disable_all_by_id(ID *id)
190 Material *ma; /* XXX hardcoded for shaders */
192 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
195 bNodeTree *ntree = ma->nodetree;
196 for (nd= ntree->nodes.first; nd; nd= nd->next) {
199 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR);
207 static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb)
209 bNodeLink *link, *next;
214 for (sock= lb->first; sock; sock= sock->next) {
215 for (link= ntree->links.first; link; link= next) {
217 if (link->fromsock==sock || link->tosock==sock) {
218 nodeRemLink(ntree, link);
224 /* XXX hardcoded for shaders */
225 static void node_dynamic_rem_all_links(bNodeType *tinfo)
230 in = tinfo->inputs ? 1 : 0;
231 out = tinfo->outputs ? 1 : 0;
233 if (!in && !out) return;
235 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
238 bNodeTree *ntree = ma->nodetree;
239 for (nd= ntree->nodes.first; nd; nd= nd->next) {
240 if (nd->typeinfo == tinfo) {
242 node_rem_socklist_links(ntree, &nd->inputs);
244 node_rem_socklist_links(ntree, &nd->outputs);
251 /* node_dynamic_reset: clean a pynode, getting rid of all
252 * data dynamically created for it. */
253 static void node_dynamic_reset(bNode *node, int unlink_text)
255 bNodeType *tinfo, *tinfo_default;
258 tinfo = node->typeinfo;
259 tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
261 if ((tinfo == tinfo_default) && unlink_text) {
262 ID *textID = node->id;
263 /* already at default (empty) state, which happens if this node's
264 * script failed to parse at the first stage: definition. We're here
265 * because its text was removed from Blender. */
266 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
269 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
270 if (nd->id == textID) {
273 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
274 BLI_strncpy(nd->name, "Dynamic", 8);
282 node_dynamic_rem_all_links(tinfo);
283 node_dynamic_free_typeinfo_sockets(tinfo);
285 /* reset all other XXX shader nodes sharing this typeinfo */
286 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
289 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
290 if (nd->typeinfo == tinfo) {
291 node_dynamic_free_storage_cb(nd);
292 node_dynamic_free_sockets(nd);
293 //node_dynamic_update_socket_links(nd, ma->nodetree);
294 nd->typeinfo = tinfo_default;
298 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
299 BLI_strncpy(nd->name, "Dynamic", 8);
306 /* XXX hardcoded for shaders: */
307 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
308 node_dynamic_free_typeinfo(tinfo);
311 /* Special case of the above function: for working pynodes
312 * that were saved on a .blend but fail for some reason when
313 * the file is opened. We need this because pynodes are initialized
315 static void node_dynamic_reset_loaded(bNode *node)
317 bNodeType *tinfo = node->typeinfo;
319 node_dynamic_rem_all_links(tinfo);
320 node_dynamic_free_typeinfo_sockets(tinfo);
321 node_dynamic_free_storage_cb(node);
322 /* XXX hardcoded for shaders: */
323 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
325 node_dynamic_free_typeinfo(tinfo);
326 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
329 int nodeDynamicUnlinkText(ID *txtid) {
333 /* find one node that uses this text */
334 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
336 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
337 if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) {
338 node_dynamic_reset(nd, 1); /* found, reset all */
344 return 0; /* no pynodes used this text */
347 static void node_dynamic_pyerror_print(bNode *node)
350 PyGILState_STATE gilstate = PyGILState_Ensure();
352 fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
353 if (PyErr_Occurred()) {
356 PySys_SetObject("last_traceback", NULL);
358 else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); }
360 PyGILState_Release(gilstate);
364 static void node_dynamic_register_type(bNode *node)
366 nodeRegisterType(&node_all_shaders, node->typeinfo);
367 /* nodeRegisterType copied it to a new one, so we
368 * free the typeinfo itself, but not what it
370 MEM_freeN(node->typeinfo);
371 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
372 MEM_freeN(node->typeinfo->name);
373 node->typeinfo->name = BLI_strdup(node->name);
377 /* node_dynamic_get_pynode:
378 * Find the pynode definition from the script */
379 static PyObject *node_dynamic_get_pynode(PyObject *dict)
383 PyObject *value = NULL;
385 /* script writer specified a node? */
386 value = PyDict_GetItemString(dict, "__node__");
389 if (PyObject_TypeCheck(value, &PyType_Type)) {
394 PyErr_SetString(PyExc_TypeError,
395 "expected class object derived from Scripted node");
400 /* case not, search for it in the script's global dictionary */
401 while (PyDict_Next(dict, &pos, &key, &value)) {
402 /* skip names we know belong to other available objects */
403 if (strcmp("Socket", PyString_AsString(key)) == 0)
405 else if (strcmp("Scripted", PyString_AsString(key)) == 0)
407 /* naive: we grab the first ob of type 'type': */
408 else if (PyObject_TypeCheck(value, &PyType_Type)) {
414 PyErr_SetString(PyExc_TypeError,
415 "no PyNode definition found in the script!");
418 #endif /* WITH_PYTHON */
420 static int node_dynamic_parse(struct bNode *node)
425 PyObject *dict= NULL;
426 PyObject *pynode_data= NULL;
427 PyObject *pynode= NULL;
428 PyObject *args= NULL;
429 NodeScriptDict *nsd = NULL;
430 PyObject *pyresult = NULL;
432 int is_valid_script = 0;
433 PyGILState_STATE gilstate;
435 if (!node->id || !node->storage)
438 /* READY, no need to be here */
439 if (BTST(node->custom1, NODE_DYNAMIC_READY))
443 gilstate = PyGILState_Ensure();
445 nsd = (NodeScriptDict *)node->storage;
447 dict = (PyObject *)(nsd->dict);
448 buf = txt_to_buf((Text *)node->id);
450 pyresult = PyRun_String(buf, Py_file_input, dict, dict);
455 if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
456 node_dynamic_disable(node);
458 node_dynamic_disable_all_by_id(node->id);
460 node_dynamic_pyerror_print(node);
461 PyGILState_Release(gilstate);
467 pynode_data = node_dynamic_get_pynode(dict);
470 BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node);
472 args = Py_BuildValue("(O)", socklists);
474 /* init it to get the input and output sockets */
475 pynode = PyObject_Call(pynode_data, args, NULL);
477 Py_DECREF(pynode_data);
478 Py_DECREF(socklists);
481 if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) {
482 InitNode((BPy_Node *)(pynode), node);
484 node->typeinfo->execfunc = node_dynamic_exec_cb;
487 /* for NEW, LOADED, REPARSE */
488 if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
489 node->typeinfo->pydict = dict;
490 node->typeinfo->pynode = pynode;
491 node->typeinfo->id = node->id;
492 if (BNTST(node->custom1, NODE_DYNAMIC_LOADED))
493 nodeAddSockets(node, node->typeinfo);
494 if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE))
495 node_dynamic_register_type(node);
499 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
503 PyGILState_Release(gilstate);
505 if (!is_valid_script) { /* not a valid pynode script */
506 node_dynamic_disable_all_by_id(node->id);
507 node_dynamic_pyerror_print(node);
515 /* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY)
516 * pynodes already linked to a script (node->id != NULL). */
517 static void node_dynamic_setup(bNode *node)
520 NodeScriptDict *nsd = NULL;
521 bNodeTree *nodetree = NULL;
522 bNodeType *ntype = NULL;
523 PyGILState_STATE gilstate;
534 /* NEW, but not linked to a script: link default (empty) typeinfo */
536 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders,
541 /* READY, no need to be here */
542 if (BTST(node->custom1, NODE_DYNAMIC_READY))
545 gilstate = PyGILState_Ensure();
547 /* ERROR, reset to (empty) defaults */
548 if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) {
549 node_dynamic_reset(node, 0);
550 PyGILState_Release(gilstate);
554 /* User asked to update this pynode, prepare it for reparsing */
555 if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) {
556 int needs_parsing = 1;
558 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
560 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
561 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE);
562 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
565 node->typeinfo = ntype;
566 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
567 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR);
570 else { nodeMakeDynamicType(node); }
573 node_dynamic_rem_all_links(node->typeinfo);
574 node_dynamic_free_typeinfo_sockets(node->typeinfo);
575 node_dynamic_update_socket_links(node, NULL);
576 node_dynamic_free_storage_cb(node);
580 nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
581 nsd->dict = init_dynamicdict();
583 /* prepared, now reparse: */
584 node_dynamic_parse(node);
585 PyGILState_Release(gilstate);
589 else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
590 /* when loading from a .blend we don't have G.main yet, so we
591 * quickly abuse node->storage in ntreeInitTypes (node.c) to have
592 * our nodetree ptr (needed if a pynode script that worked before
593 * saving the .blend for some reason fails upon loading): */
594 nodetree = (bNodeTree *)node->storage;
595 node->storage = NULL;
599 fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n");
601 nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
604 /* NEW, LOADED or REPARSE */
605 if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
606 /* check if there's already a bNodeType linked to this script */
607 /* (XXX hardcoded for shader nodes for now) */
608 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
610 if (ntype) { /* if so, reuse it */
611 node->typeinfo = ntype;
612 /* so this is actually an ADDEXIST type */
613 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
615 else { /* create bNodeType for this pynode */
616 nodeMakeDynamicType(node);
617 nsd->dict = init_dynamicdict();
618 if ((node_dynamic_parse(node) == -1) && nodetree) {
619 node_dynamic_reset_loaded(node);
621 PyGILState_Release(gilstate);
626 /* ADDEXIST: new pynode linked to an already registered dynamic type,
627 * we just reuse existing py dict and pynode */
628 nsd->dict = node->typeinfo->pydict;
629 nsd->node = node->typeinfo->pynode;
631 Py_INCREF((PyObject *)(nsd->dict));
632 Py_INCREF((PyObject *)(nsd->node));
634 if (BTST(node->custom1, NODE_DYNAMIC_NEW)) {
635 nodeAddSockets(node, node->typeinfo);
636 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW);
639 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST);
640 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
642 PyGILState_Release(gilstate);
643 #endif /* WITH_PYTHON */
647 /* node_dynamic_init_cb callback: called when a pynode is created.
648 * The pynode type is passed via node->custom2. It can be:
649 * 0: for loaded empty nodes
650 * NODE_DYNAMIC_MENU: for the default Dynamic node type
651 * > NODE_DYNAMIC_MENU: for the new types defined by scripts
653 static void node_dynamic_init_cb(bNode *node) {
654 int type = node->custom2;
658 if (type >= NODE_DYNAMIC_MENU) {
661 if (type == NODE_DYNAMIC_MENU) {
662 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
666 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
667 node->id = node->typeinfo->id;
670 node_dynamic_setup(node);
673 /* node_dynamic_copy_cb: pynode copy callback */
674 static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node)
680 PyGILState_STATE gilstate;
682 if (!orig_node->storage) return;
684 nsd = (NodeScriptDict *)(orig_node->storage);
685 new_node->storage = MEM_dupallocN(orig_node->storage);
687 gilstate = PyGILState_Ensure();
690 Py_INCREF((PyObject *)(nsd->node));
692 Py_INCREF((PyObject *)(nsd->dict));
694 PyGILState_Release(gilstate);
698 /* node_dynamic_exec_cb: the execution callback called per pixel
699 * during rendering. */
700 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) {
704 BPy_Node *mynode = NULL;
705 NodeScriptDict *nsd = NULL;
706 PyObject *pyresult = NULL;
707 PyObject *args = NULL;
709 PyGILState_STATE gilstate;
714 /*if (G.scene->r.threads > 1)
717 if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) {
718 node_dynamic_setup(node);
722 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
723 if (node->storage) node_dynamic_setup(node);
727 if (BTST(node->custom1, NODE_DYNAMIC_READY)) {
728 nsd = (NodeScriptDict *)node->storage;
729 mynode = (BPy_Node *)(nsd->node);
732 if (mynode && PyCallable_Check((PyObject *)mynode)) {
734 gilstate = PyGILState_Ensure();
737 shi = ((ShaderCallData *)data)->shi;
739 Node_SetStack(mynode, in, NODE_INPUTSTACK);
740 Node_SetStack(mynode, out, NODE_OUTPUTSTACK);
741 Node_SetShi(mynode, shi);
743 args=Py_BuildValue("()");
744 pyresult= PyObject_Call((PyObject *)mynode, args, NULL);
748 PyGILState_Release(gilstate);
749 node_dynamic_disable_all_by_id(node->id);
750 node_dynamic_pyerror_print(node);
751 node_dynamic_setup(node);
755 PyGILState_Release(gilstate);
761 void register_node_type_sh_dynamic(ListBase *lb)
763 static bNodeType ntype;
765 node_type_base(&ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS, NULL, NULL);
766 node_type_size(&ntype, 150, 60, 300);
767 node_type_init(&ntype, node_dynamic_init_cb);
768 node_type_storage(&ntype, "NodeScriptDict", node_dynamic_free_storage_cb, node_dynamic_copy_cb);
769 node_type_exec(&ntype, node_dynamic_exec_cb);
771 nodeRegisterType(lb, &ntype);
776 void register_node_type_sh_dynamic(ListBase *lb)
778 static bNodeType ntype;
780 node_type_base(&ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, 0, NULL, NULL);
782 nodeRegisterType(lb, &ntype);