diff options
author | Nathan Letwory <nathan@letworyinteractive.com> | 2008-02-10 02:17:15 +0300 |
---|---|---|
committer | Nathan Letwory <nathan@letworyinteractive.com> | 2008-02-10 02:17:15 +0300 |
commit | 16514e3ddb8500242931650c93f1397147442eba (patch) | |
tree | c66895704889f7a42219fbcdf1b59d81e6858529 /source/blender/python | |
parent | a37d9470a7f4e042efb6ce873ee05308e9aec535 (diff) |
* Merge of PyNodes to trunk. Finally!
See http://wiki.blender.org/index.php/BlenderDev/PyNodes and
http://wiki.blender.org/index.php/BlenderDev/PyNodes/API
For current documentation.
Very very big thanks go to William Germano for fixing the memory issues left
and for improving on the code.
In the coming time documentation will be finalised and further stabilising
of PyNodes is to be expected.
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/SConscript | 4 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Blender.c | 2 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Node.c | 718 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Node.h | 14 |
4 files changed, 395 insertions, 343 deletions
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 9cd245394b0..f608787d66d 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = Split('BPY_interface.c BPY_menus.c') + env.Glob('api2_2x/*.c') -incs = 'api2_2x ../blenkernel ../blenlib ../blenloader' +incs = 'api2_2x ../blenkernel ../nodes ../blenlib ../blenloader' incs += ' ../render/extern/include ../radiosity/extern/include' incs += ' ../makesdna #intern/guardedalloc #intern/bmfont ../imbuf ../include' incs += ' ' + env['BF_PYTHON_INC'] @@ -20,6 +20,8 @@ if env['WITH_BF_QUICKTIME']==1: if env['WITH_BF_OPENEXR'] == 1: defs.append('WITH_OPENEXR') +defs.append('USE_PYNODES') + if env['WITH_BF_FFMPEG'] == 1: defs.append('WITH_FFMPEG') diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index db47d6550c2..46f7b9da79f 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -85,6 +85,7 @@ struct ID; /*keep me up here */ #include "Metaball.h" #include "Modifier.h" #include "NMesh.h" +#include "Node.h" #include "Object.h" #include "Group.h" #include "Registry.h" @@ -1047,6 +1048,7 @@ void M_Blender_Init(void) PyDict_SetItemString(dict, "Geometry", Geometry_Init()); PyDict_SetItemString(dict, "Modifier", Modifier_Init()); PyDict_SetItemString(dict, "NMesh", NMesh_Init()); + PyDict_SetItemString(dict, "Node", Node_Init()); PyDict_SetItemString(dict, "Noise", Noise_Init()); PyDict_SetItemString(dict, "Object", Object_Init()); PyDict_SetItemString(dict, "Group", Group_Init()); diff --git a/source/blender/python/api2_2x/Node.c b/source/blender/python/api2_2x/Node.c index 2871eda9432..195b61a39ea 100644 --- a/source/blender/python/api2_2x/Node.c +++ b/source/blender/python/api2_2x/Node.c @@ -1,5 +1,5 @@ /* - * $Id: Node.c 10454 2007-04-04 11:27:43Z jesterking $ + * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -36,6 +36,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_utildefines.h" #include "DNA_material_types.h" @@ -48,138 +49,199 @@ static PyObject *Node_repr( BPy_Node * self ); static int Node_compare(BPy_Node *a, BPy_Node *b); static PyObject *ShadeInput_repr( BPy_ShadeInput * self ); static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b); +static BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi); /** - * Take the descriptions from dict and create sockets for those in socks + * Take the descriptions from list and create sockets for those in socks * socks is a socketstack from a bNodeTypeInfo */ -static int dict_socks_to_typeinfo(PyObject *dict, bNodeSocketType **socks, int len, int stage) { - int a = 0, pos = 0; - PyObject *key = NULL, *value = NULL; +static int list_socks_to_typeinfo(PyObject *tuple, bNodeSocketType **socks, int stage, int limit) { + int len = 0, a = 0, pos = 0, retval = 0; + //wPyObject *key = NULL, *value = NULL; + PyObject *item, *arg; bNodeSocketType *newsocks = NULL; + char *s_name = NULL; + int s_type = SOCK_VALUE; + float s_val[4], s_min, s_max; - if(stage!=SH_NODE_DYNAMIC_READY && stage!=SH_NODE_DYNAMIC_ADDEXIST) { - newsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType"); - - if (dict) { - if(PyDict_Check(dict)) { - while(PyDict_Next(dict, &pos, &key, &value)) { - if(PyTuple_Check(value) && PyTuple_Size(value)==7) { - newsocks[a].name = BLI_strdup(PyString_AsString(key)); - newsocks[a].type = (int)(PyInt_AsLong(PyTuple_GetItem(value, 0))); - newsocks[a].val1 = (float)(PyFloat_AsDouble(PyTuple_GetItem(value, 1))); - newsocks[a].val2 = (float)(PyFloat_AsDouble(PyTuple_GetItem(value, 2))); - newsocks[a].val3 = (float)(PyFloat_AsDouble(PyTuple_GetItem(value, 3))); - newsocks[a].val4 = (float)(PyFloat_AsDouble(PyTuple_GetItem(value, 4))); - newsocks[a].min = (float)(PyFloat_AsDouble(PyTuple_GetItem(value, 5))); - newsocks[a].max = (float)(PyFloat_AsDouble(PyTuple_GetItem(value, 6))); - a++; - } - } - } else { - return(EXPP_ReturnIntError( PyExc_AttributeError, "INPUT must be a dict")); - } + if (BTST2(stage, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST)) + return 0; /* already has sockets */ + + len = PyTuple_Size(tuple); + + newsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType in Node.c"); + + for (pos = 0, a = 0; pos< len; pos++, a++) { + /* default socket values: */ + s_name = NULL; + s_type = SOCK_VALUE; + s_min = 0.0f; + s_max = 1.0f; + s_val[0] = s_val[1] = s_val[2] = s_val[3] = 1.0f; + + item = PyTuple_GetItem(tuple, pos); + + if (!PySequence_Check(item)) { + PyErr_SetString(PyExc_AttributeError, "a socket must be a List of Lists or Tuples"); + retval = -1; + break; } - newsocks[a].type = -1; - if(*socks) { - int b = 0; - while((*socks)[b].type!=-1) { - MEM_freeN((*socks)[b].name); - (*socks)[b].name = NULL; - b++; - } - MEM_freeN(*socks); + + arg = PySequence_Tuple(item); + + if (!PyArg_ParseTuple(arg, "s|iffffff", &s_name, &s_type, + &s_min, &s_max, + &s_val[0], &s_val[1], &s_val[2], &s_val[3] )) { + PyErr_SetString(PyExc_AttributeError, "socket definitions require a string and optionally an int and 6 floats"); + retval = -1; + Py_DECREF(arg); + break; } - *socks = newsocks; + + newsocks[a].name = BLI_strdupn(s_name, NODE_MAXSTR); + newsocks[a].type = s_type; + newsocks[a].min = s_min; + newsocks[a].max = s_max; + newsocks[a].val1 = s_val[0]; + newsocks[a].val2 = s_val[1]; + newsocks[a].val3 = s_val[2]; + newsocks[a].val4 = s_val[3]; + newsocks[a].limit = limit; + + Py_DECREF(arg); } - return 0; + + newsocks[a].type = -1; + + *socks = newsocks; + + return retval; } -/* Get number of complying entries in a dict. +/* Get number of complying entries in a list. * */ -static int num_dict_sockets(PyObject *dict) { - int a = 0, pos = 0; - PyObject *key = NULL, *value = NULL; - while(PyDict_Next(dict, &pos, &key, &value)) { - if(PyTuple_Check(value) && PyTuple_Size(value)==7) - a++; +/* unused +static int num_list_sockets(PyObject *list) { + int size = 0; + int i = 0, count = 0; + PyObject *element = NULL; + + size = PyList_Size(list); + for(i = 0; i < size; i++) { + element = PyList_GetItem(list, i); + //wPy_INCREF(element); + if(PyList_Check(element) && PyList_Size(element) == 8) + count++; + //wPy_DECREF(element); } - return a; + return count; +} +*/ +static void NodeSockets_dealloc(BPy_NodeSockets *self) +{ + Py_DECREF(self->input); + Py_DECREF(self->output); + self->ob_type->tp_free((PyObject *)self); } -static int Map_socketdef(PyObject *self, PyObject *args, void *closure) +static PyObject *Map_socketdef_getter(BPy_NodeSockets *self, void *closure) { - int newincnt = 0, newoutcnt = 0; - bNode *node = NULL; - BPy_DefinitionMap *defs= NULL; + PyObject *sockets = NULL; - Py_INCREF(args); - Py_INCREF(self); + switch ((int)closure) { + case 'I': /* inputs */ + Py_INCREF(self->input); + sockets = self->input; + break; + case 'O': /* outputs */ + Py_INCREF(self->output); + sockets = self->output; + break; + default: + fprintf(stderr, "DEBUG pynodes: wrong option in Map_socketdef_getter\n"); + Py_INCREF(Py_None); + sockets = Py_None; + break; + } + + return sockets; +} + +static int Map_socketdef(BPy_NodeSockets *self, PyObject *args, void *closure) +{ + bNode *node = NULL; + PyObject *tuple = NULL; - defs= (BPy_DefinitionMap *)self; - node= defs->node; + node = self->node; if(!node) { - fprintf(stderr,"! no bNode in BPy_Node (Map_socketdef)\n"); + fprintf(stderr,"DEBUG pynodes: No bNode in BPy_Node (Map_socketdef)\n"); return 0; } - if(node->custom1==SH_NODE_DYNAMIC_READY && node->custom1==SH_NODE_DYNAMIC_ADDEXIST) + if(BTST2(node->custom1, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST)) return 0; switch((int)closure) { case 'I': if (args) { - if(PyDict_Check(args)) { - newincnt = num_dict_sockets(args); - dict_socks_to_typeinfo(args, &(node->typeinfo->inputs), newincnt, node->custom1); + if(PySequence_Check(args)) { + tuple = PySequence_Tuple(args); + list_socks_to_typeinfo(tuple, &(node->typeinfo->inputs), node->custom1, 1); + Py_DECREF(self->input); + self->input = tuple; } else { - Py_DECREF(self); - Py_DECREF(args); - return(EXPP_ReturnIntError( PyExc_AttributeError, "INPUT must be a dict")); + return(EXPP_ReturnIntError( PyExc_AttributeError, "INPUT must be a List of Lists or Tuples")); } } break; case 'O': if (args) { - if(PyDict_Check(args)) { - newoutcnt = num_dict_sockets(args); - dict_socks_to_typeinfo(args, &(node->typeinfo->outputs), newoutcnt, node->custom1); + if(PyList_Check(args)) { + tuple = PySequence_Tuple(args); + list_socks_to_typeinfo(tuple, &(node->typeinfo->outputs), node->custom1, 0); + Py_DECREF(self->output); + self->output = tuple; } else { - Py_DECREF(self); - Py_DECREF(args); - return(EXPP_ReturnIntError( PyExc_AttributeError, "OUTPUT must be a dict")); + return(EXPP_ReturnIntError( PyExc_AttributeError, "OUTPUT must be a List of Lists or Tuples")); } } break; default: - fprintf(stderr, "Hrm, why we got no dict? Todo: figure out proper complaint to scripter\n"); + fprintf(stderr,"DEBUG pynodes: got no list in Map_socketdef\n"); break; } - Py_DECREF(self); - Py_DECREF(args); return 0; } -static PyGetSetDef InputDefMap_getseters[] = { - {"definitions", (getter)NULL, (setter)Map_socketdef, - "Set the inputs definition (dictionary)", +static PyGetSetDef NodeSockets_getseters[] = { + {"input", (getter)Map_socketdef_getter, (setter)Map_socketdef, + "Set this node's input sockets (list of lists or tuples)", + (void *)'I'}, + {"i" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef, + "Set this node's input sockets (list of lists or tuples)", (void *)'I'}, + {"output", (getter)Map_socketdef_getter, (setter)Map_socketdef, + "Set this node's output sockets (list of lists or tuples)", + (void *)'O'}, + {"o" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef, + "Set this node's output sockets (list of lists or tuples)", + (void *)'O'}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; -PyTypeObject InputDefMap_Type = { +PyTypeObject NodeSockets_Type = { PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /* ob_size */ /* For printing, in format "<module>.<name>" */ - "Blender.Node.InputDefinitions", /* char *tp_name; */ - sizeof( BPy_DefinitionMap ), /* int tp_basicsize; */ + "Blender.Node.Sockets", /* char *tp_name; */ + sizeof( BPy_NodeSockets ), /* int tp_basicsize; */ 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ - NULL,/* destructor tp_dealloc; */ + (destructor)NodeSockets_dealloc,/* destructor tp_dealloc; */ NULL, /* printfunc tp_print; */ NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ @@ -229,7 +291,7 @@ PyTypeObject InputDefMap_Type = { /*** Attribute descriptor and subclassing stuff ***/ 0, //BPy_MVertSeq_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ - InputDefMap_getseters, /* struct PyGetSetDef *tp_getset; */ + NodeSockets_getseters, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ @@ -251,127 +313,48 @@ PyTypeObject InputDefMap_Type = { NULL }; -BPy_DefinitionMap *Node_CreateInputDefMap(bNode *node) { - BPy_DefinitionMap *map = PyObject_NEW(BPy_DefinitionMap, &InputDefMap_Type); - map->node = node; - return map; +BPy_NodeSockets *Node_CreateSockets(bNode *node) { + BPy_NodeSockets *sockets = PyObject_NEW(BPy_NodeSockets, &NodeSockets_Type); + sockets->node = node; + sockets->input = PyList_New(0); + sockets->output = PyList_New(0); + return sockets; } /***************************************/ -static PyGetSetDef OutputDefMap_getseters[] = { - {"definitions", (getter)NULL, (setter)Map_socketdef, - "Set the outputs definition (dictionary)", - (void *)'O'}, - {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ -}; - -PyTypeObject OutputDefMap_Type = { - PyObject_HEAD_INIT( NULL ) /* required py macro */ - 0, /* ob_size */ - /* For printing, in format "<module>.<name>" */ - "Blender.Node.OutputDefinitions", /* char *tp_name; */ - sizeof( BPy_DefinitionMap ), /* int tp_basicsize; */ - 0, /* tp_itemsize; For allocation */ - - /* Methods to implement standard operations */ - - NULL,/* destructor tp_dealloc; */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* cmpfunc tp_compare; */ - NULL, /* reprfunc tp_repr; */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ - - /*** Added in release 2.2 ***/ - /* Iterators */ - 0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */ - 0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */ +static int sockinmap_len ( BPy_SockMap * self) { + bNode *node = self->node; + bNodeType *tinfo; + int a = 0; - /*** Attribute descriptor and subclassing stuff ***/ - 0, //BPy_MVertSeq_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - OutputDefMap_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL -}; + if (!node) return 0; -BPy_DefinitionMap *Node_CreateOutputDefMap(bNode *node) { - BPy_DefinitionMap *map = PyObject_NEW(BPy_DefinitionMap, &OutputDefMap_Type); - map->node = node; - return map; -} + tinfo = node->typeinfo; -/***************************************/ + if (BNTST(node->custom1, NODE_DYNAMIC_READY)) return 0; -static int sockinmap_len ( BPy_SockMap * self) { - int a = 0; - if(self->typeinfo) { - while(self->typeinfo->inputs[a].type!=-1) + if (tinfo && tinfo->inputs) { + while(self->node->typeinfo->inputs[a].type!=-1) a++; } return a; } static int sockinmap_has_key( BPy_SockMap *self, PyObject *key) { + bNode *node = self->node; + bNodeType *tinfo; + char *strkey = NULL; int a = 0; - char *strkey = PyString_AsString(key); - if(self->typeinfo){ - while(self->typeinfo->inputs[a].type!=-1) { - if(BLI_strcaseeq(self->typeinfo->inputs[a].name, strkey)) { + if (!node) return -1; + + tinfo = node->typeinfo; + strkey = PyString_AsString(key); + + if(tinfo && tinfo->inputs){ + while(self->node->typeinfo->inputs[a].type!=-1) { + if(BLI_strcaseeq(self->node->typeinfo->inputs[a].name, strkey)) { return a; } a++; @@ -380,39 +363,46 @@ static int sockinmap_has_key( BPy_SockMap *self, PyObject *key) { return -1; } -PyObject *sockinmap_subscript(BPy_SockMap *self, PyObject *idx) { - int a, _idx; - a = sockinmap_len(self); +PyObject *sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) { + int idx; + + if (!self->node) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, "no access to Blender node data!"); - if (PyString_Check(idx)) { - _idx = sockinmap_has_key( self, idx); + if (PyString_Check(pyidx)) { + idx = sockinmap_has_key(self, pyidx); } - else if(PyInt_Check(idx)) { - PyErr_SetString(PyExc_ValueError, "int index not implemented"); - Py_RETURN_NONE; + else if(PyInt_Check(pyidx)) { + int len = sockinmap_len(self); + idx = (int)PyInt_AsLong(pyidx); + if (idx < 0 || idx >= len) + return EXPP_ReturnPyObjError(PyExc_IndexError, "index out of range"); } - else if (PySlice_Check(idx)) { - PyErr_SetString(PyExc_ValueError, "slices not implemented"); - Py_RETURN_NONE; + else if (PySlice_Check(pyidx)) { + return EXPP_ReturnPyObjError(PyExc_ValueError, "slices not implemented"); } else { - PyErr_SetString(PyExc_IndexError, "Index must be string"); - Py_RETURN_NONE; + return EXPP_ReturnPyObjError(PyExc_IndexError, "index must be an int or a string"); } + if(idx<0) { /* we're not as nice as Python */ + return EXPP_ReturnPyObjError(PyExc_IndexError, "invalid socket index"); + } - switch(self->typeinfo->inputs[_idx].type) { + switch(self->node->typeinfo->inputs[idx].type) { case SOCK_VALUE: - return Py_BuildValue("f", self->stack[_idx]->vec[0]); + return Py_BuildValue("f", self->stack[idx]->vec[0]); break; case SOCK_VECTOR: - return Py_BuildValue("(fff)", self->stack[_idx]->vec[0], self->stack[_idx]->vec[1], self->stack[_idx]->vec[2]); + return Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]); break; case SOCK_RGBA: - return Py_BuildValue("(ffff)", self->stack[_idx]->vec[0], self->stack[_idx]->vec[1], self->stack[_idx]->vec[2], self->stack[_idx]->vec[3]); + /* otherwise RGBA tuple */ + return Py_BuildValue("(ffff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2], self->stack[idx]->vec[3]); break; default: break; } + Py_RETURN_NONE; } @@ -506,21 +496,35 @@ PyTypeObject SockInMap_Type = { }; static int sockoutmap_len ( BPy_SockMap * self) { + bNode *node = self->node; + bNodeType *tinfo; int a = 0; - if(self->typeinfo) { - while(self->typeinfo->outputs[a].type!=-1) + + if (!node) return 0; + + tinfo = node->typeinfo; + + if (tinfo && tinfo->outputs) { + while(self->node->typeinfo->outputs[a].type!=-1) a++; } return a; } static int sockoutmap_has_key( BPy_SockMap *self, PyObject *key) { + bNode *node = self->node; + bNodeType *tinfo; int a = 0; - char *strkey = PyString_AsString(key); + char *strkey = NULL; + + if (!node) return -1; + + tinfo = node->typeinfo; + strkey = PyString_AsString(key); - if(self->typeinfo){ - while(self->typeinfo->outputs[a].type!=-1) { - if(BLI_strcaseeq(self->typeinfo->outputs[a].name, strkey)) { + if(tinfo && tinfo->outputs){ + while(self->node->typeinfo->outputs[a].type!=-1) { + if(BLI_strcaseeq(self->node->typeinfo->outputs[a].name, strkey)) { return a; } a++; @@ -529,51 +533,89 @@ static int sockoutmap_has_key( BPy_SockMap *self, PyObject *key) { return -1; } -static int sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *idx, PyObject *value) { - int a, _idx; - a = sockoutmap_len(self); - if(PyInt_Check(idx)) { - _idx = (int)PyInt_AsLong(idx); +static int sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObject *value) { + int i, idx, len, wanted_len = 0, ret = -1; + PyObject *val; + PyObject **items; + + if (!self->node) + return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!"); + + if (PyInt_Check(pyidx)) { + idx = (int)PyInt_AsLong(pyidx); + if (idx < 0 || idx >= sockinmap_len(self)) + return EXPP_ReturnIntError(PyExc_IndexError, "index out of range"); } - else if (PyString_Check(idx)) { - _idx = sockoutmap_has_key( self, idx); + else if (PyString_Check(pyidx)) { + idx = sockoutmap_has_key(self, pyidx); } - else if (PySlice_Check(idx)) { - PyErr_SetString(PyExc_ValueError, "slices not implemented, yet"); - return -1; - } else { - PyErr_SetString(PyExc_IndexError, "Index must be int or string"); - return -1; - } - if(_idx > -1) { - switch(self->typeinfo->outputs[_idx].type) { - case SOCK_VALUE: - if(PyTuple_Size(value)==1) - self->stack[_idx]->vec[0] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 0)); - return 0; - break; - case SOCK_VECTOR: - if(PyTuple_Size(value)==3) { - self->stack[_idx]->vec[0] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 0)); - self->stack[_idx]->vec[1] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 1)); - self->stack[_idx]->vec[2] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 2)); - } - return 0; - break; - case SOCK_RGBA: - if(PyTuple_Size(value)==4) { - self->stack[_idx]->vec[0] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 0)); - self->stack[_idx]->vec[1] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 1)); - self->stack[_idx]->vec[2] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 2)); - self->stack[_idx]->vec[3] = (float)PyFloat_AsDouble(PyTuple_GetItem(value, 3)); - } - return 0; - break; - default: - break; + else if (PySlice_Check(pyidx)) { + return EXPP_ReturnIntError(PyExc_ValueError, "slices not yet implemented"); + } else { + return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string"); + } + + if (idx < 0) + return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string"); + + val = PySequence_Fast(value, "expected a numeric tuple or list"); + if (!val) return -1; + + len = PySequence_Fast_GET_SIZE(val); + + if (len == 0) { + Py_DECREF(val); + return EXPP_ReturnIntError(PyExc_AttributeError, "expected a non-empty numeric tuple or list"); + } + + items = PySequence_Fast_ITEMS(val); + + for (i = 0; i < len; i++) { + if (!PyNumber_Check(items[i])) { + Py_DECREF(val); + return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list"); } } - return 0; + + switch(self->node->typeinfo->outputs[idx].type) { + case SOCK_VALUE: + wanted_len = 1; + if (len == 1) { + self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]); + ret = 0; + } + break; + case SOCK_VECTOR: + wanted_len = 3; + if (len == 3) { + self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]); + self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]); + self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]); + ret = 0; + } + break; + case SOCK_RGBA: + wanted_len = 4; + if (len == 4) { + self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]); + self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]); + self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]); + self->stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]); + ret = 0; + } + break; + default: + break; + } + + Py_DECREF(val); + + if (ret == -1) { + PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple"); + fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len); + } + + return ret; } /* write only */ @@ -667,14 +709,14 @@ PyTypeObject SockOutMap_Type = { static BPy_SockMap *Node_CreateInputMap(bNode *node, bNodeStack **stack) { - BPy_SockMap *map= PyObject_NEW(BPy_SockMap, &SockInMap_Type); - map->typeinfo= node->typeinfo; - map->stack= stack; + BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockInMap_Type); + map->node = node; + map->stack = stack; return map; } static PyObject *Node_GetInputMap(BPy_Node *self) { - BPy_SockMap *inmap= Node_CreateInputMap(self->node, self->in); + BPy_SockMap *inmap = Node_CreateInputMap(self->node, self->in); return (PyObject *)(inmap); } @@ -685,11 +727,11 @@ static PyObject *Node_GetInputMap(BPy_Node *self) { #define TEXTURE 4 #define PIXEL 5 #define COLOR 6 -#define SPECULAR 7 -#define MIRROR 8 -#define AMBIENT 9 -#define AMBIENTFACTOR 10 -#define EMITFACTOR 11 +#define SPECULAR_COLOR 7 +#define MIRROR_COLOR 8 +#define AMBIENT_COLOR 9 +#define AMBIENT 10 +#define EMIT 11 #define DISPLACE 12 #define STRAND 13 #define STRESS 14 @@ -704,80 +746,80 @@ static PyObject *Node_GetInputMap(BPy_Node *self) { #define STRAND_D 37 static PyObject *ShadeInput_getAttribute(BPy_ShadeInput *self, void *type) { - PyObject *obj= NULL; + PyObject *obj = NULL; if(self->shi) { switch((int)type) { case SURFACEVIEWVECTOR: - obj= Py_BuildValue("(fff)", self->shi->view[0], self->shi->view[1], self->shi->view[2]); + obj = Py_BuildValue("(fff)", self->shi->view[0], self->shi->view[1], self->shi->view[2]); break; case VIEWNORMAL: - obj= Py_BuildValue("(fff)", self->shi->vn[0], self->shi->vn[1], self->shi->vn[2]); + obj = Py_BuildValue("(fff)", self->shi->vn[0], self->shi->vn[1], self->shi->vn[2]); break; case SURFACENORMAL: - obj= Py_BuildValue("(fff)", self->shi->facenor[0], self->shi->facenor[1], self->shi->facenor[2]); + obj = Py_BuildValue("(fff)", self->shi->facenor[0], self->shi->facenor[1], self->shi->facenor[2]); break; case GLOBALTEXTURE: - obj= Py_BuildValue("(fff)", self->shi->gl[0], self->shi->gl[1], self->shi->gl[2]); + obj = Py_BuildValue("(fff)", self->shi->gl[0], self->shi->gl[1], self->shi->gl[2]); break; case TEXTURE: - obj= Py_BuildValue("(fff)", self->shi->lo[0], self->shi->lo[1], self->shi->lo[2]); + obj = Py_BuildValue("(fff)", self->shi->lo[0], self->shi->lo[1], self->shi->lo[2]); break; case PIXEL: - obj= Py_BuildValue("(ii)", self->shi->xs, self->shi->ys); + obj = Py_BuildValue("(ii)", self->shi->xs, self->shi->ys); break; case COLOR: - obj= Py_BuildValue("(fff)", self->shi->r, self->shi->g, self->shi->b); + obj = Py_BuildValue("(fff)", self->shi->r, self->shi->g, self->shi->b); break; - case SPECULAR: - obj= Py_BuildValue("(fff)", self->shi->specr, self->shi->specg, self->shi->specb); + case SPECULAR_COLOR: + obj = Py_BuildValue("(fff)", self->shi->specr, self->shi->specg, self->shi->specb); break; - case MIRROR: - obj= Py_BuildValue("(fff)", self->shi->mirr, self->shi->mirg, self->shi->mirb); + case MIRROR_COLOR: + obj = Py_BuildValue("(fff)", self->shi->mirr, self->shi->mirg, self->shi->mirb); break; - case AMBIENT: - obj= Py_BuildValue("(fff)", self->shi->ambr, self->shi->ambg, self->shi->ambb); + case AMBIENT_COLOR: + obj = Py_BuildValue("(fff)", self->shi->ambr, self->shi->ambg, self->shi->ambb); break; - case AMBIENTFACTOR: - obj= PyFloat_FromDouble((double)(self->shi->amb)); + case AMBIENT: + obj = PyFloat_FromDouble((double)(self->shi->amb)); break; - case EMITFACTOR: - obj= PyFloat_FromDouble((double)(self->shi->emit)); + case EMIT: + obj = PyFloat_FromDouble((double)(self->shi->emit)); break; case DISPLACE: - obj= Py_BuildValue("(fff)", self->shi->displace[0], self->shi->displace[1], self->shi->displace[2]); + obj = Py_BuildValue("(fff)", self->shi->displace[0], self->shi->displace[1], self->shi->displace[2]); break; case STRAND: - obj= PyFloat_FromDouble((double)(self->shi->strand)); + obj = PyFloat_FromDouble((double)(self->shi->strandco)); break; case STRESS: - obj= PyFloat_FromDouble((double)(self->shi->stress)); + obj = PyFloat_FromDouble((double)(self->shi->stress)); break; case TANGENT: - obj= Py_BuildValue("(fff)", self->shi->tang[0], self->shi->tang[1], self->shi->tang[2]); + obj = Py_BuildValue("(fff)", self->shi->tang[0], self->shi->tang[1], self->shi->tang[2]); break; case SURFACE_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxco[0], self->shi->dxco[1], self->shi->dxco[2], self->shi->dyco[0], self->shi->dyco[1], self->shi->dyco[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxco[0], self->shi->dxco[1], self->shi->dxco[2], self->shi->dyco[0], self->shi->dyco[1], self->shi->dyco[2]); break; case TEXTURE_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxlo[0], self->shi->dxlo[1], self->shi->dxlo[2], self->shi->dylo[0], self->shi->dylo[1], self->shi->dylo[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxlo[0], self->shi->dxlo[1], self->shi->dxlo[2], self->shi->dylo[0], self->shi->dylo[1], self->shi->dylo[2]); break; case GLOBALTEXTURE_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxgl[0], self->shi->dxgl[1], self->shi->dxgl[2], self->shi->dygl[0], self->shi->dygl[1], self->shi->dygl[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxgl[0], self->shi->dxgl[1], self->shi->dxgl[2], self->shi->dygl[0], self->shi->dygl[1], self->shi->dygl[2]); break; case REFLECTION_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxref[0], self->shi->dxref[1], self->shi->dxref[2], self->shi->dyref[0], self->shi->dyref[1], self->shi->dyref[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxref[0], self->shi->dxref[1], self->shi->dxref[2], self->shi->dyref[0], self->shi->dyref[1], self->shi->dyref[2]); break; case NORMAL_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxno[0], self->shi->dxno[1], self->shi->dxno[2], self->shi->dyno[0], self->shi->dyno[1], self->shi->dyno[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxno[0], self->shi->dxno[1], self->shi->dxno[2], self->shi->dyno[0], self->shi->dyno[1], self->shi->dyno[2]); break; case STICKY_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxsticky[0], self->shi->dxsticky[1], self->shi->dxsticky[2], self->shi->dysticky[0], self->shi->dysticky[1], self->shi->dysticky[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxsticky[0], self->shi->dxsticky[1], self->shi->dxsticky[2], self->shi->dysticky[0], self->shi->dysticky[1], self->shi->dysticky[2]); break; case REFRACT_D: - obj= Py_BuildValue("(fff)(fff)", self->shi->dxrefract[0], self->shi->dxrefract[1], self->shi->dxrefract[2], self->shi->dyrefract[0], self->shi->dyrefract[1], self->shi->dyrefract[2]); + obj = Py_BuildValue("(fff)(fff)", self->shi->dxrefract[0], self->shi->dxrefract[1], self->shi->dxrefract[2], self->shi->dyrefract[0], self->shi->dyrefract[1], self->shi->dyrefract[2]); break; case STRAND_D: - obj= Py_BuildValue("(ff)", self->shi->dxstrand, self->shi->dystrand); + obj = Py_BuildValue("(ff)", self->shi->dxstrand, self->shi->dystrand); break; default: break; @@ -792,27 +834,26 @@ static PyObject *ShadeInput_getAttribute(BPy_ShadeInput *self, void *type) { static BPy_SockMap *Node_CreateOutputMap(bNode *node, bNodeStack **stack) { BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockOutMap_Type); - map->typeinfo= node->typeinfo; - map->stack= stack; + map->node = node; + map->stack = stack; return map; } static PyObject *Node_GetOutputMap(BPy_Node *self) { - BPy_SockMap *outmap= Node_CreateOutputMap(self->node, self->out); + BPy_SockMap *outmap = Node_CreateOutputMap(self->node, self->out); return (PyObject *)outmap; } static PyObject *Node_GetShi(BPy_Node *self) { - BPy_ShadeInput *shi= ShadeInput_CreatePyObject(self->shi); + BPy_ShadeInput *shi = ShadeInput_CreatePyObject(self->shi); return (PyObject *)shi; - } static PyObject *node_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *self; assert(type!=NULL && type->tp_alloc!=NULL); - self= type->tp_alloc(type, 1); + self = type->tp_alloc(type, 1); return self; } @@ -822,17 +863,29 @@ static int node_init(BPy_Node *self, PyObject *args, PyObject *kwds) } static PyGetSetDef BPy_Node_getseters[] = { - {"ins", + {"input", + (getter)Node_GetInputMap, (setter)NULL, + "Get the input sockets mapping (dictionary)", + NULL}, + {"i", /* alias */ (getter)Node_GetInputMap, (setter)NULL, - "Get the ShadeInput mapping (dictionary)", + "Get the input sockets mapping (dictionary)", + NULL}, + {"output", + (getter)Node_GetOutputMap, (setter)NULL, + "Get the output sockets mapping (dictionary)", NULL}, - {"outs", + {"o", /* alias */ (getter)Node_GetOutputMap, (setter)NULL, - "Get the ShadeInput mapping (dictionary)", + "Get the output sockets mapping (dictionary)", NULL}, {"shi", (getter)Node_GetShi, (setter)NULL, - "Get the ShadeInput (ShadeInput)", + "Get the Shade Input data (ShadeInput)", + NULL}, + {"s", /* alias */ + (getter)Node_GetShi, (setter)NULL, + "Get the Shade Input data (ShadeInput)", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -842,19 +895,19 @@ static PyGetSetDef BPy_ShadeInput_getseters[] = { (getter)ShadeInput_getAttribute, (setter)NULL, "Get the current texture coordinate (tuple)", (void*)TEXTURE}, - {"texture_global", + {"textureGlobal", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the current global texture coordinate (tuple)", (void*)GLOBALTEXTURE}, - {"surface_normal", + {"surfaceNormal", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the current surface normal (tuple)", (void*)SURFACENORMAL}, - {"view_normal", + {"viewNormal", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the current view normal (tuple)", (void*)VIEWNORMAL}, - {"surface_view_vec", + {"surfaceViewVector", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the vector pointing to the viewpoint from the point being shaded (tuple)", (void*)SURFACEVIEWVECTOR}, @@ -866,26 +919,26 @@ static PyGetSetDef BPy_ShadeInput_getseters[] = { (getter)ShadeInput_getAttribute, (setter)NULL, "Get the color for the point being shaded (tuple)", (void*)COLOR}, - {"specular", + {"specularColor", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the specular color for the point being shaded (tuple)", - (void*)SPECULAR}, - {"mirror", + (void*)SPECULAR_COLOR}, + {"mirrorColor", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the mirror color for the point being shaded (tuple)", - (void*)MIRROR}, - {"ambient", + (void*)MIRROR_COLOR}, + {"ambientColor", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the ambient color for the point being shaded (tuple)", - (void*)AMBIENT}, - {"ambient_factor", + (void*)AMBIENT_COLOR}, + {"ambient", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the ambient factor for the point being shaded (float)", - (void*)AMBIENTFACTOR}, - {"emit_factor", + (void*)AMBIENT}, + {"emit", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the emit factor for the point being shaded (float)", - (void*)EMITFACTOR}, + (void*)EMIT}, {"displace", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the displace vector for the point being shaded (tuple)", @@ -902,38 +955,38 @@ static PyGetSetDef BPy_ShadeInput_getseters[] = { (getter)ShadeInput_getAttribute, (setter)NULL, "Get the tangent vector (tuple)", (void*)TANGENT}, - {"surface_d", + {"surfaceD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the surface d (tuple of tuples)", (void*)SURFACE_D}, - {"texture_d", + {"textureD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the texture d (tuple of tuples)", (void*)TEXTURE_D}, - {"texture_global_d", + {"textureGlobalD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the global texture d (tuple of tuples)", (void*)GLOBALTEXTURE_D}, - {"reflection_d", + {"reflectionD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the reflection d (tuple of tuples)", (void*)REFLECTION_D}, - {"normal_d", + {"normalD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the normal d (tuple of tuples)", (void*)NORMAL_D}, - {"sticky_d", + {"stickyD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the sticky d (tuple of tuples)", (void*)STICKY_D}, - {"refract_d", + {"refractD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the refract d (tuple of tuples)", (void*)REFRACT_D}, - {"strand_d", + {"strandD", (getter)ShadeInput_getAttribute, (setter)NULL, "Get the strand d (tuple)", - (void*)REFRACT_D}, + (void*)STRAND_D}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -1101,7 +1154,6 @@ PyTypeObject ShadeInput_Type = { NULL }; - /* Initialise Node module */ PyObject *Node_Init(void) { @@ -1111,9 +1163,7 @@ PyObject *Node_Init(void) return NULL; if( PyType_Ready( &ShadeInput_Type ) < 0 ) return NULL; - if( PyType_Ready( &OutputDefMap_Type ) < 0 ) - return NULL; - if( PyType_Ready( &InputDefMap_Type ) < 0 ) + if( PyType_Ready( &NodeSockets_Type ) < 0 ) return NULL; if( PyType_Ready( &SockInMap_Type ) < 0 ) return NULL; @@ -1135,7 +1185,7 @@ PyObject *Node_Init(void) static int Node_compare(BPy_Node *a, BPy_Node *b) { bNode *pa = a->node, *pb = b->node; - return (pa==pb) ? 0 : -1; + return (pa == pb) ? 0 : -1; } static PyObject *Node_repr(BPy_Node *self) @@ -1154,13 +1204,13 @@ BPy_Node *Node_CreatePyObject(bNode *node) return (BPy_Node *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_Node object")); } - pynode->node= node; + pynode->node = node; return pynode; } void InitNode(BPy_Node *self, bNode *node) { - self->node= node; + self->node = node; } bNode *Node_FromPyObject(PyObject *pyobj) @@ -1170,16 +1220,16 @@ bNode *Node_FromPyObject(PyObject *pyobj) void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type) { - if(type==NODE_INPUTSTACK) { - self->in= stack; - } else if(type==NODE_OUTPUTSTACK) { - self->out= stack; + if(type == NODE_INPUTSTACK) { + self->in = stack; + } else if(type == NODE_OUTPUTSTACK) { + self->out = stack; } } void Node_SetShi(BPy_Node *self, ShadeInput *shi) { - self->shi= shi; + self->shi = shi; } /*********************/ @@ -1187,12 +1237,12 @@ void Node_SetShi(BPy_Node *self, ShadeInput *shi) static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b) { ShadeInput *pa = a->shi, *pb = b->shi; - return (pa==pb) ? 0 : -1; + return (pa == pb) ? 0 : -1; } static PyObject *ShadeInput_repr(BPy_ShadeInput *self) { - return PyString_FromFormat( "[ShadeInput @ \"%p\"]", self); + return PyString_FromFormat( "[ShadeInput at \"%p\"]", self); } BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi) diff --git a/source/blender/python/api2_2x/Node.h b/source/blender/python/api2_2x/Node.h index 434d0aa684a..ce42527342a 100644 --- a/source/blender/python/api2_2x/Node.h +++ b/source/blender/python/api2_2x/Node.h @@ -1,5 +1,5 @@ /* - * $Id: Node.h 10449 2007-04-03 11:24:11Z jesterking $ + * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -56,14 +56,16 @@ typedef struct BPy_ShadeInput { typedef struct { PyObject_VAR_HEAD - bNodeType *typeinfo; + bNode* node; bNodeStack **stack; } BPy_SockMap; typedef struct { PyObject_HEAD bNode *node; -} BPy_DefinitionMap; + PyObject *input; + PyObject *output; +} BPy_NodeSockets; typedef struct BPy_Node { PyObject_HEAD @@ -76,13 +78,9 @@ typedef struct BPy_Node { extern PyObject *Node_Init(void); extern void InitNode(BPy_Node *self, bNode *node); extern BPy_Node *Node_CreatePyObject(bNode *node); -extern BPy_DefinitionMap *Node_CreateOutputDefMap(bNode *node); -extern BPy_DefinitionMap *Node_CreateInputDefMap(bNode *node); +extern BPy_NodeSockets *Node_CreateSockets(bNode *node); extern void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type); extern void Node_SetShi(BPy_Node *self, ShadeInput *shi); -extern BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi); -extern void Node_dealloc(BPy_Node *self); -extern void ShadeInput_dealloc(BPy_ShadeInput *self); #define NODE_INPUTSTACK 0 #define NODE_OUTPUTSTACK 1 |