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