2
* ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18
* The Original Code is Copyright (C) 2007 Blender Foundation.
19
* All rights reserved.
21
* The Original Code is: all of this file.
23
* Contributor(s): Nathan Letwory
25
* ***** END GPL LICENSE BLOCK *****
28
/** \file blender/nodes/shader/nodes/node_shader_dynamic.c
33
/* TODO, support python3.x */
42
#include "DNA_text_types.h"
49
#include "api2_2x/Node.h"
50
#include "api2_2x/gen_utils.h"
51
#include "BPY_extern.h"
55
#include "node_shader_util.h"
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);
64
static PyObject *init_dynamicdict(void)
66
PyObject *newscriptdict, *item;
67
PyGILState_STATE gilstate = PyGILState_Ensure();
69
newscriptdict= PyDict_New();
71
PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins());
72
item= PyString_FromString("__main__");
73
PyDict_SetItemString(newscriptdict, "__name__", item);
76
PyGILState_Release(gilstate);
82
static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id)
84
bNodeType *ntype = list->first;
87
if (ntype->type == NODE_DYNAMIC && ntype->id == id)
92
return ntype; /* NULL if doesn't exist */
95
static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo)
97
bNodeSocketTemplate *sock;
102
sock = tinfo->inputs;
103
while (sock->type != -1) {
104
MEM_freeN(sock->name);
107
MEM_freeN(tinfo->inputs);
108
tinfo->inputs = NULL;
110
if (tinfo->outputs) {
111
sock = tinfo->outputs;
112
while (sock->type != -1) {
113
MEM_freeN(sock->name);
116
MEM_freeN(tinfo->outputs);
117
tinfo->outputs = NULL;
121
static void node_dynamic_free_typeinfo(bNodeType *tinfo)
125
node_dynamic_free_typeinfo_sockets(tinfo);
127
if (tinfo->name) { MEM_freeN(tinfo->name); }
132
static void node_dynamic_free_sockets(bNode *node)
134
BLI_freelistN(&node->inputs);
135
BLI_freelistN(&node->outputs);
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)
145
nodeVerifyType(ntree, node);
150
for (ma= G.main->mat.first; ma; ma= ma->id.next) {
153
for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
154
if (nd == node) nodeVerifyType(ma->nodetree, node);
161
static void node_dynamic_free_storage_cb(bNode *node)
168
if (!node->storage) return;
169
nsd = (NodeScriptDict *)(node->storage);
179
MEM_freeN(node->storage);
180
node->storage = NULL;
183
/* Disable pynode when its script fails */
184
static void node_dynamic_disable(bNode *node)
187
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
190
/* Disable all pynodes using the given text (script) id */
191
static void node_dynamic_disable_all_by_id(ID *id)
194
Material *ma; /* XXX hardcoded for shaders */
196
for (ma= G.main->mat.first; ma; ma= ma->id.next) {
199
bNodeTree *ntree = ma->nodetree;
200
for (nd= ntree->nodes.first; nd; nd= nd->next) {
203
nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR);
211
static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb)
213
bNodeLink *link, *next;
218
for (sock= lb->first; sock; sock= sock->next) {
219
for (link= ntree->links.first; link; link= next) {
221
if (link->fromsock==sock || link->tosock==sock) {
222
nodeRemLink(ntree, link);
228
/* XXX hardcoded for shaders */
229
static void node_dynamic_rem_all_links(bNodeType *tinfo)
234
in = tinfo->inputs ? 1 : 0;
235
out = tinfo->outputs ? 1 : 0;
237
if (!in && !out) return;
239
for (ma= G.main->mat.first; ma; ma= ma->id.next) {
242
bNodeTree *ntree = ma->nodetree;
243
for (nd= ntree->nodes.first; nd; nd= nd->next) {
244
if (nd->typeinfo == tinfo) {
246
node_rem_socklist_links(ntree, &nd->inputs);
248
node_rem_socklist_links(ntree, &nd->outputs);
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)
259
bNodeType *tinfo, *tinfo_default;
262
tinfo = node->typeinfo;
263
tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
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) {
273
for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) {
274
if (nd->id == textID) {
277
nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
278
BLI_strncpy(nd->name, "Dynamic", 8);
286
node_dynamic_rem_all_links(tinfo);
287
node_dynamic_free_typeinfo_sockets(tinfo);
289
/* reset all other XXX shader nodes sharing this typeinfo */
290
for (ma= G.main->mat.first; ma; ma= ma->id.next) {
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;
302
nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW);
303
BLI_strncpy(nd->name, "Dynamic", 8);
310
/* XXX hardcoded for shaders: */
311
if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); }
312
node_dynamic_free_typeinfo(tinfo);
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
319
static void node_dynamic_reset_loaded(bNode *node)
321
bNodeType *tinfo = node->typeinfo;
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); }
329
node_dynamic_free_typeinfo(tinfo);
330
node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL);
333
int nodeDynamicUnlinkText(ID *txtid)
338
/* find one node that uses this text */
339
for (ma= G.main->mat.first; ma; ma= ma->id.next) {
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 */
349
return 0; /* no pynodes used this text */
352
static void node_dynamic_pyerror_print(bNode *node)
355
PyGILState_STATE gilstate = PyGILState_Ensure();
357
fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name);
358
if (PyErr_Occurred()) {
361
PySys_SetObject("last_traceback", NULL);
363
else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); }
365
PyGILState_Release(gilstate);
369
static void node_dynamic_register_type(bNode *node)
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
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);
382
/* node_dynamic_get_pynode:
383
* Find the pynode definition from the script */
384
static PyObject *node_dynamic_get_pynode(PyObject *dict)
388
PyObject *value = NULL;
390
/* script writer specified a node? */
391
value = PyDict_GetItemString(dict, "__node__");
394
if (PyObject_TypeCheck(value, &PyType_Type)) {
399
PyErr_SetString(PyExc_TypeError,
400
"expected class object derived from Scripted node");
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)
410
else if (strcmp("Scripted", PyString_AsString(key)) == 0)
412
/* naive: we grab the first ob of type 'type': */
413
else if (PyObject_TypeCheck(value, &PyType_Type)) {
419
PyErr_SetString(PyExc_TypeError,
420
"no PyNode definition found in the script!");
423
#endif /* WITH_PYTHON */
425
static int node_dynamic_parse(struct bNode *node)
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;
437
int is_valid_script = 0;
438
PyGILState_STATE gilstate;
440
if (!node->id || !node->storage)
443
/* READY, no need to be here */
444
if (BTST(node->custom1, NODE_DYNAMIC_READY))
448
gilstate = PyGILState_Ensure();
450
nsd = (NodeScriptDict *)node->storage;
452
dict = (PyObject *)(nsd->dict);
453
buf = txt_to_buf((Text *)node->id);
455
pyresult = PyRun_String(buf, Py_file_input, dict, dict);
460
if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
461
node_dynamic_disable(node);
464
node_dynamic_disable_all_by_id(node->id);
466
node_dynamic_pyerror_print(node);
467
PyGILState_Release(gilstate);
473
pynode_data = node_dynamic_get_pynode(dict);
476
BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node);
478
args = Py_BuildValue("(O)", socklists);
480
/* init it to get the input and output sockets */
481
pynode = PyObject_Call(pynode_data, args, NULL);
483
Py_DECREF(pynode_data);
484
Py_DECREF(socklists);
487
if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) {
488
InitNode((BPy_Node *)(pynode), node);
490
node->typeinfo->execfunc = node_dynamic_exec_cb;
493
/* for NEW, LOADED, REPARSE */
494
if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
495
node->typeinfo->pydict = dict;
496
node->typeinfo->pynode = pynode;
497
node->typeinfo->id = node->id;
498
if (BNTST(node->custom1, NODE_DYNAMIC_LOADED))
499
nodeAddSockets(node, node->typeinfo);
500
if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE))
501
node_dynamic_register_type(node);
505
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
509
PyGILState_Release(gilstate);
511
if (!is_valid_script) { /* not a valid pynode script */
512
node_dynamic_disable_all_by_id(node->id);
513
node_dynamic_pyerror_print(node);
521
/* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY)
522
* pynodes already linked to a script (node->id != NULL). */
523
static void node_dynamic_setup(bNode *node)
526
NodeScriptDict *nsd = NULL;
527
bNodeTree *nodetree = NULL;
528
bNodeType *ntype = NULL;
529
PyGILState_STATE gilstate;
540
/* NEW, but not linked to a script: link default (empty) typeinfo */
542
node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders,
547
/* READY, no need to be here */
548
if (BTST(node->custom1, NODE_DYNAMIC_READY))
551
gilstate = PyGILState_Ensure();
553
/* ERROR, reset to (empty) defaults */
554
if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) {
555
node_dynamic_reset(node, 0);
556
PyGILState_Release(gilstate);
560
/* User asked to update this pynode, prepare it for reparsing */
561
if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) {
562
int needs_parsing = 1;
564
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
566
if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
567
node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE);
568
ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
571
node->typeinfo = ntype;
572
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
573
node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR);
576
else { nodeMakeDynamicType(node); }
580
node_dynamic_rem_all_links(node->typeinfo);
581
node_dynamic_free_typeinfo_sockets(node->typeinfo);
582
node_dynamic_update_socket_links(node, NULL);
583
node_dynamic_free_storage_cb(node);
587
nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
588
nsd->dict = init_dynamicdict();
590
/* prepared, now reparse: */
591
node_dynamic_parse(node);
592
PyGILState_Release(gilstate);
596
else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) {
597
/* when loading from a .blend we don't have G.main yet, so we
598
* quickly abuse node->storage in ntreeInitTypes (node.c) to have
599
* our nodetree ptr (needed if a pynode script that worked before
600
* saving the .blend for some reason fails upon loading): */
601
nodetree = (bNodeTree *)node->storage;
602
node->storage = NULL;
606
fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n");
608
nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary");
611
/* NEW, LOADED or REPARSE */
612
if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) {
613
/* check if there's already a bNodeType linked to this script */
614
/* (XXX hardcoded for shader nodes for now) */
615
ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id);
617
if (ntype) { /* if so, reuse it */
618
node->typeinfo = ntype;
619
/* so this is actually an ADDEXIST type */
620
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
622
else { /* create bNodeType for this pynode */
623
nodeMakeDynamicType(node);
624
nsd->dict = init_dynamicdict();
625
if ((node_dynamic_parse(node) == -1) && nodetree) {
626
node_dynamic_reset_loaded(node);
628
PyGILState_Release(gilstate);
633
/* ADDEXIST: new pynode linked to an already registered dynamic type,
634
* we just reuse existing py dict and pynode */
635
nsd->dict = node->typeinfo->pydict;
636
nsd->node = node->typeinfo->pynode;
638
Py_INCREF((PyObject *)(nsd->dict));
639
Py_INCREF((PyObject *)(nsd->node));
641
if (BTST(node->custom1, NODE_DYNAMIC_NEW)) {
642
nodeAddSockets(node, node->typeinfo);
643
node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW);
646
node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST);
647
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY);
649
PyGILState_Release(gilstate);
650
#endif /* WITH_PYTHON */
654
/* node_dynamic_init_cb callback: called when a pynode is created.
655
* The pynode type is passed via node->custom2. It can be:
656
* 0: for loaded empty nodes
657
* NODE_DYNAMIC_MENU: for the default Dynamic node type
658
* > NODE_DYNAMIC_MENU: for the new types defined by scripts
660
static void node_dynamic_init_cb(bNode *node)
662
int type = node->custom2;
666
if (type >= NODE_DYNAMIC_MENU) {
669
if (type == NODE_DYNAMIC_MENU) {
670
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW);
674
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST);
675
node->id = node->typeinfo->id;
678
node_dynamic_setup(node);
681
/* node_dynamic_copy_cb: pynode copy callback */
682
static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node)
688
PyGILState_STATE gilstate;
690
if (!orig_node->storage) return;
692
nsd = (NodeScriptDict *)(orig_node->storage);
693
new_node->storage = MEM_dupallocN(orig_node->storage);
695
gilstate = PyGILState_Ensure();
698
Py_INCREF((PyObject *)(nsd->node));
700
Py_INCREF((PyObject *)(nsd->dict));
702
PyGILState_Release(gilstate);
706
/* node_dynamic_exec_cb: the execution callback called per pixel
707
* during rendering. */
708
static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
713
BPy_Node *mynode = NULL;
714
NodeScriptDict *nsd = NULL;
715
PyObject *pyresult = NULL;
716
PyObject *args = NULL;
718
PyGILState_STATE gilstate;
724
if (G.scene->r.threads > 1)
728
if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) {
729
node_dynamic_setup(node);
733
if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
734
if (node->storage) node_dynamic_setup(node);
738
if (BTST(node->custom1, NODE_DYNAMIC_READY)) {
739
nsd = (NodeScriptDict *)node->storage;
740
mynode = (BPy_Node *)(nsd->node);
743
if (mynode && PyCallable_Check((PyObject *)mynode)) {
745
gilstate = PyGILState_Ensure();
748
shi = ((ShaderCallData *)data)->shi;
750
Node_SetStack(mynode, in, NODE_INPUTSTACK);
751
Node_SetStack(mynode, out, NODE_OUTPUTSTACK);
752
Node_SetShi(mynode, shi);
754
args=Py_BuildValue("()");
755
pyresult= PyObject_Call((PyObject *)mynode, args, NULL);
759
PyGILState_Release(gilstate);
760
node_dynamic_disable_all_by_id(node->id);
761
node_dynamic_pyerror_print(node);
762
node_dynamic_setup(node);
766
PyGILState_Release(gilstate);
772
void register_node_type_sh_dynamic(bNodeTreeType *ttype)
774
static bNodeType ntype;
776
node_type_base(ttype, &ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS, NULL, NULL);
777
node_type_compatibility(&ntype, NODE_OLD_SHADING);
778
node_type_size(&ntype, 150, 60, 300);
779
node_type_init(&ntype, node_dynamic_init_cb);
780
node_type_storage(&ntype, "NodeScriptDict", node_dynamic_free_storage_cb, node_dynamic_copy_cb);
781
node_type_exec(&ntype, node_dynamic_exec_cb);
783
nodeRegisterType(ttype, &ntype);
788
void register_node_type_sh_dynamic(bNodeTreeType *ttype)
790
static bNodeType ntype;
792
node_type_base(ttype, &ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, 0);
793
node_type_compatibility(&ntype, NODE_OLD_SHADING);
795
nodeRegisterType(ttype, &ntype);