fbc56dfcc835da4973d1308b94d3f3a9b1100992
[blender.git] / source / blender / nodes / intern / SHD_nodes / SHD_dynamic.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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. 
10  *
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.
15  *
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.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Nathan Letwory
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifndef DISABLE_PYTHON
31 #include <Python.h>
32 #include <compile.h>
33 #include <eval.h>
34 #endif
35
36 /* TODO, support python3.x */
37 #if PY_VERSION_HEX >= 0x03000000
38 #define DISABLE_PYTHON 1
39 #endif
40
41 #include "DNA_text_types.h"
42 #include "BKE_text.h"
43 #include "BKE_utildefines.h"
44
45 // XXX
46 #if 0
47 #ifndef DISABLE_PYTHON
48 #include "api2_2x/Node.h"
49 #include "api2_2x/gen_utils.h"
50 #include "BPY_extern.h"
51 #endif
52 #endif
53
54 #include "../SHD_util.h"
55
56 // XXX
57 #if 0
58 static void node_dynamic_setup(bNode *node);
59 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out);
60 static void node_dynamic_free_storage_cb(bNode *node);
61
62 #ifndef DISABLE_PYTHON
63 static PyObject *init_dynamicdict(void) {
64         PyObject *newscriptdict, *item;
65         PyGILState_STATE gilstate = PyGILState_Ensure();
66
67         newscriptdict= PyDict_New();
68
69         PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins());
70         item= PyString_FromString("__main__");
71         PyDict_SetItemString(newscriptdict, "__name__", item);
72         Py_DECREF(item);
73
74         PyGILState_Release(gilstate);
75
76         return newscriptdict;
77 }
78 #endif
79
80 static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
81 {
82         bNodeType *ntype = list->first;
83
84         while(ntype) {
85                 if (ntype->type == NODE_DYNAMIC && ntype->id == id)
86                         break;
87                 ntype = ntype->next;
88         }
89
90         return ntype; /* NULL if doesn't exist */
91 }
92
93 static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo)
94 {
95         bNodeSocketType *sock;
96
97         if (!tinfo) return;
98
99         if (tinfo->inputs) {
100                 sock = tinfo->inputs;
101                 while (sock->type != -1) {
102                         MEM_freeN(sock->name);
103                         sock++;
104                 }
105                 MEM_freeN(tinfo->inputs);
106                 tinfo->inputs = NULL;
107         }
108         if (tinfo->outputs) {
109                 sock = tinfo->outputs;
110                 while (sock->type != -1) {
111                         MEM_freeN(sock->name);
112                         sock++;
113                 }
114                 MEM_freeN(tinfo->outputs);
115                 tinfo->outputs = NULL;
116         }
117 }
118
119 static void node_dynamic_free_typeinfo(bNodeType *tinfo)
120 {
121         if (!tinfo) return;
122
123         node_dynamic_free_typeinfo_sockets(tinfo);
124
125         if (tinfo->name) { MEM_freeN(tinfo->name); }
126
127         MEM_freeN(tinfo);
128 }
129
130 static void node_dynamic_free_sockets(bNode *node)
131 {
132         BLI_freelistN(&node->inputs);
133         BLI_freelistN(&node->outputs);
134 }
135
136 /* For now we just remove the socket links. It's the safest
137  * route, since an update in the script may change completely the
138  * inputs and outputs. Trying to recreate the node links would be
139  * nicer for pynode authors, though. */
140 static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree)
141 {
142         if (ntree) {
143                 nodeVerifyType(ntree, node);
144         }
145         else {
146                 Material *ma;
147
148                 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
149                         if (ma->nodetree) {
150                                 bNode *nd;
151                                 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
152                                         if (nd == node) nodeVerifyType(ma->nodetree, node);
153                                 }
154                         }
155                 }
156         }
157 }
158
159 static void node_dynamic_free_storage_cb(bNode *node)
160 {
161 #ifndef DISABLE_PYTHON
162         NodeScriptDict *nsd;
163         PyObject *pydict;
164         BPy_Node *pynode;
165
166         if (!node->storage) return;
167         nsd = (NodeScriptDict *)(node->storage);
168         pydict = nsd->dict;
169         if (pydict) {
170                 Py_DECREF(pydict);
171         }
172         pynode = nsd->node;
173         if (pynode) {
174                 Py_DECREF(pynode);
175         }
176 #endif
177         MEM_freeN(node->storage);
178         node->storage = NULL;
179 }
180
181 /* Disable pynode when its script fails */
182 static void node_dynamic_disable(bNode *node)
183 {
184         node->custom1 = 0;
185         node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
186 }
187
188 /* Disable all pynodes using the given text (script) id */
189 static void node_dynamic_disable_all_by_id(ID *id)
190 {
191 #ifndef DISABLE_PYTHON
192         Material *ma; /* XXX hardcoded for shaders */
193
194         for (ma= G.main->mat.first; ma; ma= ma->id.next) {
195                 if (ma->nodetree) {
196                         bNode *nd;
197                         bNodeTree *ntree = ma->nodetree;
198                         for (nd= ntree->nodes.first; nd; nd= nd->next) {
199                                 if (nd->id == id) {
200                                         nd->custom1 = 0;
201                                         nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR);
202                                 }
203                         }
204                 }
205         }
206 #endif
207 }
208
209 static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb)
210 {
211         bNodeLink *link, *next;
212         bNodeSocket *sock;
213
214         if (!lb) return;
215
216         for (sock= lb->first; sock; sock= sock->next) {
217                 for (link= ntree->links.first; link; link= next) {
218                         next= link->next;
219                         if (link->fromsock==sock || link->tosock==sock) {
220                                 nodeRemLink(ntree, link);
221                         }
222                 }
223         }
224 }
225
226 /* XXX hardcoded for shaders */
227 static void node_dynamic_rem_all_links(bNodeType *tinfo)
228 {
229         Material *ma;
230         int in, out;
231
232         in = tinfo->inputs ? 1 : 0;
233         out = tinfo->outputs ? 1 : 0;
234
235         if (!in && !out) return;
236
237         for (ma= G.main->mat.first; ma; ma= ma->id.next) {
238                 if (ma->nodetree) {
239                         bNode *nd;
240                         bNodeTree *ntree = ma->nodetree;
241                         for (nd= ntree->nodes.first; nd; nd= nd->next) {
242                                 if (nd->typeinfo == tinfo) {
243                                         if (in)
244                                                 node_rem_socklist_links(ntree, &nd->inputs);
245                                         if (out)
246                                                 node_rem_socklist_links(ntree, &nd->outputs);
247                                 }
248                         }
249                 }
250         }
251 }
252
253 /* node_dynamic_reset: clean a pynode, getting rid of all
254  * data dynamically created for it. */
255 static void node_dynamic_reset(bNode *node, int unlink_text)
256 {
257         bNodeType *tinfo, *tinfo_default;
258         Material *ma;
259
260         tinfo = node->typeinfo;
261         tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
262
263         if ((tinfo == tinfo_default) && unlink_text) {
264                 ID *textID = node->id;
265         /* already at default (empty) state, which happens if this node's
266          * script failed to parse at the first stage: definition. We're here
267          * because its text was removed from Blender. */
268                 for (ma= G.main->mat.first; ma; ma= ma->id.next) {
269                         if (ma->nodetree) {
270                                 bNode *nd;
271                                 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
272                                         if (nd->id == textID) {
273                                                 nd->id = NULL;
274                                                 nd->custom1 = 0;
275                                                 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
276                                                 BLI_strncpy(nd->name, "Dynamic", 8);
277                                                 return;
278                                         }
279                                 }
280                         }
281                 }
282         }
283
284         node_dynamic_rem_all_links(tinfo);
285         node_dynamic_free_typeinfo_sockets(tinfo);
286
287         /* reset all other XXX shader nodes sharing this typeinfo */
288         for (ma= G.main->mat.first; ma; ma= ma->id.next) {
289                 if (ma->nodetree) {
290                         bNode *nd;
291                         for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
292                                 if (nd->typeinfo == tinfo) {
293                                         node_dynamic_free_storage_cb(nd);
294                                         node_dynamic_free_sockets(nd);
295                                         //node_dynamic_update_socket_links(nd, ma->nodetree);
296                                         nd->typeinfo = tinfo_default;
297                                         if (unlink_text) {
298                                                 nd->id = NULL;
299                                                 nd->custom1 = 0;
300                                                 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
301                                                 BLI_strncpy(nd->name, "Dynamic", 8);
302                                         }
303                                 }
304                         }
305                 }
306         }
307
308         /* XXX hardcoded for shaders: */
309         if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
310         node_dynamic_free_typeinfo(tinfo);
311 }
312
313 /* Special case of the above function: for working pynodes
314  * that were saved on a .blend but fail for some reason when
315  * the file is opened. We need this because pynodes are initialized
316  * before G.main. */
317 static void node_dynamic_reset_loaded(bNode *node)
318 {
319         bNodeType *tinfo = node->typeinfo;
320
321         node_dynamic_rem_all_links(tinfo);
322         node_dynamic_free_typeinfo_sockets(tinfo);
323         node_dynamic_free_storage_cb(node);
324         /* XXX hardcoded for shaders: */
325         if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
326
327         node_dynamic_free_typeinfo(tinfo);
328         node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
329 }
330
331 int nodeDynamicUnlinkText(ID *txtid) {
332         Material *ma;
333         bNode *nd;
334
335         /* find one node that uses this text */
336         for (ma= G.main->mat.first; ma; ma= ma->id.next) {
337                 if (ma->nodetree) {
338                         for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
339                                 if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) {
340                                         node_dynamic_reset(nd, 1); /* found, reset all */
341                                         return 1;
342                                 }
343                         }
344                 }
345         }
346         return 0; /* no pynodes used this text */
347 }
348
349 static void node_dynamic_pyerror_print(bNode *node)
350 {
351 #ifndef DISABLE_PYTHON
352         PyGILState_STATE gilstate = PyGILState_Ensure();
353
354         fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
355         if (PyErr_Occurred()) {
356                 PyErr_Print();
357                 PyErr_Clear();
358                 PySys_SetObject("last_traceback", NULL);
359         }
360         else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); }
361
362         PyGILState_Release(gilstate);
363 #endif
364 }
365
366 static void node_dynamic_register_type(bNode *node)
367 {
368         nodeRegisterType(&node_all_shaders, node->typeinfo);
369         /* nodeRegisterType copied it to a new one, so we
370          * free the typeinfo itself, but not what it
371          * points to: */
372         MEM_freeN(node->typeinfo);
373         node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
374         MEM_freeN(node->typeinfo->name);
375         node->typeinfo->name = BLI_strdup(node->name);
376 }
377
378 #ifndef DISABLE_PYTHON
379 /* node_dynamic_get_pynode:
380  * Find the pynode definition from the script */
381 static PyObject *node_dynamic_get_pynode(PyObject *dict)
382 {
383         PyObject *key= NULL;
384         Py_ssize_t pos = 0;
385         PyObject *value = NULL;
386
387         /* script writer specified a node? */
388         value = PyDict_GetItemString(dict, "__node__");
389
390         if (value) {
391                 if (PyObject_TypeCheck(value, &PyType_Type)) {
392                         Py_INCREF(value);
393                         return value;
394                 }
395                 else {
396                         PyErr_SetString(PyExc_TypeError,
397                                 "expected class object derived from Scripted node");
398                         return NULL;
399                 }
400         }
401
402         /* case not, search for it in the script's global dictionary */
403         while (PyDict_Next(dict, &pos, &key, &value)) {
404                 /* skip names we know belong to other available objects */
405                 if (strcmp("Socket", PyString_AsString(key)) == 0)
406                         continue;
407                 else if (strcmp("Scripted", PyString_AsString(key)) == 0)
408                         continue;
409                 /* naive: we grab the first ob of type 'type': */
410                 else if (PyObject_TypeCheck(value, &PyType_Type)) {
411                         Py_INCREF(value);
412                         return value;
413                 }
414         }
415
416         PyErr_SetString(PyExc_TypeError,
417                 "no PyNode definition found in the script!");
418         return NULL;
419 }
420 #endif /* DISABLE_PYTHON */
421
422 static int node_dynamic_parse(struct bNode *node)
423 {
424 #ifdef DISABLE_PYTHON
425         return -1;
426 #else
427         PyObject *dict= NULL;
428         PyObject *pynode_data= NULL;
429         PyObject *pynode= NULL;
430         PyObject *args= NULL;
431         NodeScriptDict *nsd = NULL;
432         PyObject *pyresult = NULL;
433         char *buf = NULL;
434         int is_valid_script = 0;
435         PyGILState_STATE gilstate;
436
437         if (!node->id || !node->storage)
438                 return 0;
439
440         /* READY, no need to be here */
441         if (BTST(node->custom1, NODE_DYNAMIC_READY))
442                 return 0;
443
444         /* for threading */
445         gilstate = PyGILState_Ensure();
446
447         nsd = (NodeScriptDict *)node->storage;
448
449         dict = (PyObject *)(nsd->dict);
450         buf = txt_to_buf((Text *)node->id);
451
452         pyresult = PyRun_String(buf, Py_file_input, dict, dict);
453
454         MEM_freeN(buf);
455
456         if (!pyresult) {
457                 if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
458                         node_dynamic_disable(node);
459                 } else {
460                 node_dynamic_disable_all_by_id(node->id);
461                 }
462                 node_dynamic_pyerror_print(node);
463                 PyGILState_Release(gilstate);
464                 return -1;
465         }
466
467         Py_DECREF(pyresult);
468
469         pynode_data = node_dynamic_get_pynode(dict);
470
471         if (pynode_data) {
472                 BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node);
473
474                 args = Py_BuildValue("(O)", socklists);
475
476                 /* init it to get the input and output sockets */
477                 pynode = PyObject_Call(pynode_data, args, NULL);
478
479                 Py_DECREF(pynode_data);
480                 Py_DECREF(socklists);
481                 Py_DECREF(args);
482
483                 if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) {
484                         InitNode((BPy_Node *)(pynode), node);
485                         nsd->node = pynode;
486                         node->typeinfo->execfunc = node_dynamic_exec_cb;
487                         is_valid_script = 1;
488
489                         /* for NEW, LOADED, REPARSE */
490                         if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
491                                 node->typeinfo->pydict = dict;
492                                 node->typeinfo->pynode = pynode;
493                                 node->typeinfo->id = node->id;
494                                 if (BNTST(node->custom1, NODE_DYNAMIC_LOADED))
495                                         nodeAddSockets(node, node->typeinfo);
496                                 if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE))
497                                         node_dynamic_register_type(node);
498                         }
499
500                         node->custom1 = 0;
501                         node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
502                 }
503         }
504
505         PyGILState_Release(gilstate);
506
507         if (!is_valid_script) { /* not a valid pynode script */
508                 node_dynamic_disable_all_by_id(node->id);
509                 node_dynamic_pyerror_print(node);
510                 return -1;
511         }
512
513         return 0;
514 #endif
515 }
516
517 /* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY)
518  * pynodes already linked to a script (node->id != NULL). */
519 static void node_dynamic_setup(bNode *node)
520 {
521 #ifndef DISABLE_PYTHON
522         NodeScriptDict *nsd = NULL;
523         bNodeTree *nodetree = NULL;
524         bNodeType *ntype = NULL;
525         PyGILState_STATE gilstate;
526
527         /* Possible cases:
528          * NEW
529          * ADDEXIST
530          * LOADED
531          * REPARSE
532          * ERROR
533          * READY
534          */
535
536         /* NEW, but not linked to a script: link default (empty) typeinfo */
537         if (!node->id) {
538                 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders,
539                                 NULL);
540                 return;
541         }
542
543         /* READY, no need to be here */
544         if (BTST(node->custom1, NODE_DYNAMIC_READY))
545                 return;
546
547         gilstate = PyGILState_Ensure();
548
549         /* ERROR, reset to (empty) defaults */
550         if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) {
551                 node_dynamic_reset(node, 0);
552                 PyGILState_Release(gilstate);
553                 return;
554         }
555
556         /* User asked to update this pynode, prepare it for reparsing */
557         if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) {
558                 int needs_parsing = 1;
559
560                 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
561
562                 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
563                         node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE);
564                         ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
565
566                         if (ntype) {
567                                 node->typeinfo = ntype;
568                                 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
569                                 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR);
570                                 needs_parsing = 0;
571                         }
572                         else { nodeMakeDynamicType(node); }
573
574                 } else {
575                         node_dynamic_rem_all_links(node->typeinfo);
576                         node_dynamic_free_typeinfo_sockets(node->typeinfo);
577                         node_dynamic_update_socket_links(node, NULL);
578                         node_dynamic_free_storage_cb(node);
579                 }
580
581                 if (needs_parsing) {
582                         nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
583                         nsd->dict = init_dynamicdict();
584                         node->storage = nsd;
585                         /* prepared, now reparse: */
586                         node_dynamic_parse(node);
587                         PyGILState_Release(gilstate);
588                         return;
589                 }
590         }
591         else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
592                 /* when loading from a .blend we don't have G.main yet, so we
593                  * quickly abuse node->storage in ntreeInitTypes (node.c) to have
594                  * our nodetree ptr (needed if a pynode script that worked before
595                  * saving the .blend for some reason fails upon loading): */
596                 nodetree = (bNodeTree *)node->storage;
597                 node->storage = NULL;
598         }
599
600         if (node->storage)
601                 fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n");
602
603         nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
604         node->storage = nsd;
605         
606         /* NEW, LOADED or REPARSE */
607         if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
608                 /* check if there's already a bNodeType linked to this script */
609                 /* (XXX hardcoded for shader nodes for now) */
610                 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
611
612                 if (ntype) { /* if so, reuse it */
613                         node->typeinfo = ntype;
614                         /* so this is actually an ADDEXIST type */
615                         node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
616                 }
617                 else { /* create bNodeType for this pynode */
618                         nodeMakeDynamicType(node);
619                         nsd->dict = init_dynamicdict();
620                         if ((node_dynamic_parse(node) == -1) && nodetree) {
621                                 node_dynamic_reset_loaded(node);
622                         }
623                         PyGILState_Release(gilstate);
624                         return;
625                 }
626         }
627
628         /* ADDEXIST: new pynode linked to an already registered dynamic type,
629          * we just reuse existing py dict and pynode */
630         nsd->dict = node->typeinfo->pydict;
631         nsd->node = node->typeinfo->pynode;
632
633         Py_INCREF((PyObject *)(nsd->dict));
634         Py_INCREF((PyObject *)(nsd->node));
635
636         if (BTST(node->custom1, NODE_DYNAMIC_NEW)) {
637                 nodeAddSockets(node, node->typeinfo);
638                 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW);
639         }
640
641         node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST);
642         node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
643
644         PyGILState_Release(gilstate);
645 #endif /* DISABLE_PYTHON */
646         return;
647 }
648
649 /* node_dynamic_init_cb callback: called when a pynode is created.
650  * The pynode type is passed via node->custom2. It can be:
651  *  0: for loaded empty nodes
652  *  NODE_DYNAMIC_MENU: for the default Dynamic node type
653  *  > NODE_DYNAMIC_MENU: for the new types defined by scripts
654 */
655 static void node_dynamic_init_cb(bNode *node) {
656         int type = node->custom2;
657
658         node->custom2 = 0;
659
660         if (type >= NODE_DYNAMIC_MENU) {
661                 node->custom1 = 0;
662
663                 if (type == NODE_DYNAMIC_MENU) {
664                         node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
665                         return;
666                 }
667
668                 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
669                 node->id = node->typeinfo->id;
670         }
671
672         node_dynamic_setup(node);
673 }
674
675 /* node_dynamic_copy_cb: pynode copy callback */
676 static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node)
677 {
678 #ifdef DISABLE_PYTHON
679         return;
680 #else
681         NodeScriptDict *nsd;
682         PyGILState_STATE gilstate;
683
684         if (!orig_node->storage) return;
685
686         nsd = (NodeScriptDict *)(orig_node->storage);
687         new_node->storage = MEM_dupallocN(orig_node->storage);
688
689         gilstate = PyGILState_Ensure();
690
691         if (nsd->node)
692                 Py_INCREF((PyObject *)(nsd->node));
693         if (nsd->dict)
694                 Py_INCREF((PyObject *)(nsd->dict));
695
696         PyGILState_Release(gilstate);
697 #endif
698 }
699
700 /* node_dynamic_exec_cb: the execution callback called per pixel
701  * during rendering. */
702 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) {
703 #ifdef DISABLE_PYTHON
704         return;
705 #else
706         BPy_Node *mynode = NULL;
707         NodeScriptDict *nsd = NULL;
708         PyObject *pyresult = NULL;
709         PyObject *args = NULL;
710         ShadeInput *shi;
711         PyGILState_STATE gilstate;
712
713         if (!node->id)
714                 return;
715
716         /*if (G.scene->r.threads > 1)
717                 return;*/
718
719         if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) {
720                 node_dynamic_setup(node);
721                 return;
722         }
723
724         if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
725                 if (node->storage) node_dynamic_setup(node);
726                 return;
727         }
728
729         if (BTST(node->custom1, NODE_DYNAMIC_READY)) {
730                 nsd = (NodeScriptDict *)node->storage;
731                 mynode = (BPy_Node *)(nsd->node);
732
733
734                 if (mynode && PyCallable_Check((PyObject *)mynode)) {
735
736                         gilstate = PyGILState_Ensure();
737
738                         mynode->node = node;
739                         shi = ((ShaderCallData *)data)->shi;
740
741                         Node_SetStack(mynode, in, NODE_INPUTSTACK);
742                         Node_SetStack(mynode, out, NODE_OUTPUTSTACK);
743                         Node_SetShi(mynode, shi);
744
745                         args=Py_BuildValue("()");
746                         pyresult= PyObject_Call((PyObject *)mynode, args, NULL);
747                         Py_DECREF(args);
748
749                         if (!pyresult) {
750                                 PyGILState_Release(gilstate);
751                                 node_dynamic_disable_all_by_id(node->id);
752                                 node_dynamic_pyerror_print(node);
753                                 node_dynamic_setup(node);
754                                 return;
755                         }
756                         Py_DECREF(pyresult);
757                         PyGILState_Release(gilstate);
758                 }
759         }
760 #endif
761 }
762
763 bNodeType node_dynamic_typeinfo = {
764         /* next, prev  */       NULL, NULL,
765         /* type code   */       NODE_DYNAMIC,
766         /* name        */       "Dynamic",
767         /* width+range */       150, 60, 300,
768         /* class+opts  */       NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS,
769         /* input sock  */       NULL,
770         /* output sock */       NULL,
771         /* storage     */       "NodeScriptDict",
772         /* execfunc    */       node_dynamic_exec_cb,
773         /* butfunc     */       NULL,
774         /* initfunc    */       node_dynamic_init_cb,
775         /* freefunc    */       node_dynamic_free_storage_cb,
776         /* copyfunc    */       node_dynamic_copy_cb,
777         /* id          */       NULL
778 };
779
780 #else
781
782 bNodeType node_dynamic_typeinfo = {NULL};
783
784 #endif
785
786