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