Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2007 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Nathan Letwory 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 /* TODO, support python3.x */ 00034 #undef WITH_PYTHON 00035 00036 #ifdef WITH_PYTHON 00037 #include <Python.h> 00038 #include <compile.h> 00039 #include <eval.h> 00040 #endif 00041 00042 #include "DNA_text_types.h" 00043 #include "BKE_text.h" 00044 00045 00046 // XXX 00047 #if 0 00048 #ifdef WITH_PYTHON 00049 #include "api2_2x/Node.h" 00050 #include "api2_2x/gen_utils.h" 00051 #include "BPY_extern.h" 00052 #endif 00053 #endif 00054 00055 #include "node_shader_util.h" 00056 00057 // XXX 00058 #if 0 00059 static void node_dynamic_setup(bNode *node); 00060 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out); 00061 static void node_dynamic_free_storage_cb(bNode *node); 00062 00063 #ifdef WITH_PYTHON 00064 static PyObject *init_dynamicdict(void) 00065 { 00066 PyObject *newscriptdict, *item; 00067 PyGILState_STATE gilstate = PyGILState_Ensure(); 00068 00069 newscriptdict= PyDict_New(); 00070 00071 PyDict_SetItemString(newscriptdict, "__builtins__", PyEval_GetBuiltins()); 00072 item= PyString_FromString("__main__"); 00073 PyDict_SetItemString(newscriptdict, "__name__", item); 00074 Py_DECREF(item); 00075 00076 PyGILState_Release(gilstate); 00077 00078 return newscriptdict; 00079 } 00080 #endif 00081 00082 static bNodeType *node_dynamic_find_typeinfo(ListBase *list, ID *id) 00083 { 00084 bNodeType *ntype = list->first; 00085 00086 while(ntype) { 00087 if (ntype->type == NODE_DYNAMIC && ntype->id == id) 00088 break; 00089 ntype = ntype->next; 00090 } 00091 00092 return ntype; /* NULL if doesn't exist */ 00093 } 00094 00095 static void node_dynamic_free_typeinfo_sockets(bNodeType *tinfo) 00096 { 00097 bNodeSocketTemplate *sock; 00098 00099 if (!tinfo) return; 00100 00101 if (tinfo->inputs) { 00102 sock = tinfo->inputs; 00103 while (sock->type != -1) { 00104 MEM_freeN(sock->name); 00105 sock++; 00106 } 00107 MEM_freeN(tinfo->inputs); 00108 tinfo->inputs = NULL; 00109 } 00110 if (tinfo->outputs) { 00111 sock = tinfo->outputs; 00112 while (sock->type != -1) { 00113 MEM_freeN(sock->name); 00114 sock++; 00115 } 00116 MEM_freeN(tinfo->outputs); 00117 tinfo->outputs = NULL; 00118 } 00119 } 00120 00121 static void node_dynamic_free_typeinfo(bNodeType *tinfo) 00122 { 00123 if (!tinfo) return; 00124 00125 node_dynamic_free_typeinfo_sockets(tinfo); 00126 00127 if (tinfo->name) { MEM_freeN(tinfo->name); } 00128 00129 MEM_freeN(tinfo); 00130 } 00131 00132 static void node_dynamic_free_sockets(bNode *node) 00133 { 00134 BLI_freelistN(&node->inputs); 00135 BLI_freelistN(&node->outputs); 00136 } 00137 00138 /* For now we just remove the socket links. It's the safest 00139 * route, since an update in the script may change completely the 00140 * inputs and outputs. Trying to recreate the node links would be 00141 * nicer for pynode authors, though. */ 00142 static void node_dynamic_update_socket_links(bNode *node, bNodeTree *ntree) 00143 { 00144 if (ntree) { 00145 nodeVerifyType(ntree, node); 00146 } 00147 else { 00148 Material *ma; 00149 00150 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00151 if (ma->nodetree) { 00152 bNode *nd; 00153 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00154 if (nd == node) nodeVerifyType(ma->nodetree, node); 00155 } 00156 } 00157 } 00158 } 00159 } 00160 00161 static void node_dynamic_free_storage_cb(bNode *node) 00162 { 00163 #ifdef WITH_PYTHON 00164 NodeScriptDict *nsd; 00165 PyObject *pydict; 00166 BPy_Node *pynode; 00167 00168 if (!node->storage) return; 00169 nsd = (NodeScriptDict *)(node->storage); 00170 pydict = nsd->dict; 00171 if (pydict) { 00172 Py_DECREF(pydict); 00173 } 00174 pynode = nsd->node; 00175 if (pynode) { 00176 Py_DECREF(pynode); 00177 } 00178 #endif 00179 MEM_freeN(node->storage); 00180 node->storage = NULL; 00181 } 00182 00183 /* Disable pynode when its script fails */ 00184 static void node_dynamic_disable(bNode *node) 00185 { 00186 node->custom1 = 0; 00187 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR); 00188 } 00189 00190 /* Disable all pynodes using the given text (script) id */ 00191 static void node_dynamic_disable_all_by_id(ID *id) 00192 { 00193 #ifdef WITH_PYTHON 00194 Material *ma; /* XXX hardcoded for shaders */ 00195 00196 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00197 if (ma->nodetree) { 00198 bNode *nd; 00199 bNodeTree *ntree = ma->nodetree; 00200 for (nd= ntree->nodes.first; nd; nd= nd->next) { 00201 if (nd->id == id) { 00202 nd->custom1 = 0; 00203 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_ERROR); 00204 } 00205 } 00206 } 00207 } 00208 #endif 00209 } 00210 00211 static void node_rem_socklist_links(bNodeTree *ntree, ListBase *lb) 00212 { 00213 bNodeLink *link, *next; 00214 bNodeSocket *sock; 00215 00216 if (!lb) return; 00217 00218 for (sock= lb->first; sock; sock= sock->next) { 00219 for (link= ntree->links.first; link; link= next) { 00220 next= link->next; 00221 if (link->fromsock==sock || link->tosock==sock) { 00222 nodeRemLink(ntree, link); 00223 } 00224 } 00225 } 00226 } 00227 00228 /* XXX hardcoded for shaders */ 00229 static void node_dynamic_rem_all_links(bNodeType *tinfo) 00230 { 00231 Material *ma; 00232 int in, out; 00233 00234 in = tinfo->inputs ? 1 : 0; 00235 out = tinfo->outputs ? 1 : 0; 00236 00237 if (!in && !out) return; 00238 00239 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00240 if (ma->nodetree) { 00241 bNode *nd; 00242 bNodeTree *ntree = ma->nodetree; 00243 for (nd= ntree->nodes.first; nd; nd= nd->next) { 00244 if (nd->typeinfo == tinfo) { 00245 if (in) 00246 node_rem_socklist_links(ntree, &nd->inputs); 00247 if (out) 00248 node_rem_socklist_links(ntree, &nd->outputs); 00249 } 00250 } 00251 } 00252 } 00253 } 00254 00255 /* node_dynamic_reset: clean a pynode, getting rid of all 00256 * data dynamically created for it. */ 00257 static void node_dynamic_reset(bNode *node, int unlink_text) 00258 { 00259 bNodeType *tinfo, *tinfo_default; 00260 Material *ma; 00261 00262 tinfo = node->typeinfo; 00263 tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL); 00264 00265 if ((tinfo == tinfo_default) && unlink_text) { 00266 ID *textID = node->id; 00267 /* already at default (empty) state, which happens if this node's 00268 * script failed to parse at the first stage: definition. We're here 00269 * because its text was removed from Blender. */ 00270 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00271 if (ma->nodetree) { 00272 bNode *nd; 00273 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00274 if (nd->id == textID) { 00275 nd->id = NULL; 00276 nd->custom1 = 0; 00277 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); 00278 BLI_strncpy(nd->name, "Dynamic", 8); 00279 return; 00280 } 00281 } 00282 } 00283 } 00284 } 00285 00286 node_dynamic_rem_all_links(tinfo); 00287 node_dynamic_free_typeinfo_sockets(tinfo); 00288 00289 /* reset all other XXX shader nodes sharing this typeinfo */ 00290 for (ma= G.main->mat.first; ma; ma= ma->id.next) { 00291 if (ma->nodetree) { 00292 bNode *nd; 00293 for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { 00294 if (nd->typeinfo == tinfo) { 00295 node_dynamic_free_storage_cb(nd); 00296 node_dynamic_free_sockets(nd); 00297 //node_dynamic_update_socket_links(nd, ma->nodetree); 00298 nd->typeinfo = tinfo_default; 00299 if (unlink_text) { 00300 nd->id = NULL; 00301 nd->custom1 = 0; 00302 nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); 00303 BLI_strncpy(nd->name, "Dynamic", 8); 00304 } 00305 } 00306 } 00307 } 00308 } 00309 00310 /* XXX hardcoded for shaders: */ 00311 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } 00312 node_dynamic_free_typeinfo(tinfo); 00313 } 00314 00315 /* Special case of the above function: for working pynodes 00316 * that were saved on a .blend but fail for some reason when 00317 * the file is opened. We need this because pynodes are initialized 00318 * before G.main. */ 00319 static void node_dynamic_reset_loaded(bNode *node) 00320 { 00321 bNodeType *tinfo = node->typeinfo; 00322 00323 node_dynamic_rem_all_links(tinfo); 00324 node_dynamic_free_typeinfo_sockets(tinfo); 00325 node_dynamic_free_storage_cb(node); 00326 /* XXX hardcoded for shaders: */ 00327 if (tinfo->id) { BLI_remlink(&node_all_shaders, tinfo); } 00328 00329 node_dynamic_free_typeinfo(tinfo); 00330 node->typeinfo = node_dynamic_find_typeinfo(&node_all_shaders, NULL); 00331 } 00332 00333 int nodeDynamicUnlinkText(ID *txtid) 00334 { 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 { 00660 int type = node->custom2; 00661 00662 node->custom2 = 0; 00663 00664 if (type >= NODE_DYNAMIC_MENU) { 00665 node->custom1 = 0; 00666 00667 if (type == NODE_DYNAMIC_MENU) { 00668 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_NEW); 00669 return; 00670 } 00671 00672 node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ADDEXIST); 00673 node->id = node->typeinfo->id; 00674 } 00675 00676 node_dynamic_setup(node); 00677 } 00678 00679 /* node_dynamic_copy_cb: pynode copy callback */ 00680 static void node_dynamic_copy_cb(bNode *orig_node, bNode *new_node) 00681 { 00682 #ifndef WITH_PYTHON 00683 return; 00684 #else 00685 NodeScriptDict *nsd; 00686 PyGILState_STATE gilstate; 00687 00688 if (!orig_node->storage) return; 00689 00690 nsd = (NodeScriptDict *)(orig_node->storage); 00691 new_node->storage = MEM_dupallocN(orig_node->storage); 00692 00693 gilstate = PyGILState_Ensure(); 00694 00695 if (nsd->node) 00696 Py_INCREF((PyObject *)(nsd->node)); 00697 if (nsd->dict) 00698 Py_INCREF((PyObject *)(nsd->dict)); 00699 00700 PyGILState_Release(gilstate); 00701 #endif 00702 } 00703 00704 /* node_dynamic_exec_cb: the execution callback called per pixel 00705 * during rendering. */ 00706 static void node_dynamic_exec_cb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) 00707 { 00708 #ifndef WITH_PYTHON 00709 return; 00710 #else 00711 BPy_Node *mynode = NULL; 00712 NodeScriptDict *nsd = NULL; 00713 PyObject *pyresult = NULL; 00714 PyObject *args = NULL; 00715 ShadeInput *shi; 00716 PyGILState_STATE gilstate; 00717 00718 if (!node->id) 00719 return; 00720 00721 /*if (G.scene->r.threads > 1) 00722 return;*/ 00723 00724 if (BTST2(node->custom1, NODE_DYNAMIC_NEW, NODE_DYNAMIC_REPARSE)) { 00725 node_dynamic_setup(node); 00726 return; 00727 } 00728 00729 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) { 00730 if (node->storage) node_dynamic_setup(node); 00731 return; 00732 } 00733 00734 if (BTST(node->custom1, NODE_DYNAMIC_READY)) { 00735 nsd = (NodeScriptDict *)node->storage; 00736 mynode = (BPy_Node *)(nsd->node); 00737 00738 00739 if (mynode && PyCallable_Check((PyObject *)mynode)) { 00740 00741 gilstate = PyGILState_Ensure(); 00742 00743 mynode->node = node; 00744 shi = ((ShaderCallData *)data)->shi; 00745 00746 Node_SetStack(mynode, in, NODE_INPUTSTACK); 00747 Node_SetStack(mynode, out, NODE_OUTPUTSTACK); 00748 Node_SetShi(mynode, shi); 00749 00750 args=Py_BuildValue("()"); 00751 pyresult= PyObject_Call((PyObject *)mynode, args, NULL); 00752 Py_DECREF(args); 00753 00754 if (!pyresult) { 00755 PyGILState_Release(gilstate); 00756 node_dynamic_disable_all_by_id(node->id); 00757 node_dynamic_pyerror_print(node); 00758 node_dynamic_setup(node); 00759 return; 00760 } 00761 Py_DECREF(pyresult); 00762 PyGILState_Release(gilstate); 00763 } 00764 } 00765 #endif 00766 } 00767 00768 void register_node_type_sh_dynamic(bNodeTreeType *ttype) 00769 { 00770 static bNodeType ntype; 00771 00772 node_type_base(ttype, &ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, NODE_OPTIONS, NULL, NULL); 00773 node_type_compatibility(&ntype, NODE_OLD_SHADING); 00774 node_type_size(&ntype, 150, 60, 300); 00775 node_type_init(&ntype, node_dynamic_init_cb); 00776 node_type_storage(&ntype, "NodeScriptDict", node_dynamic_free_storage_cb, node_dynamic_copy_cb); 00777 node_type_exec(&ntype, node_dynamic_exec_cb); 00778 00779 nodeRegisterType(ttype, &ntype); 00780 } 00781 00782 #else 00783 00784 void register_node_type_sh_dynamic(bNodeTreeType *ttype) 00785 { 00786 static bNodeType ntype; 00787 00788 node_type_base(ttype, &ntype, NODE_DYNAMIC, "Dynamic", NODE_CLASS_OP_DYNAMIC, 0); 00789 node_type_compatibility(&ntype, NODE_OLD_SHADING); 00790 00791 nodeRegisterType(ttype, &ntype); 00792 } 00793 00794 #endif