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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 #ifndef DISABLE_PYTHON
36 #include "DNA_text_types.h"
38 #include "BKE_utildefines.h"
40 #ifndef DISABLE_PYTHON
41 #include "api2_2x/Node.h"
42 #include "api2_2x/gen_utils.h"
43 #include "BPY_extern.h"
46 #include "../SHD_util.h"
48 static void node_dynamic_setup(bNode *node);
49 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out);
50 static void node_dynamic_free_storage_cb(bNode *node);
52 #ifndef DISABLE_PYTHON
53 static PyObject *init_dynamicdict(void) {
54 PyObject *newscriptdict;
55 PyGILState_STATE gilstate = PyGILState_Ensure();
57 newscriptdict= PyDict_New();
59 PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins());
60 EXPP_dict_set_item_str(newscriptdict, "__name__", PyString_FromString("__main__"));
62 PyGILState_Release(gilstate);
68 static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
70 bNodeType *ntype = list->first;
73 if (ntype->type == NODE_DYNAMIC && ntype->id == id)
78 return ntype; /* NULL if doesn't exist */
81 static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo)
83 bNodeSocketType *sock;
89 while (sock->type != -1) {
90 MEM_freeN(sock->name);
93 MEM_freeN(tinfo->inputs);
97 sock = tinfo->outputs;
98 while (sock->type != -1) {
99 MEM_freeN(sock->name);
102 MEM_freeN(tinfo->outputs);
103 tinfo->outputs = NULL;
107 static void node_dynamic_free_typeinfo(bNodeType *tinfo)
111 node_dynamic_free_typeinfo_sockets(tinfo);
113 if (tinfo->name) { MEM_freeN(tinfo->name); }
118 static void node_dynamic_free_sockets(bNode *node)
120 BLI_freelistN(&node->inputs);
121 BLI_freelistN(&node->outputs);
124 /* For now we just remove the socket links. It's the safest
125 * route, since an update in the script may change completely the
126 * inputs and outputs. Trying to recreate the node links would be
127 * nicer for pynode authors, though. */
128 static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree)
131 nodeVerifyType(ntree, node);
136 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
139 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
140 if (nd == node) nodeVerifyType(ma->nodetree, node);
147 static void node_dynamic_free_storage_cb(bNode *node)
149 #ifndef DISABLE_PYTHON
154 if (!node->storage) return;
155 nsd = (NodeScriptDict *)(node->storage);
165 MEM_freeN(node->storage);
166 node->storage = NULL;
169 /* Disable pynode when its script fails */
170 static void node_dynamic_disable(bNode *node)
173 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
176 /* Disable all pynodes using the given text (script) id */
177 static void node_dynamic_disable_all_by_id(ID *id)
179 #ifndef DISABLE_PYTHON
180 Material *ma; /* XXX hardcoded for shaders */
182 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
185 bNodeTree *ntree = ma->nodetree;
186 for (nd= ntree->nodes.first; nd; nd= nd->next) {
189 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR);
197 static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb)
199 bNodeLink *link, *next;
204 for (sock= lb->first; sock; sock= sock->next) {
205 for (link= ntree->links.first; link; link= next) {
207 if (link->fromsock==sock || link->tosock==sock) {
208 nodeRemLink(ntree, link);
214 /* XXX hardcoded for shaders */
215 static void node_dynamic_rem_all_links(bNodeType *tinfo)
220 in = tinfo->inputs ? 1 : 0;
221 out = tinfo->outputs ? 1 : 0;
223 if (!in && !out) return;
225 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
228 bNodeTree *ntree = ma->nodetree;
229 for (nd= ntree->nodes.first; nd; nd= nd->next) {
230 if (nd->typeinfo == tinfo) {
232 node_rem_socklist_links(ntree, &nd->inputs);
234 node_rem_socklist_links(ntree, &nd->outputs);
241 /* node_dynamic_reset: clean a pynode, getting rid of all
242 * data dynamically created for it. */
243 static void node_dynamic_reset(bNode *node, int unlink_text)
245 bNodeType *tinfo, *tinfo_default;
248 tinfo = node->typeinfo;
249 tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
251 if ((tinfo == tinfo_default) && unlink_text) {
252 ID *textID = node->id;
253 /* already at default (empty) state, which happens if this node's
254 * script failed to parse at the first stage: definition. We're here
255 * because its text was removed from Blender. */
256 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
259 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
260 if (nd->id == textID) {
263 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
264 BLI_strncpy(nd->name, "Dynamic", 8);
272 node_dynamic_rem_all_links(tinfo);
273 node_dynamic_free_typeinfo_sockets(tinfo);
275 /* reset all other XXX shader nodes sharing this typeinfo */
276 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
279 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
280 if (nd->typeinfo == tinfo) {
281 node_dynamic_free_storage_cb(nd);
282 node_dynamic_free_sockets(nd);
283 //node_dynamic_update_socket_links(nd, ma->nodetree);
284 nd->typeinfo = tinfo_default;
288 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
289 BLI_strncpy(nd->name, "Dynamic", 8);
296 /* XXX hardcoded for shaders: */
297 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
298 node_dynamic_free_typeinfo(tinfo);
301 /* Special case of the above function: for working pynodes
302 * that were saved on a .blend but fail for some reason when
303 * the file is opened. We need this because pynodes are initialized
305 static void node_dynamic_reset_loaded(bNode *node)
307 bNodeType *tinfo = node->typeinfo;
309 node_dynamic_rem_all_links(tinfo);
310 node_dynamic_free_typeinfo_sockets(tinfo);
311 node_dynamic_free_storage_cb(node);
312 /* XXX hardcoded for shaders: */
313 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
315 node_dynamic_free_typeinfo(tinfo);
316 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
319 int nodeDynamicUnlinkText(ID *txtid) {
323 /* find one node that uses this text */
324 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
326 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
327 if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) {
328 node_dynamic_reset(nd, 1); /* found, reset all */
334 return 0; /* no pynodes used this text */
337 static void node_dynamic_pyerror_print(bNode *node)
339 #ifndef DISABLE_PYTHON
340 PyGILState_STATE gilstate = PyGILState_Ensure();
342 fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
343 if (PyErr_Occurred()) { PyErr_Print(); }
344 else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); }
346 PyGILState_Release(gilstate);
350 static void node_dynamic_register_type(bNode *node)
352 nodeRegisterType(&node_all_shaders, node->typeinfo);
353 /* nodeRegisterType copied it to a new one, so we
354 * free the typeinfo itself, but not what it
356 MEM_freeN(node->typeinfo);
357 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
358 MEM_freeN(node->typeinfo->name);
359 node->typeinfo->name = BLI_strdup(node->name);
362 #ifndef DISABLE_PYTHON
363 /* node_dynamic_get_pynode:
364 * Find the pynode definition from the script */
365 static PyObject *node_dynamic_get_pynode(PyObject *dict)
369 PyObject *value = NULL;
371 /* script writer specified a node? */
372 value = PyDict_GetItemString(dict, "__node__");
375 if (PyObject_TypeCheck(value, &PyType_Type)) {
380 PyErr_SetString(PyExc_TypeError,
381 "expected class object derived from Scripted node");
386 /* case not, search for it in the script's global dictionary */
387 while (PyDict_Next(dict, &pos, &key, &value)) {
388 /* skip names we know belong to other available objects */
389 if (strcmp("Socket", PyString_AsString(key)) == 0)
391 else if (strcmp("Scripted", PyString_AsString(key)) == 0)
393 /* naive: we grab the first ob of type 'type': */
394 else if (PyObject_TypeCheck(value, &PyType_Type)) {
400 PyErr_SetString(PyExc_TypeError,
401 "no PyNode definition found in the script!");
404 #endif /* DISABLE_PYTHON */
406 static int node_dynamic_parse(struct bNode *node)
408 #ifdef DISABLE_PYTHON
411 PyObject *dict= NULL;
412 PyObject *pynode_data= NULL;
413 PyObject *pynode= NULL;
414 PyObject *args= NULL;
415 NodeScriptDict *nsd = NULL;
416 PyObject *pyresult = NULL;
418 int is_valid_script = 0;
419 PyGILState_STATE gilstate;
421 if (!node->id || !node->storage)
424 /* READY, no need to be here */
425 if (BTST(node->custom1, NODE_DYNAMIC_READY))
429 gilstate = PyGILState_Ensure();
431 nsd = (NodeScriptDict *)node->storage;
433 dict = (PyObject *)(nsd->dict);
434 buf = txt_to_buf((Text *)node->id);
436 pyresult = PyRun_String(buf, Py_file_input, dict, dict);
441 if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
442 node_dynamic_disable(node);
444 node_dynamic_disable_all_by_id(node->id);
446 node_dynamic_pyerror_print(node);
447 PyGILState_Release(gilstate);
453 pynode_data = node_dynamic_get_pynode(dict);
456 BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node);
458 args = Py_BuildValue("(O)", socklists);
460 /* init it to get the input and output sockets */
461 pynode = PyObject_Call(pynode_data, args, NULL);
463 Py_DECREF(pynode_data);
464 Py_DECREF(socklists);
467 if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) {
468 InitNode((BPy_Node *)(pynode), node);
470 node->typeinfo->execfunc = node_dynamic_exec_cb;
473 /* for NEW, LOADED, REPARSE */
474 if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
475 node->typeinfo->pydict = dict;
476 node->typeinfo->pynode = pynode;
477 node->typeinfo->id = node->id;
478 if (BNTST(node->custom1, NODE_DYNAMIC_LOADED))
479 nodeAddSockets(node, node->typeinfo);
480 if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE))
481 node_dynamic_register_type(node);
485 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
489 PyGILState_Release(gilstate);
491 if (!is_valid_script) { /* not a valid pynode script */
492 node_dynamic_disable_all_by_id(node->id);
493 node_dynamic_pyerror_print(node);
501 /* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY)
502 * pynodes already linked to a script (node->id != NULL). */
503 static void node_dynamic_setup(bNode *node)
505 #ifndef DISABLE_PYTHON
506 NodeScriptDict *nsd = NULL;
507 bNodeTree *nodetree = NULL;
508 bNodeType *ntype = NULL;
509 PyGILState_STATE gilstate;
520 /* NEW, but not linked to a script: link default (empty) typeinfo */
522 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders,
527 /* READY, no need to be here */
528 if (BTST(node->custom1, NODE_DYNAMIC_READY))
531 gilstate = PyGILState_Ensure();
533 /* ERROR, reset to (empty) defaults */
534 if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) {
535 node_dynamic_reset(node, 0);
536 PyGILState_Release(gilstate);
540 /* User asked to update this pynode, prepare it for reparsing */
541 if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) {
542 int needs_parsing = 1;
544 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
546 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
547 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE);
548 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
551 node->typeinfo = ntype;
552 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
553 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR);
556 else { nodeMakeDynamicType(node); }
559 node_dynamic_rem_all_links(node->typeinfo);
560 node_dynamic_free_typeinfo_sockets(node->typeinfo);
561 node_dynamic_update_socket_links(node, NULL);
562 node_dynamic_free_storage_cb(node);
566 nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
567 nsd->dict = init_dynamicdict();
569 /* prepared, now reparse: */
570 node_dynamic_parse(node);
571 PyGILState_Release(gilstate);
575 else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
576 /* when loading from a .blend we don't have G.main yet, so we
577 * quickly abuse node->storage in ntreeInitTypes (node.c) to have
578 * our nodetree ptr (needed if a pynode script that worked before
579 * saving the .blend for some reason fails upon loading): */
580 nodetree = (bNodeTree *)node->storage;
581 node->storage = NULL;
585 fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n");
587 nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
590 /* NEW, LOADED or REPARSE */
591 if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
592 /* check if there's already a bNodeType linked to this script */
593 /* (XXX hardcoded for shader nodes for now) */
594 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
596 if (ntype) { /* if so, reuse it */
597 node->typeinfo = ntype;
598 /* so this is actually an ADDEXIST type */
599 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
601 else { /* create bNodeType for this pynode */
602 nodeMakeDynamicType(node);
603 nsd->dict = init_dynamicdict();
604 if ((node_dynamic_parse(node) == -1) && nodetree) {
605 node_dynamic_reset_loaded(node);
607 PyGILState_Release(gilstate);
612 /* ADDEXIST: new pynode linked to an already registered dynamic type,
613 * we just reuse existing py dict and pynode */
614 nsd->dict = node->typeinfo->pydict;
615 nsd->node = node->typeinfo->pynode;
617 Py_INCREF((PyObject *)(nsd->dict));
618 Py_INCREF((PyObject *)(nsd->node));
620 if (BTST(node->custom1, NODE_DYNAMIC_NEW)) {
621 nodeAddSockets(node, node->typeinfo);
622 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW);
625 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST);
626 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
628 PyGILState_Release(gilstate);
629 #endif /* DISABLE_PYTHON */
633 /* node_dynamic_init_cb callback: called when a pynode is created.
634 * The pynode type is passed via node->custom2. It can be:
635 * 0: for loaded empty nodes
636 * NODE_DYNAMIC_MENU: for the default Dynamic node type
637 * > NODE_DYNAMIC_MENU: for the new types defined by scripts
639 static void node_dynamic_init_cb(bNode *node) {
640 int type = node->custom2;
644 if (type >= NODE_DYNAMIC_MENU) {
647 if (type == NODE_DYNAMIC_MENU) {
648 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
652 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
653 node->id = node->typeinfo->id;
656 node_dynamic_setup(node);
659 /* node_dynamic_copy_cb: pynode copy callback */
660 static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node)
662 #ifdef DISABLE_PYTHON
666 PyGILState_STATE gilstate;
668 if (!orig_node->storage) return;
670 nsd = (NodeScriptDict *)(orig_node->storage);
671 new_node->storage = MEM_dupallocN(orig_node->storage);
673 gilstate = PyGILState_Ensure();
676 Py_INCREF((PyObject *)(nsd->node));
678 Py_INCREF((PyObject *)(nsd->dict));
680 PyGILState_Release(gilstate);
684 /* node_dynamic_exec_cb: the execution callback called per pixel
685 * during rendering. */
686 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) {
687 #ifdef DISABLE_PYTHON
690 BPy_Node *mynode = NULL;
691 NodeScriptDict *nsd = NULL;
692 PyObject *pyresult = NULL;
693 PyObject *args = NULL;
695 PyGILState_STATE gilstate;
700 /*if (G.scene->r.threads > 1)
703 if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) {
704 node_dynamic_setup(node);
708 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
709 if (node->storage) node_dynamic_setup(node);
713 if (BTST(node->custom1, NODE_DYNAMIC_READY)) {
714 nsd = (NodeScriptDict *)node->storage;
715 mynode = (BPy_Node *)(nsd->node);
718 if (mynode && PyCallable_Check((PyObject *)mynode)) {
720 gilstate = PyGILState_Ensure();
723 shi = ((ShaderCallData *)data)->shi;
725 Node_SetStack(mynode, in, NODE_INPUTSTACK);
726 Node_SetStack(mynode, out, NODE_OUTPUTSTACK);
727 Node_SetShi(mynode, shi);
729 args=Py_BuildValue("()");
730 pyresult= PyObject_Call((PyObject *)mynode, args, NULL);
734 PyGILState_Release(gilstate);
735 node_dynamic_disable_all_by_id(node->id);
736 node_dynamic_pyerror_print(node);
737 node_dynamic_setup(node);
741 PyGILState_Release(gilstate);
747 bNodeType node_dynamic_typeinfo = {
748 /* next, prev */ NULL, NULL,
749 /* type code */ NODE_DYNAMIC,
750 /* name */ "Dynamic",
751 /* width+range */ 150, 60, 300,
752 /* class+opts */ NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS,
753 /* input sock */ NULL,
754 /* output sock */ NULL,
755 /* storage */ "NodeScriptDict",
756 /* execfunc */ node_dynamic_exec_cb,
758 /* initfunc */ node_dynamic_init_cb,
759 /* freefunc */ node_dynamic_free_storage_cb,
760 /* copyfunc */ node_dynamic_copy_cb,