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