|
Blender
V2.59
|
00001 /* 00002 * $Id: SHD_dynamic.c 35237 2011-02-27 20:13:22Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2007 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Nathan Letwory 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 /* TODO, support python3.x */ 00036 #undef WITH_PYTHON 00037 00038 #ifdef WITH_PYTHON 00039 #include <Python.h> 00040 #include <compile.h> 00041 #include <eval.h> 00042 #endif 00043 00044 #include "DNA_text_types.h" 00045 #include "BKE_text.h" 00046 00047 00048 // XXX 00049 #if 0 00050 #ifdef WITH_PYTHON 00051 #include "api2_2x/Node.h" 00052 #include "api2_2x/gen_utils.h" 00053 #include "BPY_extern.h" 00054 #endif 00055 #endif 00056 00057 #include "../SHD_util.h" 00058 00059 // XXX 00060 #if 0 00061 static void node_dynamic_setup(bNode *node); 00062 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out); 00063 static void node_dynamic_free_storage_cb(bNode *node); 00064 00065 #ifdef WITH_PYTHON 00066 static PyObject *init_dynamicdict(void) { 00067 PyObject *newscriptdict, *item; 00068 PyGILState_STATE gilstate = PyGILState_Ensure(); 00069 00070 newscriptdict= PyDict_New(); 00071 00072 PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins()); 00073 item= PyString_FromString("__main__"); 00074 PyDict_SetItemString(newscriptdict, "__name__", item); 00075 Py_DECREF(item); 00076 00077 PyGILState_Release(gilstate); 00078 00079 return newscriptdict; 00080 } 00081 #endif 00082 00083 static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id) 00084 { 00085 bNodeType *ntype = list->first; 00086 00087 while(ntype) { 00088 if (ntype->type == NODE_DYNAMIC && ntype->id == id) 00089 break; 00090 ntype = ntype->next; 00091 } 00092 00093 return ntype; /* NULL if doesn't exist */ 00094 } 00095 00096 static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo) 00097 { 00098 bNodeSocketType *sock; 00099 00100 if (!tinfo) return; 00101 00102 if (tinfo->inputs) { 00103 sock = tinfo->inputs; 00104 while (sock->type != -1) { 00105 MEM_freeN(sock->name); 00106 sock++; 00107 } 00108 MEM_freeN(tinfo->inputs); 00109 tinfo->inputs = NULL; 00110 } 00111 if (tinfo->outputs) { 00112 sock = tinfo->outputs; 00113 while (sock->type != -1) { 00114 MEM_freeN(sock->name); 00115 sock++; 00116 } 00117 MEM_freeN(tinfo->outputs); 00118 tinfo->outputs = NULL; 00119 } 00120 } 00121 00122 static void node_dynamic_free_typeinfo(bNodeType *tinfo) 00123 { 00124 if (!tinfo) return; 00125 00126 node_dynamic_free_typeinfo_sockets(tinfo); 00127 00128 if (tinfo->name) { MEM_freeN(tinfo->name); } 00129 00130 MEM_freeN(tinfo); 00131 } 00132 00133 static void node_dynamic_free_sockets(bNode *node) 00134 { 00135 BLI_freelistN(&node->inputs); 00136 BLI_freelistN(&node->outputs); 00137 } 00138 00139 /* For now we just remove the socket links. It's the safest 00140 * route, since an update in the script may change completely the 00141 * inputs and outputs. Trying to recreate the node links would be 00142 * nicer for pynode authors, though. */ 00143 static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree) 00144 { 00145 if (ntree) { 00146 nodeVerifyType(ntree, node); 00147 } 00148 else { 00149 Material *ma; 00150 00151 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00152 if (ma->nodetree) { 00153 bNode *nd; 00154 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00155 if (nd == node) nodeVerifyType(ma->nodetree, node); 00156 } 00157 } 00158 } 00159 } 00160 } 00161 00162 static void node_dynamic_free_storage_cb(bNode *node) 00163 { 00164 #ifdef WITH_PYTHON 00165 NodeScriptDict *nsd; 00166 PyObject *pydict; 00167 BPy_Node *pynode; 00168 00169 if (!node->storage) return; 00170 nsd = (NodeScriptDict *)(node->storage); 00171 pydict = nsd->dict; 00172 if (pydict) { 00173 Py_DECREF(pydict); 00174 } 00175 pynode = nsd->node; 00176 if (pynode) { 00177 Py_DECREF(pynode); 00178 } 00179 #endif 00180 MEM_freeN(node->storage); 00181 node->storage = NULL; 00182 } 00183 00184 /* Disable pynode when its script fails */ 00185 static void node_dynamic_disable(bNode *node) 00186 { 00187 node->custom1 = 0; 00188 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR); 00189 } 00190 00191 /* Disable all pynodes using the given text (script) id */ 00192 static void node_dynamic_disable_all_by_id(ID *id) 00193 { 00194 #ifdef WITH_PYTHON 00195 Material *ma; /* XXX hardcoded for shaders */ 00196 00197 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00198 if (ma->nodetree) { 00199 bNode *nd; 00200 bNodeTree *ntree = ma->nodetree; 00201 for (nd= ntree->nodes.first; nd; nd= nd->next) { 00202 if (nd->id == id) { 00203 nd->custom1 = 0; 00204 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR); 00205 } 00206 } 00207 } 00208 } 00209 #endif 00210 } 00211 00212 static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb) 00213 { 00214 bNodeLink *link, *next; 00215 bNodeSocket *sock; 00216 00217 if (!lb) return; 00218 00219 for (sock= lb->first; sock; sock= sock->next) { 00220 for (link= ntree->links.first; link; link= next) { 00221 next= link->next; 00222 if (link->fromsock==sock || link->tosock==sock) { 00223 nodeRemLink(ntree, link); 00224 } 00225 } 00226 } 00227 } 00228 00229 /* XXX hardcoded for shaders */ 00230 static void node_dynamic_rem_all_links(bNodeType *tinfo) 00231 { 00232 Material *ma; 00233 int in, out; 00234 00235 in = tinfo->inputs ? 1 : 0; 00236 out = tinfo->outputs ? 1 : 0; 00237 00238 if (!in && !out) return; 00239 00240 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00241 if (ma->nodetree) { 00242 bNode *nd; 00243 bNodeTree *ntree = ma->nodetree; 00244 for (nd= ntree->nodes.first; nd; nd= nd->next) { 00245 if (nd->typeinfo == tinfo) { 00246 if (in) 00247 node_rem_socklist_links(ntree, &nd->inputs); 00248 if (out) 00249 node_rem_socklist_links(ntree, &nd->outputs); 00250 } 00251 } 00252 } 00253 } 00254 } 00255 00256 /* node_dynamic_reset: clean a pynode, getting rid of all 00257 * data dynamically created for it. */ 00258 static void node_dynamic_reset(bNode *node, int unlink_text) 00259 { 00260 bNodeType *tinfo, *tinfo_default; 00261 Material *ma; 00262 00263 tinfo = node->typeinfo; 00264 tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL); 00265 00266 if ((tinfo == tinfo_default) && unlink_text) { 00267 ID *textID = node->id; 00268 /* already at default (empty) state, which happens if this node's 00269 * script failed to parse at the first stage: definition. We're here 00270 * because its text was removed from Blender. */ 00271 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00272 if (ma->nodetree) { 00273 bNode *nd; 00274 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00275 if (nd->id == textID) { 00276 nd->id = NULL; 00277 nd->custom1 = 0; 00278 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); 00279 BLI_strncpy(nd->name, "Dynamic", 8); 00280 return; 00281 } 00282 } 00283 } 00284 } 00285 } 00286 00287 node_dynamic_rem_all_links(tinfo); 00288 node_dynamic_free_typeinfo_sockets(tinfo); 00289 00290 /* reset all other XXX shader nodes sharing this typeinfo */ 00291 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00292 if (ma->nodetree) { 00293 bNode *nd; 00294 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00295 if (nd->typeinfo == tinfo) { 00296 node_dynamic_free_storage_cb(nd); 00297 node_dynamic_free_sockets(nd); 00298 //node_dynamic_update_socket_links(nd, ma->nodetree); 00299 nd->typeinfo = tinfo_default; 00300 if (unlink_text) { 00301 nd->id = NULL; 00302 nd->custom1 = 0; 00303 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); 00304 BLI_strncpy(nd->name, "Dynamic", 8); 00305 } 00306 } 00307 } 00308 } 00309 } 00310 00311 /* XXX hardcoded for shaders: */ 00312 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } 00313 node_dynamic_free_typeinfo(tinfo); 00314 } 00315 00316 /* Special case of the above function: for working pynodes 00317 * that were saved on a .blend but fail for some reason when 00318 * the file is opened. We need this because pynodes are initialized 00319 * before G.main. */ 00320 static void node_dynamic_reset_loaded(bNode *node) 00321 { 00322 bNodeType *tinfo = node->typeinfo; 00323 00324 node_dynamic_rem_all_links(tinfo); 00325 node_dynamic_free_typeinfo_sockets(tinfo); 00326 node_dynamic_free_storage_cb(node); 00327 /* XXX hardcoded for shaders: */ 00328 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } 00329 00330 node_dynamic_free_typeinfo(tinfo); 00331 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL); 00332 } 00333 00334 int nodeDynamicUnlinkText(ID *txtid) { 00335 Material *ma; 00336 bNode *nd; 00337 00338 /* find one node that uses this text */ 00339 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00340 if (ma->nodetree) { 00341 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00342 if ((nd->type == NODE_DYNAMIC) && (nd->id == txtid)) { 00343 node_dynamic_reset(nd, 1); /* found, reset all */ 00344 return 1; 00345 } 00346 } 00347 } 00348 } 00349 return 0; /* no pynodes used this text */ 00350 } 00351 00352 static void node_dynamic_pyerror_print(bNode *node) 00353 { 00354 #ifdef WITH_PYTHON 00355 PyGILState_STATE gilstate = PyGILState_Ensure(); 00356 00357 fprintf(stderr, "\nError in dynamic node script \"%s\":\n", node->name); 00358 if (PyErr_Occurred()) { 00359 PyErr_Print(); 00360 PyErr_Clear(); 00361 PySys_SetObject("last_traceback", NULL); 00362 } 00363 else { fprintf(stderr, "Not a valid dynamic node Python script.\n"); } 00364 00365 PyGILState_Release(gilstate); 00366 #endif 00367 } 00368 00369 static void node_dynamic_register_type(bNode *node) 00370 { 00371 nodeRegisterType(&node_all_shaders, node->typeinfo); 00372 /* nodeRegisterType copied it to a new one, so we 00373 * free the typeinfo itself, but not what it 00374 * points to: */ 00375 MEM_freeN(node->typeinfo); 00376 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, node->id); 00377 MEM_freeN(node->typeinfo->name); 00378 node->typeinfo->name = BLI_strdup(node->name); 00379 } 00380 00381 #ifdef WITH_PYTHON 00382 /* node_dynamic_get_pynode: 00383 * Find the pynode definition from the script */ 00384 static PyObject *node_dynamic_get_pynode(PyObject *dict) 00385 { 00386 PyObject *key= NULL; 00387 Py_ssize_t pos = 0; 00388 PyObject *value = NULL; 00389 00390 /* script writer specified a node? */ 00391 value = PyDict_GetItemString(dict, "__node__"); 00392 00393 if (value) { 00394 if (PyObject_TypeCheck(value, &PyType_Type)) { 00395 Py_INCREF(value); 00396 return value; 00397 } 00398 else { 00399 PyErr_SetString(PyExc_TypeError, 00400 "expected class object derived from Scripted node"); 00401 return NULL; 00402 } 00403 } 00404 00405 /* case not, search for it in the script's global dictionary */ 00406 while (PyDict_Next(dict, &pos, &key, &value)) { 00407 /* skip names we know belong to other available objects */ 00408 if (strcmp("Socket", PyString_AsString(key)) == 0) 00409 continue; 00410 else if (strcmp("Scripted", PyString_AsString(key)) == 0) 00411 continue; 00412 /* naive: we grab the first ob of type 'type': */ 00413 else if (PyObject_TypeCheck(value, &PyType_Type)) { 00414 Py_INCREF(value); 00415 return value; 00416 } 00417 } 00418 00419 PyErr_SetString(PyExc_TypeError, 00420 "no PyNode definition found in the script!"); 00421 return NULL; 00422 } 00423 #endif /* WITH_PYTHON */ 00424 00425 static int node_dynamic_parse(struct bNode *node) 00426 { 00427 #ifndef WITH_PYTHON 00428 return -1; 00429 #else 00430 PyObject *dict= NULL; 00431 PyObject *pynode_data= NULL; 00432 PyObject *pynode= NULL; 00433 PyObject *args= NULL; 00434 NodeScriptDict *nsd = NULL; 00435 PyObject *pyresult = NULL; 00436 char *buf = NULL; 00437 int is_valid_script = 0; 00438 PyGILState_STATE gilstate; 00439 00440 if (!node->id || !node->storage) 00441 return 0; 00442 00443 /* READY, no need to be here */ 00444 if (BTST(node->custom1, NODE_DYNAMIC_READY)) 00445 return 0; 00446 00447 /* for threading */ 00448 gilstate = PyGILState_Ensure(); 00449 00450 nsd = (NodeScriptDict *)node->storage; 00451 00452 dict = (PyObject *)(nsd->dict); 00453 buf = txt_to_buf((Text *)node->id); 00454 00455 pyresult = PyRun_String(buf, Py_file_input, dict, dict); 00456 00457 MEM_freeN(buf); 00458 00459 if (!pyresult) { 00460 if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) { 00461 node_dynamic_disable(node); 00462 } else { 00463 node_dynamic_disable_all_by_id(node->id); 00464 } 00465 node_dynamic_pyerror_print(node); 00466 PyGILState_Release(gilstate); 00467 return -1; 00468 } 00469 00470 Py_DECREF(pyresult); 00471 00472 pynode_data = node_dynamic_get_pynode(dict); 00473 00474 if (pynode_data) { 00475 BPy_NodeSocketLists *socklists = Node_CreateSocketLists(node); 00476 00477 args = Py_BuildValue("(O)", socklists); 00478 00479 /* init it to get the input and output sockets */ 00480 pynode = PyObject_Call(pynode_data, args, NULL); 00481 00482 Py_DECREF(pynode_data); 00483 Py_DECREF(socklists); 00484 Py_DECREF(args); 00485 00486 if (!PyErr_Occurred() && pynode && pytype_is_pynode(pynode)) { 00487 InitNode((BPy_Node *)(pynode), node); 00488 nsd->node = pynode; 00489 node->typeinfo->execfunc = node_dynamic_exec_cb; 00490 is_valid_script = 1; 00491 00492 /* for NEW, LOADED, REPARSE */ 00493 if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { 00494 node->typeinfo->pydict = dict; 00495 node->typeinfo->pynode = pynode; 00496 node->typeinfo->id = node->id; 00497 if (BNTST(node->custom1, NODE_DYNAMIC_LOADED)) 00498 nodeAddSockets(node, node->typeinfo); 00499 if (BNTST(node->custom1, NODE_DYNAMIC_REPARSE)) 00500 node_dynamic_register_type(node); 00501 } 00502 00503 node->custom1 = 0; 00504 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); 00505 } 00506 } 00507 00508 PyGILState_Release(gilstate); 00509 00510 if (!is_valid_script) { /* not a valid pynode script */ 00511 node_dynamic_disable_all_by_id(node->id); 00512 node_dynamic_pyerror_print(node); 00513 return -1; 00514 } 00515 00516 return 0; 00517 #endif 00518 } 00519 00520 /* node_dynamic_setup: prepare for execution (state: NODE_DYNAMIC_READY) 00521 * pynodes already linked to a script (node->id != NULL). */ 00522 static void node_dynamic_setup(bNode *node) 00523 { 00524 #ifdef WITH_PYTHON 00525 NodeScriptDict *nsd = NULL; 00526 bNodeTree *nodetree = NULL; 00527 bNodeType *ntype = NULL; 00528 PyGILState_STATE gilstate; 00529 00530 /* Possible cases: 00531 * NEW 00532 * ADDEXIST 00533 * LOADED 00534 * REPARSE 00535 * ERROR 00536 * READY 00537 */ 00538 00539 /* NEW, but not linked to a script: link default (empty) typeinfo */ 00540 if (!node->id) { 00541 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, 00542 NULL); 00543 return; 00544 } 00545 00546 /* READY, no need to be here */ 00547 if (BTST(node->custom1, NODE_DYNAMIC_READY)) 00548 return; 00549 00550 gilstate = PyGILState_Ensure(); 00551 00552 /* ERROR, reset to (empty) defaults */ 00553 if (BCLR(node->custom1, NODE_DYNAMIC_ERROR) == 0) { 00554 node_dynamic_reset(node, 0); 00555 PyGILState_Release(gilstate); 00556 return; 00557 } 00558 00559 /* User asked to update this pynode, prepare it for reparsing */ 00560 if (BTST(node->custom1, NODE_DYNAMIC_REPARSE)) { 00561 int needs_parsing = 1; 00562 00563 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); 00564 00565 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { 00566 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_REPARSE); 00567 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id); 00568 00569 if (ntype) { 00570 node->typeinfo = ntype; 00571 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); 00572 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ERROR); 00573 needs_parsing = 0; 00574 } 00575 else { nodeMakeDynamicType(node); } 00576 00577 } else { 00578 node_dynamic_rem_all_links(node->typeinfo); 00579 node_dynamic_free_typeinfo_sockets(node->typeinfo); 00580 node_dynamic_update_socket_links(node, NULL); 00581 node_dynamic_free_storage_cb(node); 00582 } 00583 00584 if (needs_parsing) { 00585 nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); 00586 nsd->dict = init_dynamicdict(); 00587 node->storage = nsd; 00588 /* prepared, now reparse: */ 00589 node_dynamic_parse(node); 00590 PyGILState_Release(gilstate); 00591 return; 00592 } 00593 } 00594 else if (BTST(node->custom1, NODE_DYNAMIC_LOADED)) { 00595 /* when loading from a .blend we don't have G.main yet, so we 00596 * quickly abuse node->storage in ntreeInitTypes (node.c) to have 00597 * our nodetree ptr (needed if a pynode script that worked before 00598 * saving the .blend for some reason fails upon loading): */ 00599 nodetree = (bNodeTree *)node->storage; 00600 node->storage = NULL; 00601 } 00602 00603 if (node->storage) 00604 fprintf(stderr, "\nDEBUG: PYNODES ERROR: non NULL node->storage in node_dynamic_setup()\n"); 00605 00606 nsd = MEM_callocN(sizeof(NodeScriptDict), "node script dictionary"); 00607 node->storage = nsd; 00608 00609 /* NEW, LOADED or REPARSE */ 00610 if (BNTST(node->custom1, NODE_DYNAMIC_ADDEXIST)) { 00611 /* check if there's already a bNodeType linked to this script */ 00612 /* (XXX hardcoded for shader nodes for now) */ 00613 ntype = node_dynamic_find_typeinfo(&node_all_shaders, node->id); 00614 00615 if (ntype) { /* if so, reuse it */ 00616 node->typeinfo = ntype; 00617 /* so this is actually an ADDEXIST type */ 00618 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); 00619 } 00620 else { /* create bNodeType for this pynode */ 00621 nodeMakeDynamicType(node); 00622 nsd->dict = init_dynamicdict(); 00623 if ((node_dynamic_parse(node) == -1) && nodetree) { 00624 node_dynamic_reset_loaded(node); 00625 } 00626 PyGILState_Release(gilstate); 00627 return; 00628 } 00629 } 00630 00631 /* ADDEXIST: new pynode linked to an already registered dynamic type, 00632 * we just reuse existing py dict and pynode */ 00633 nsd->dict = node->typeinfo->pydict; 00634 nsd->node = node->typeinfo->pynode; 00635 00636 Py_INCREF((PyObject *)(nsd->dict)); 00637 Py_INCREF((PyObject *)(nsd->node)); 00638 00639 if (BTST(node->custom1, NODE_DYNAMIC_NEW)) { 00640 nodeAddSockets(node, node->typeinfo); 00641 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_NEW); 00642 } 00643 00644 node->custom1 = BCLR(node->custom1, NODE_DYNAMIC_ADDEXIST); 00645 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_READY); 00646 00647 PyGILState_Release(gilstate); 00648 #endif /* WITH_PYTHON */ 00649 return; 00650 } 00651 00652 /* node_dynamic_init_cb callback: called when a pynode is created. 00653 * The pynode type is passed via node->custom2. It can be: 00654 * 0: for loaded empty nodes 00655 * NODE_DYNAMIC_MENU: for the default Dynamic node type 00656 * > NODE_DYNAMIC_MENU: for the new types defined by scripts 00657 */ 00658 static void node_dynamic_init_cb(bNode *node) { 00659 int type = node->custom2; 00660 00661 node->custom2 = 0; 00662 00663 if (type >= NODE_DYNAMIC_MENU) { 00664 node->custom1 = 0; 00665 00666 if (type == NODE_DYNAMIC_MENU) { 00667 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); 00668 return; 00669 } 00670 00671 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); 00672 node->id = node->typeinfo->id; 00673 } 00674 00675 node_dynamic_setup(node); 00676 } 00677 00678 /* node_dynamic_copy_cb: pynode copy callback */ 00679 static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) 00680 { 00681 #ifndef WITH_PYTHON 00682 return; 00683 #else 00684 NodeScriptDict *nsd; 00685 PyGILState_STATE gilstate; 00686 00687 if (!orig_node->storage) return; 00688 00689 nsd = (NodeScriptDict *)(orig_node->storage); 00690 new_node->storage = MEM_dupallocN(orig_node->storage); 00691 00692 gilstate = PyGILState_Ensure(); 00693 00694 if (nsd->node) 00695 Py_INCREF((PyObject *)(nsd->node)); 00696 if (nsd->dict) 00697 Py_INCREF((PyObject *)(nsd->dict)); 00698 00699 PyGILState_Release(gilstate); 00700 #endif 00701 } 00702 00703 /* node_dynamic_exec_cb: the execution callback called per pixel 00704 * during rendering. */ 00705 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { 00706 #ifndef WITH_PYTHON 00707 return; 00708 #else 00709 BPy_Node *mynode = NULL; 00710 NodeScriptDict *nsd = NULL; 00711 PyObject *pyresult = NULL; 00712 PyObject *args = NULL; 00713 ShadeInput *shi; 00714 PyGILState_STATE gilstate; 00715 00716 if (!node->id) 00717 return; 00718 00719 /*if (G.scene->r.threads > 1) 00720 return;*/ 00721 00722 if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) { 00723 node_dynamic_setup(node); 00724 return; 00725 } 00726 00727 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { 00728 if (node->storage) node_dynamic_setup(node); 00729 return; 00730 } 00731 00732 if (BTST(node->custom1, NODE_DYNAMIC_READY)) { 00733 nsd = (NodeScriptDict *)node->storage; 00734 mynode = (BPy_Node *)(nsd->node); 00735 00736 00737 if (mynode && PyCallable_Check((PyObject *)mynode)) { 00738 00739 gilstate = PyGILState_Ensure(); 00740 00741 mynode->node = node; 00742 shi = ((ShaderCallData *)data)->shi; 00743 00744 Node_SetStack(mynode, in, NODE_INPUTSTACK); 00745 Node_SetStack(mynode, out, NODE_OUTPUTSTACK); 00746 Node_SetShi(mynode, shi); 00747 00748 args=Py_BuildValue("()"); 00749 pyresult= PyObject_Call((PyObject *)mynode, args, NULL); 00750 Py_DECREF(args); 00751 00752 if (!pyresult) { 00753 PyGILState_Release(gilstate); 00754 node_dynamic_disable_all_by_id(node->id); 00755 node_dynamic_pyerror_print(node); 00756 node_dynamic_setup(node); 00757 return; 00758 } 00759 Py_DECREF(pyresult); 00760 PyGILState_Release(gilstate); 00761 } 00762 } 00763 #endif 00764 } 00765 00766 void register_node_type_sh_dynamic(ListBase *lb) 00767 { 00768 static bNodeType ntype; 00769 00770 node_type_base(&ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS, NULL, NULL); 00771 node_type_size(&ntype, 150, 60, 300); 00772 node_type_init(&ntype, node_dynamic_init_cb); 00773 node_type_storage(&ntype, "NodeScriptDict", node_dynamic_free_storage_cb, node_dynamic_copy_cb); 00774 node_type_exec(&ntype, node_dynamic_exec_cb); 00775 00776 nodeRegisterType(lb, &ntype); 00777 } 00778 00779 #else 00780 00781 void register_node_type_sh_dynamic(ListBase *lb) 00782 { 00783 static bNodeType ntype; 00784 00785 node_type_base(&ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, 0, NULL, NULL); 00786 00787 nodeRegisterType(lb, &ntype); 00788 } 00789 00790 #endif 00791 00792