== PyNodes ==
[blender.git] / source / blender / python / api2_2x / Node.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2006, Blender Foundation
24  * All rights reserved.
25  *
26  * Original code is this file
27  *
28  * Contributor(s): Nathan Letwory
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31 */
32
33 #include "Node.h"
34
35 #include "BKE_global.h"
36 #include "BKE_main.h"
37 #include "BKE_node.h"
38 #include "BKE_utildefines.h"
39
40 #include "DNA_material_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "gen_utils.h"
46 #include "vector.h"
47
48 static PyObject *Node_repr( BPy_Node * self );
49 static int Node_compare(BPy_Node *a, BPy_Node *b);
50 static PyObject *ShadeInput_repr( BPy_ShadeInput * self );
51 static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b);
52 static BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi);
53
54 /* node socket type */
55
56 static PyObject *NodeSocket_getName(BPy_NodeSocket *self, void *unused)
57 {
58         return PyString_FromString(self->name);
59 }
60
61 static int NodeSocket_setName(BPy_NodeSocket *self, PyObject *value, void *unused)
62 {
63         char *name = NULL;
64
65         if (!PyString_Check(value))
66                 return EXPP_ReturnIntError( PyExc_TypeError,
67                         "expected a string" );
68
69         name = PyString_AsString(value);
70
71         if (!name)
72                 return EXPP_ReturnIntError(PyExc_RuntimeError,
73                         "couldn't convert value to string!");
74
75         BLI_strncpy(self->name, name, NODE_MAXSTR);
76
77         return 0;
78 }
79
80 static PyObject *NodeSocket_getVal(BPy_NodeSocket *self, void *unused)
81 {
82         PyObject *pyret = NULL;
83
84         if (self->type == SOCK_VALUE) {
85                 pyret = PyFloat_FromDouble(self->val[0]);
86         }
87         else { /* VECTOR or RGBA */
88                 pyret = newVectorObject(self->val, self->type, Py_NEW);
89
90                 if (!pyret)
91                         return EXPP_ReturnPyObjError(PyExc_RuntimeError,
92                                 "couldn't create vector object!");
93         }
94
95         return pyret;
96 }
97
98 static int NodeSocket_setVal(BPy_NodeSocket *self, PyObject *value, void *unused)
99 {
100         int error = 0;
101
102         if (PySequence_Check(value)) {
103                 PyObject *item, *fpyval;
104                 int i, len;
105
106                 len = PySequence_Size(value);
107
108                 if (len == 3 || len == 4) {
109                         for (i = 0; i < len; i++) {
110                                 item = PySequence_GetItem(value, i);
111                                 fpyval = PyNumber_Float(item);
112                                 if (!fpyval) {
113                                         Py_DECREF(item);
114                                         error = 1;
115                                         break;
116                                 }
117                                 self->val[i] = (float)PyFloat_AsDouble(fpyval);
118                                 Py_DECREF(item);
119                                 Py_DECREF(fpyval);
120                         }
121                         if (len == 3)
122                                 self->type = SOCK_VECTOR;
123                         else /* len == 4 */
124                                 self->type = SOCK_RGBA;
125                 }
126                 else error = 1;
127         }
128         else if (VectorObject_Check(value)) {
129                 VectorObject *vecOb = (VectorObject *)value;
130                 short vlen = vecOb->size;
131
132                 if (vlen == 3 || vlen == 4) {
133                         VECCOPY(self->val, vecOb->vec); /* copies 3 values */
134                         if (vlen == 3)
135                                 self->type = SOCK_VECTOR;
136                         else {
137                                 self->val[3] = vecOb->vec[3];
138                                 self->type = SOCK_RGBA;
139                         }
140                 }
141                 else error = 1;
142         }
143         else if (PyNumber_Check(value)) {
144                 self->val[0] = (float)PyFloat_AsDouble(value);
145                 self->type = SOCK_VALUE;
146         }
147         else error = 1;
148
149         if (error)
150                 return EXPP_ReturnIntError( PyExc_TypeError,
151                         "expected a float or a sequence (or vector) of 3 or 4 floats" );
152         return 0;
153 }
154
155 static PyObject *NodeSocket_getMin(BPy_NodeSocket *self, void *unused)
156 {
157         return PyFloat_FromDouble(self->min);
158 }
159
160 static int NodeSocket_setMin(BPy_NodeSocket *self, PyObject *value, void *unused)
161 {
162         PyObject *pyval = PyNumber_Float(value);
163
164         if (!pyval)
165                 return EXPP_ReturnIntError( PyExc_TypeError,
166                         "expected a float number" );
167
168         self->min = (float)PyFloat_AsDouble(pyval);
169         Py_DECREF(pyval);
170
171         return 0;
172 }
173
174 static PyObject *NodeSocket_getMax(BPy_NodeSocket *self, void *unused)
175 {
176         return PyFloat_FromDouble(self->max);
177 }
178
179 static int NodeSocket_setMax(BPy_NodeSocket *self, PyObject *value, void *unused)
180 {
181         PyObject *pyval = PyNumber_Float(value);
182
183         if (!pyval)
184                 return EXPP_ReturnIntError( PyExc_TypeError,
185                         "expected a float number" );
186
187         self->max = (float)PyFloat_AsDouble(pyval);
188         Py_DECREF(pyval);
189
190         return 0;
191 }
192
193 static PyGetSetDef NodeSocket_getseters[] = {
194         {"name", (getter)NodeSocket_getName, (setter)NodeSocket_setName,
195                 "This socket's name", NULL},
196         {"val", (getter)NodeSocket_getVal, (setter)NodeSocket_setVal,
197                 "This socket's data value(s)", NULL},
198         {"min", (getter)NodeSocket_getMin, (setter)NodeSocket_setMin,
199                 "This socket's min possible value (lower range limit)", NULL},
200         {"max", (getter)NodeSocket_getMax, (setter)NodeSocket_setMax,
201                 "This socket's max possible value (upper range limit)", NULL},
202         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
203 };
204
205 static void NodeSocket_dealloc(BPy_NodeSocket *self)
206 {
207         self->ob_type->tp_free((PyObject *)self);
208 }
209
210 static PyObject *NodeSocket_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
211 {
212         PyObject *pysocket = type->tp_alloc(type, 0);
213
214         if (!pysocket)
215                 return EXPP_ReturnPyObjError(PyExc_RuntimeError, "couldn't create socket type!");
216
217         return pysocket;
218 }
219
220 static int NodeSocket_init(BPy_NodeSocket *self, PyObject *args, PyObject *kwargs)
221 {
222         char *name = NULL;
223         float min = 0.0f, max = 1.0f;
224         PyObject *val = NULL;
225         static char *kwlist[] = {"name", "val", "min", "max", NULL};
226
227         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Off", kwlist, &name, &val, &min, &max)){
228                 return EXPP_ReturnIntError(PyExc_AttributeError, "expected a string and optionally:\n1) a float or a sequence (or vector) of 3 or 4 floats and\n2) two floats");
229         }
230
231         BLI_strncpy(self->name, name, NODE_MAXSTR);
232
233         self->min = min;
234         self->max = max;
235
236         if (val)
237                 return NodeSocket_setVal(self, val, NULL);
238         /* else */
239         self->type = SOCK_VALUE;
240         self->val[0] = 0.0f;
241
242         return 0;
243 }
244
245 static PyObject *NodeSocket_copy(BPy_NodeSocket *self)
246 {
247         BPy_NodeSocket *copied;
248
249         copied = (BPy_NodeSocket*)NodeSocket_new(&NodeSocket_Type, NULL, NULL);
250
251         if (!copied) return NULL; /* error already set in NodeSocket_new */
252
253         BLI_strncpy(copied->name, self->name, NODE_MAXSTR);
254         copied->min = self->min;
255         copied->max = self->max;
256         copied->type = self->type;
257         memcpy(copied->val, self->val, 4*sizeof(float));
258
259         return (PyObject *)copied;
260 }
261
262 static PyMethodDef BPy_NodeSocket_methods[] = {
263         {"__copy__", ( PyCFunction ) NodeSocket_copy, METH_NOARGS,
264          "() - Makes a copy of this node socket."},
265         {"copy", ( PyCFunction ) NodeSocket_copy, METH_NOARGS,
266          "() - Makes a copy of this node socket."},
267         {NULL, NULL, 0, NULL}
268 };
269
270 PyTypeObject NodeSocket_Type = {
271         PyObject_HEAD_INIT( NULL )  /* required py macro */
272         0,                          /* ob_size */
273         /*  For printing, in format "<module>.<name>" */
274         "Blender.Node.Socket",           /* char *tp_name; */
275         sizeof( BPy_NodeSocket ),       /* int tp_basicsize; */
276         0,                          /* tp_itemsize;  For allocation */
277
278         /* Methods to implement standard operations */
279
280         (destructor)NodeSocket_dealloc,/* destructor tp_dealloc; */
281         NULL,                       /* printfunc tp_print; */
282         NULL,                       /* getattrfunc tp_getattr; */
283         NULL,                       /* setattrfunc tp_setattr; */
284         NULL,                       /* cmpfunc tp_compare; */
285         NULL,                       /* reprfunc tp_repr; */
286
287         /* Method suites for standard classes */
288
289         NULL,                                           /* PyNumberMethods *tp_as_number; */
290         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
291         NULL,      /* PyMappingMethods *tp_as_mapping; */
292
293         /* More standard operations (here for binary compatibility) */
294
295         NULL,                       /* hashfunc tp_hash; */
296         NULL,                       /* ternaryfunc tp_call; */
297         NULL,                       /* reprfunc tp_str; */
298         NULL,                       /* getattrofunc tp_getattro; */
299         NULL,                       /* setattrofunc tp_setattro; */
300
301         /* Functions to access object as input/input buffer */
302         NULL,                       /* PyBufferProcs *tp_as_buffer; */
303
304   /*** Flags to define presence of optional/expanded features ***/
305         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* long tp_flags; */
306
307         NULL,                       /*  char *tp_doc;  Documentation string */
308   /*** Assigned meaning in release 2.0 ***/
309         /* call function for all accessible objects */
310         NULL,                       /* traverseproc tp_traverse; */
311
312         /* delete references to contained objects */
313         NULL,                       /* inquiry tp_clear; */
314
315   /***  Assigned meaning in release 2.1 ***/
316   /*** rich comparisons ***/
317         NULL,                       /* richcmpfunc tp_richcompare; */
318
319   /***  weak reference enabler ***/
320         0,                          /* long tp_weaklistoffset; */
321
322   /*** Added in release 2.2 ***/
323         /*   Iterators */
324         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
325         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
326
327   /*** Attribute descriptor and subclassing stuff ***/
328         BPy_NodeSocket_methods,     /* struct PyMethodDef *tp_methods; */
329         NULL,                       /* struct PyMemberDef *tp_members; */
330         NodeSocket_getseters,       /* struct PyGetSetDef *tp_getset; */
331         NULL,                       /* struct _typeobject *tp_base; */
332         NULL,                       /* PyObject *tp_dict; */
333         NULL,                       /* descrgetfunc tp_descr_get; */
334         NULL,                       /* descrsetfunc tp_descr_set; */
335         0,                          /* long tp_dictoffset; */
336         (initproc)NodeSocket_init,  /* initproc tp_init; */
337         NULL,                       /* allocfunc tp_alloc; */
338         NodeSocket_new,                         /* newfunc tp_new; */
339         /*  Low-level free-memory routine */
340         NULL,                       /* freefunc tp_free;  */
341         /* For PyObject_IS_GC */
342         NULL,                       /* inquiry tp_is_gc;  */
343         NULL,                       /* PyObject *tp_bases; */
344         /* method resolution order */
345         NULL,                       /* PyObject *tp_mro;  */
346         NULL,                       /* PyObject *tp_cache; */
347         NULL,                       /* PyObject *tp_subclasses; */
348         NULL,                       /* PyObject *tp_weaklist; */
349         NULL
350 };
351
352 /**
353  * Take the descriptions from tuple and create sockets for those in socks
354  * socks is a socketstack from a bNodeTypeInfo
355  */
356 static int pysockets_to_blendersockets(PyObject *tuple, bNodeSocketType **socks, int stage, int limit) {
357         int len = 0, a = 0, pos = 0, retval = 0;
358         short stype;
359         BPy_NodeSocket *pysock;
360         bNodeSocketType *nsocks = NULL;
361
362         if (BTST2(stage, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST))
363                 return 0; /* already has sockets */
364
365         len = PyTuple_Size(tuple);
366
367         nsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType in Node.c");
368
369         for (pos = 0, a = 0; pos< len; pos++, a++) {
370                 pysock = (BPy_NodeSocket *)PyTuple_GetItem(tuple, pos);/*borrowed*/
371
372                 if (!BPy_NodeSocket_Check(pysock)) {
373                         PyErr_SetString(PyExc_AttributeError, "expected a sequence of node sockets");
374                         retval = -1;
375                         break;
376                 }
377
378                 stype = pysock->type;
379
380                 nsocks[a].type = stype;
381                 nsocks[a].limit = limit;
382
383                 nsocks[a].name = BLI_strdupn(pysock->name, NODE_MAXSTR);
384
385                 nsocks[a].min = pysock->min;
386                 nsocks[a].max = pysock->max;
387
388                 if (stype > SOCK_VALUE) {
389                         float *vec = pysock->val;
390
391                         nsocks[a].val1 = vec[0];
392                         nsocks[a].val2 = vec[1];
393                         nsocks[a].val3 = vec[2];
394
395                         if (stype == SOCK_RGBA)
396                                 nsocks[a].val4 = vec[3];
397                 }
398                 else /* SOCK_VALUE */
399                         nsocks[a].val1 = pysock->val[0];
400         }
401
402         nsocks[a].type = -1;
403
404         *socks = nsocks;
405
406         return retval;
407 }
408
409 static void NodeSocketLists_dealloc(BPy_NodeSocketLists *self)
410 {
411         Py_DECREF(self->input);
412         Py_DECREF(self->output);
413         self->ob_type->tp_free((PyObject *)self);
414 }
415
416 static PyObject *Map_socketdef_getter(BPy_NodeSocketLists *self, void *closure)
417 {
418         PyObject *sockets = NULL;
419
420         switch ((int)closure) {
421                 case 'I': /* inputs */
422                         Py_INCREF(self->input);
423                         sockets = self->input;
424                         break;
425                 case 'O': /* outputs */
426                         Py_INCREF(self->output);
427                         sockets = self->output;
428                         break;
429                 default:
430                         fprintf(stderr, "DEBUG pynodes: wrong option in Map_socketdef_getter\n");
431                         Py_INCREF(Py_None);
432                         sockets = Py_None;
433                         break;
434         }
435
436         return sockets;
437 }
438
439 static int Map_socketdef(BPy_NodeSocketLists *self, PyObject *args, void *closure)
440 {
441         bNode *node = NULL;
442         PyObject *tuple = NULL;
443
444         node = self->node;
445
446         if(!node) {
447                 fprintf(stderr,"DEBUG pynodes: No bNode in BPy_Node (Map_socketdef)\n");
448                 return 0;
449         }
450
451         if(BTST2(node->custom1, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST))
452                 return 0;
453
454         switch((int)closure) {
455                 case 'I':
456                         if (args) {
457                                 if(PySequence_Check(args)) {
458                                         tuple = PySequence_Tuple(args);
459                                         pysockets_to_blendersockets(tuple,
460                                                         &(node->typeinfo->inputs), node->custom1, 1);
461                                         Py_DECREF(self->input);
462                                         self->input = tuple;
463                                 } else {
464                                         return(EXPP_ReturnIntError( PyExc_AttributeError, "INPUT must be a List of Lists or Tuples"));
465                                 }
466                         }
467                         break;
468                 case 'O':
469                         if (args) {
470                                 if(PyList_Check(args)) {
471                                         tuple = PySequence_Tuple(args);
472                                         pysockets_to_blendersockets(tuple,
473                                                         &(node->typeinfo->outputs), node->custom1, 0);
474                                         Py_DECREF(self->output);
475                                         self->output = tuple;
476                                 } else {
477                                         return(EXPP_ReturnIntError( PyExc_AttributeError, "OUTPUT must be a List of Lists or Tuples"));
478                                 }
479                         }
480                         break;
481                 default:
482                         fprintf(stderr,"DEBUG pynodes: got no list in Map_socketdef\n");
483                         break;
484         }
485         return 0;
486 }
487
488 static PyGetSetDef NodeSocketLists_getseters[] = {
489         {"input", (getter)Map_socketdef_getter, (setter)Map_socketdef,
490                 "Set this node's input sockets (list of lists or tuples)",
491                 (void *)'I'},
492         {"i" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef,
493                 "Set this node's input sockets (list of lists or tuples)",
494                 (void *)'I'},
495         {"output", (getter)Map_socketdef_getter, (setter)Map_socketdef,
496                 "Set this node's output sockets (list of lists or tuples)",
497                 (void *)'O'},
498         {"o" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef,
499                 "Set this node's output sockets (list of lists or tuples)",
500                 (void *)'O'},
501         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
502 };
503
504 PyTypeObject NodeSocketLists_Type = {
505         PyObject_HEAD_INIT( NULL )  /* required py macro */
506         0,                          /* ob_size */
507         /*  For printing, in format "<module>.<name>" */
508         "Blender.Node.SocketLists",           /* char *tp_name; */
509         sizeof( BPy_NodeSocketLists ),       /* int tp_basicsize; */
510         0,                          /* tp_itemsize;  For allocation */
511
512         /* Methods to implement standard operations */
513
514         (destructor)NodeSocketLists_dealloc,/* destructor tp_dealloc; */
515         NULL,                       /* printfunc tp_print; */
516         NULL,                       /* getattrfunc tp_getattr; */
517         NULL,                       /* setattrfunc tp_setattr; */
518         NULL,                       /* cmpfunc tp_compare; */
519         NULL,                       /* reprfunc tp_repr; */
520
521         /* Method suites for standard classes */
522
523         NULL,                                           /* PyNumberMethods *tp_as_number; */
524         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
525         NULL,      /* PyMappingMethods *tp_as_mapping; */
526
527         /* More standard operations (here for binary compatibility) */
528
529         NULL,                       /* hashfunc tp_hash; */
530         NULL,                       /* ternaryfunc tp_call; */
531         NULL,                       /* reprfunc tp_str; */
532         NULL,                       /* getattrofunc tp_getattro; */
533         NULL,                       /* setattrofunc tp_setattro; */
534
535         /* Functions to access object as input/input buffer */
536         NULL,                       /* PyBufferProcs *tp_as_buffer; */
537
538   /*** Flags to define presence of optional/expanded features ***/
539         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
540
541         NULL,                       /*  char *tp_doc;  Documentation string */
542   /*** Assigned meaning in release 2.0 ***/
543         /* call function for all accessible objects */
544         NULL,                       /* traverseproc tp_traverse; */
545
546         /* delete references to contained objects */
547         NULL,                       /* inquiry tp_clear; */
548
549   /***  Assigned meaning in release 2.1 ***/
550   /*** rich comparisons ***/
551         NULL,                       /* richcmpfunc tp_richcompare; */
552
553   /***  weak reference enabler ***/
554         0,                          /* long tp_weaklistoffset; */
555
556   /*** Added in release 2.2 ***/
557         /*   Iterators */
558         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
559         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
560
561   /*** Attribute descriptor and subclassing stuff ***/
562         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
563         NULL,                       /* struct PyMemberDef *tp_members; */
564         NodeSocketLists_getseters,      /* struct PyGetSetDef *tp_getset; */
565         NULL,                       /* struct _typeobject *tp_base; */
566         NULL,                       /* PyObject *tp_dict; */
567         NULL,                       /* descrgetfunc tp_descr_get; */
568         NULL,                       /* descrsetfunc tp_descr_set; */
569         0,                          /* long tp_dictoffset; */
570         NULL,                       /* initproc tp_init; */
571         NULL,                       /* allocfunc tp_alloc; */
572         NULL,                       /* newfunc tp_new; */
573         /*  Low-level free-memory routine */
574         NULL,                       /* freefunc tp_free;  */
575         /* For PyObject_IS_GC */
576         NULL,                       /* inquiry tp_is_gc;  */
577         NULL,                       /* PyObject *tp_bases; */
578         /* method resolution order */
579         NULL,                       /* PyObject *tp_mro;  */
580         NULL,                       /* PyObject *tp_cache; */
581         NULL,                       /* PyObject *tp_subclasses; */
582         NULL,                       /* PyObject *tp_weaklist; */
583         NULL
584 };
585
586 BPy_NodeSocketLists *Node_CreateSocketLists(bNode *node) {
587         BPy_NodeSocketLists *socklists = PyObject_NEW(BPy_NodeSocketLists, &NodeSocketLists_Type);
588         socklists->node = node;
589         socklists->input = PyList_New(0);
590         socklists->output = PyList_New(0);
591         return socklists;
592 }
593
594 /***************************************/
595
596 static int Sockinmap_len ( BPy_SockMap * self) {
597         bNode *node = self->node;
598         bNodeType *tinfo;
599         int a = 0;
600
601         if (!node) return 0;
602
603         tinfo = node->typeinfo;
604
605         if (BNTST(node->custom1, NODE_DYNAMIC_READY)) return 0;
606
607         if (tinfo && tinfo->inputs) {
608                 while(self->node->typeinfo->inputs[a].type!=-1)
609                         a++;
610         }
611         return a;
612 }
613
614 static int sockinmap_has_key( BPy_SockMap *self, char *strkey) {
615         bNode *node = self->node;
616         bNodeType *tinfo;
617         int a = 0;
618
619         if (!node || !strkey) return -1;
620
621         tinfo = node->typeinfo;
622
623         if(tinfo && tinfo->inputs){
624                 while(self->node->typeinfo->inputs[a].type!=-1) {
625                         if(BLI_strcaseeq(self->node->typeinfo->inputs[a].name, strkey)) {
626                                 return a;
627                         }
628                         a++;
629                 }
630         }
631         return -1;
632 }
633
634 PyObject *Sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) {
635         int idx;
636
637         if (!self->node)
638                 return EXPP_ReturnPyObjError(PyExc_RuntimeError, "no access to Blender node data!");
639
640         if (PyString_Check(pyidx)) {
641                 idx = sockinmap_has_key(self, PyString_AsString(pyidx));
642         }
643         else if(PyInt_Check(pyidx)) {
644                 int len = Sockinmap_len(self);
645                 idx = (int)PyInt_AsLong(pyidx);
646                 if (idx < 0 || idx >= len)
647                         return EXPP_ReturnPyObjError(PyExc_IndexError, "index out of range");
648         }
649         else if (PySlice_Check(pyidx)) {
650                 return EXPP_ReturnPyObjError(PyExc_ValueError, "slices not implemented");
651         } else {
652                 return EXPP_ReturnPyObjError(PyExc_IndexError, "index must be an int or a string");
653         }
654
655         if(idx<0) { /* we're not as nice as Python */
656                 return EXPP_ReturnPyObjError(PyExc_IndexError, "invalid socket index");
657         }
658         
659         switch(self->node->typeinfo->inputs[idx].type) {
660                 case SOCK_VALUE:
661                         return Py_BuildValue("f", self->stack[idx]->vec[0]);
662                         break;
663                 case SOCK_VECTOR:
664                         return Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
665                         break;
666                 case SOCK_RGBA:
667                         /* otherwise RGBA tuple */
668                         return Py_BuildValue("(ffff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2], self->stack[idx]->vec[3]);
669                         break;
670                 default:
671                         break;
672         }
673
674         Py_RETURN_NONE;
675 }
676
677 static PyObject *Sockinmap_getAttr(BPy_SockMap *self, char *attr)
678 {
679         PyObject *pyob = NULL;
680         int idx;
681
682         idx = sockinmap_has_key(self, attr);
683
684         if (idx < 0)
685                 return EXPP_ReturnPyObjError(PyExc_AttributeError, "unknown input socket name");
686
687         switch(self->node->typeinfo->inputs[idx].type) {
688                 case SOCK_VALUE:
689                         pyob = Py_BuildValue("f", self->stack[idx]->vec[0]);
690                         break;
691                 case SOCK_VECTOR:
692                         pyob = Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
693                         break;
694                 case SOCK_RGBA:
695                         pyob = Py_BuildValue("(ffff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2], self->stack[idx]->vec[3]);
696                         break;
697                 default:
698                         break;
699         }
700
701         return pyob;
702 }
703
704 /* read only */
705 static PyMappingMethods Sockinmap_as_mapping = {
706         ( inquiry ) Sockinmap_len,  /* mp_length */
707         ( binaryfunc ) Sockinmap_subscript, /* mp_subscript */
708         ( objobjargproc ) 0 /* mp_ass_subscript */
709 };
710
711 PyTypeObject SockInMap_Type = {
712         PyObject_HEAD_INIT( NULL )  /* required py macro */
713         0,                          /* ob_size */
714         /*  For printing, in format "<module>.<name>" */
715         "Blender.Node.InputSockets",           /* char *tp_name; */
716         sizeof( BPy_SockMap ),       /* int tp_basicsize; */
717         0,                          /* tp_itemsize;  For allocation */
718
719         /* Methods to implement standard operations */
720
721         NULL,/* destructor tp_dealloc; */
722         NULL,                       /* printfunc tp_print; */
723         (getattrfunc) Sockinmap_getAttr,/* getattrfunc tp_getattr; */
724         NULL,                       /* setattrfunc tp_setattr; */
725         NULL,                       /* cmpfunc tp_compare; */
726         NULL,                       /* reprfunc tp_repr; */
727
728         /* Method suites for standard classes */
729
730         NULL,                                           /* PyNumberMethods *tp_as_number; */
731         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
732         &Sockinmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
733
734         /* More standard operations (here for binary compatibility) */
735
736         NULL,                       /* hashfunc tp_hash; */
737         NULL,                       /* ternaryfunc tp_call; */
738         NULL,                       /* reprfunc tp_str; */
739         NULL,                       /* getattrofunc tp_getattro; */
740         NULL,                       /* setattrofunc tp_setattro; */
741
742         /* Functions to access object as input/output buffer */
743         NULL,                       /* PyBufferProcs *tp_as_buffer; */
744
745   /*** Flags to define presence of optional/expanded features ***/
746         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
747
748         NULL,                       /*  char *tp_doc;  Documentation string */
749   /*** Assigned meaning in release 2.0 ***/
750         /* call function for all accessible objects */
751         NULL,                       /* traverseproc tp_traverse; */
752
753         /* delete references to contained objects */
754         NULL,                       /* inquiry tp_clear; */
755
756   /***  Assigned meaning in release 2.1 ***/
757   /*** rich comparisons ***/
758         NULL,                       /* richcmpfunc tp_richcompare; */
759
760   /***  weak reference enabler ***/
761         0,                          /* long tp_weaklistoffset; */
762
763   /*** Added in release 2.2 ***/
764         /*   Iterators */
765         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
766         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
767
768   /*** Attribute descriptor and subclassing stuff ***/
769         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
770         NULL,                       /* struct PyMemberDef *tp_members; */
771         NULL,                       /* struct PyGetSetDef *tp_getset; */
772         NULL,                       /* struct _typeobject *tp_base; */
773         NULL,                       /* PyObject *tp_dict; */
774         NULL,                       /* descrgetfunc tp_descr_get; */
775         NULL,                       /* descrsetfunc tp_descr_set; */
776         0,                          /* long tp_dictoffset; */
777         NULL,                       /* initproc tp_init; */
778         NULL,                       /* allocfunc tp_alloc; */
779         NULL,                       /* newfunc tp_new; */
780         /*  Low-level free-memory routine */
781         NULL,                       /* freefunc tp_free;  */
782         /* For PyObject_IS_GC */
783         NULL,                       /* inquiry tp_is_gc;  */
784         NULL,                       /* PyObject *tp_bases; */
785         /* method resolution order */
786         NULL,                       /* PyObject *tp_mro;  */
787         NULL,                       /* PyObject *tp_cache; */
788         NULL,                       /* PyObject *tp_subclasses; */
789         NULL,                       /* PyObject *tp_weaklist; */
790         NULL
791 };
792
793 static int Sockoutmap_len ( BPy_SockMap * self) {
794         bNode *node = self->node;
795         bNodeType *tinfo;
796         int a = 0;
797
798         if (!node) return 0;
799
800         tinfo = node->typeinfo;
801
802         if (tinfo && tinfo->outputs) {
803                 while(self->node->typeinfo->outputs[a].type!=-1)
804                         a++;
805         }
806         return a;
807 }
808
809 static int sockoutmap_has_key(BPy_SockMap *self, char *strkey) {
810         bNode *node = self->node;
811         bNodeType *tinfo;
812         int a = 0;
813
814         if (!node) return -1;
815
816         tinfo = node->typeinfo;
817
818         if(tinfo && tinfo->outputs){
819                 while(self->node->typeinfo->outputs[a].type!=-1) {
820                         if(BLI_strcaseeq(self->node->typeinfo->outputs[a].name, strkey)) {
821                                 return a;
822                         }
823                         a++;
824                 }
825         }
826         return -1;
827 }
828
829 static int Sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObject *value) {
830         int i, idx, len, type, wanted_len = 0;
831         PyObject *val;
832         PyObject *items[4];
833
834         if (!self->node)
835                 return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
836
837         if (PyInt_Check(pyidx)) {
838                 idx = (int)PyInt_AsLong(pyidx);
839                 if (idx < 0 || idx >= Sockinmap_len(self))
840                         return EXPP_ReturnIntError(PyExc_IndexError, "index out of range");
841         }
842         else if (PyString_Check(pyidx)) {
843                 idx = sockoutmap_has_key(self, PyString_AsString(pyidx));
844         }
845         else if (PySlice_Check(pyidx)) {
846                 return EXPP_ReturnIntError(PyExc_ValueError, "slices not yet implemented");
847         } else {
848                 return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
849         }
850
851         if (idx < 0)
852                 return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
853
854         type = self->node->typeinfo->outputs[idx].type;
855
856         if (type == SOCK_VALUE) {
857                 val = PyNumber_Float(value);
858                 if (!val)
859                         return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
860                 self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
861                 Py_DECREF(val);
862         }
863         else {
864                 val = PySequence_Fast(value, "expected a numeric tuple or list");
865                 if (!val) return -1;
866
867                 len = PySequence_Fast_GET_SIZE(val);
868
869                 if (type == SOCK_VECTOR) {
870                         wanted_len = 3;
871                 } else { /* SOCK_RGBA */
872                         wanted_len = 4;
873                 }
874
875                 if (len != wanted_len) {
876                         Py_DECREF(val);
877                         PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
878                         fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
879                         return -1;
880                 }
881
882                 for (i = 0; i < len; i++) {
883                         items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
884                         if (!PyNumber_Check(items[i])) {
885                                 Py_DECREF(val);
886                                 return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
887                         }
888                 }
889
890                 self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
891                 self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
892                 self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
893
894                 if (type == SOCK_RGBA)
895                         self->stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
896
897                 Py_DECREF(val);
898         }
899
900         return 0;
901 }
902
903 static int sockoutmap_set_attr(bNodeStack **stack, short type, short idx, PyObject *value)
904 {
905         PyObject *val;
906         PyObject *items[4];
907         int i;
908         short len, wanted_len;
909
910         if (type == SOCK_VALUE) {
911                 val = PyNumber_Float(value);
912                 if (!val)
913                         return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
914                 stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
915                 Py_DECREF(val);
916         }
917         else {
918                 val = PySequence_Fast(value, "expected a numeric tuple or list");
919                 if (!val) return -1;
920
921                 len = PySequence_Fast_GET_SIZE(val);
922
923                 if (type == SOCK_VECTOR) {
924                         wanted_len = 3;
925                 } else { /* SOCK_RGBA */
926                         wanted_len = 4;
927                 }
928
929                 if (len != wanted_len) {
930                         Py_DECREF(val);
931                         PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
932                         fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
933                         return -1;
934                 }
935
936                 for (i = 0; i < len; i++) {
937                         items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
938                         if (!PyNumber_Check(items[i])) {
939                                 Py_DECREF(val);
940                                 return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
941                         }
942                 }
943
944                 stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
945                 stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
946                 stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
947
948                 if (type == SOCK_RGBA)
949                         stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
950
951                 Py_DECREF(val);
952         }
953
954         return 0;
955 }
956
957 static int Sockoutmap_setAttr(BPy_SockMap *self, char *name, PyObject *value) {
958         short idx, type;
959
960         if (!self->node)
961                 return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
962
963         idx = sockoutmap_has_key(self, name);
964
965         if (idx < 0)
966                 return EXPP_ReturnIntError(PyExc_AttributeError, "unknown output socket name");
967
968         type = self->node->typeinfo->outputs[idx].type;
969
970         return sockoutmap_set_attr(self->stack, type, idx, value);
971 }
972 /* write only */
973 static PyMappingMethods Sockoutmap_as_mapping = {
974         ( inquiry ) Sockoutmap_len,  /* mp_length */
975         ( binaryfunc ) 0, /* mp_subscript */
976         ( objobjargproc ) Sockoutmap_assign_subscript /* mp_ass_subscript */
977 };
978
979 PyTypeObject SockOutMap_Type = {
980         PyObject_HEAD_INIT( NULL )  /* required py macro */
981         0,                          /* ob_size */
982         /*  For printing, in format "<module>.<name>" */
983         "Blender.Node.OutputSockets",           /* char *tp_name; */
984         sizeof( BPy_SockMap ),       /* int tp_basicsize; */
985         0,                          /* tp_itemsize;  For allocation */
986
987         /* Methods to implement standard operations */
988
989         NULL,/* destructor tp_dealloc; */
990         NULL,                       /* printfunc tp_print; */
991         NULL,                       /* getattrfunc tp_getattr; */
992         (setattrfunc) Sockoutmap_setAttr,/* setattrfunc tp_setattr; */
993         NULL,                       /* cmpfunc tp_compare; */
994         NULL,                       /* reprfunc tp_repr; */
995
996         /* Method suites for standard classes */
997
998         NULL,                                           /* PyNumberMethods *tp_as_number; */
999         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
1000         &Sockoutmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
1001
1002         /* More standard operations (here for binary compatibility) */
1003
1004         NULL,                       /* hashfunc tp_hash; */
1005         NULL,                       /* ternaryfunc tp_call; */
1006         NULL,                       /* reprfunc tp_str; */
1007         NULL,                       /* getattrofunc tp_getattro; */
1008         NULL,                       /* setattrofunc tp_setattro; */
1009
1010         /* Functions to access object as input/output buffer */
1011         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1012
1013   /*** Flags to define presence of optional/expanded features ***/
1014         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1015
1016         NULL,                       /*  char *tp_doc;  Documentation string */
1017   /*** Assigned meaning in release 2.0 ***/
1018         /* call function for all accessible objects */
1019         NULL,                       /* traverseproc tp_traverse; */
1020
1021         /* delete references to contained objects */
1022         NULL,                       /* inquiry tp_clear; */
1023
1024   /***  Assigned meaning in release 2.1 ***/
1025   /*** rich comparisons ***/
1026         NULL,                       /* richcmpfunc tp_richcompare; */
1027
1028   /***  weak reference enabler ***/
1029         0,                          /* long tp_weaklistoffset; */
1030
1031   /*** Added in release 2.2 ***/
1032         /*   Iterators */
1033         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
1034         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
1035
1036   /*** Attribute descriptor and subclassing stuff ***/
1037         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
1038         NULL,                       /* struct PyMemberDef *tp_members; */
1039         NULL,                       /* struct PyGetSetDef *tp_getset; */
1040         NULL,                       /* struct _typeobject *tp_base; */
1041         NULL,                       /* PyObject *tp_dict; */
1042         NULL,                       /* descrgetfunc tp_descr_get; */
1043         NULL,                       /* descrsetfunc tp_descr_set; */
1044         0,                          /* long tp_dictoffset; */
1045         NULL,                       /* initproc tp_init; */
1046         NULL,                       /* allocfunc tp_alloc; */
1047         NULL,                       /* newfunc tp_new; */
1048         /*  Low-level free-memory routine */
1049         NULL,                       /* freefunc tp_free;  */
1050         /* For PyObject_IS_GC */
1051         NULL,                       /* inquiry tp_is_gc;  */
1052         NULL,                       /* PyObject *tp_bases; */
1053         /* method resolution order */
1054         NULL,                       /* PyObject *tp_mro;  */
1055         NULL,                       /* PyObject *tp_cache; */
1056         NULL,                       /* PyObject *tp_subclasses; */
1057         NULL,                       /* PyObject *tp_weaklist; */
1058         NULL
1059 };
1060
1061
1062 static BPy_SockMap *Node_CreateInputMap(bNode *node, bNodeStack **stack) {
1063         BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockInMap_Type);
1064         map->node = node;
1065         map->stack = stack;
1066         return map;
1067 }
1068
1069 static PyObject *Node_GetInputMap(BPy_Node *self) {
1070         BPy_SockMap *inmap = Node_CreateInputMap(self->node, self->in);
1071         return (PyObject *)(inmap);
1072 }
1073
1074 #define SURFACEVIEWVECTOR       0
1075 #define VIEWNORMAL                      1
1076 #define SURFACENORMAL           2
1077 #define GLOBALTEXTURE           3
1078 #define TEXTURE                         4
1079 #define PIXEL                           5
1080 #define COLOR                           6
1081 #define SPECULAR_COLOR          7
1082 #define MIRROR_COLOR            8
1083 #define AMBIENT_COLOR           9
1084 #define AMBIENT                         10
1085 #define EMIT                            11
1086 #define DISPLACE                        12
1087 #define STRAND                          13
1088 #define STRESS                          14
1089 #define TANGENT                         15
1090 #define SURFACE_D                       30
1091 #define TEXTURE_D                       31
1092 #define GLOBALTEXTURE_D         32
1093 #define REFLECTION_D            33
1094 #define NORMAL_D                        34
1095 #define STICKY_D                        35
1096 #define REFRACT_D                       36
1097 #define STRAND_D                        37
1098
1099 static PyObject *ShadeInput_getAttribute(BPy_ShadeInput *self, void *type) {
1100         PyObject *obj = NULL;
1101         if(self->shi) {
1102                 switch((int)type) {
1103                         case SURFACEVIEWVECTOR:
1104                                 obj = Py_BuildValue("(fff)", self->shi->view[0], self->shi->view[1], self->shi->view[2]);
1105                                 break;
1106                         case VIEWNORMAL:
1107                                 obj = Py_BuildValue("(fff)", self->shi->vn[0], self->shi->vn[1], self->shi->vn[2]);
1108                                 break;
1109                         case SURFACENORMAL:
1110                                 obj = Py_BuildValue("(fff)", self->shi->facenor[0], self->shi->facenor[1], self->shi->facenor[2]);
1111                                 break;
1112                         case GLOBALTEXTURE:
1113                                 obj = Py_BuildValue("(fff)", self->shi->gl[0], self->shi->gl[1], self->shi->gl[2]);
1114                                 break;
1115                         case TEXTURE:
1116                                 obj = Py_BuildValue("(fff)", self->shi->lo[0], self->shi->lo[1], self->shi->lo[2]);
1117                                 break;
1118                         case PIXEL:
1119                                 obj = Py_BuildValue("(ii)", self->shi->xs, self->shi->ys);
1120                                 break;
1121                         case COLOR:
1122                                 obj = Py_BuildValue("(fff)", self->shi->r, self->shi->g, self->shi->b);
1123                                 break;
1124                         case SPECULAR_COLOR:
1125                                 obj = Py_BuildValue("(fff)", self->shi->specr, self->shi->specg, self->shi->specb);
1126                                 break;
1127                         case MIRROR_COLOR:
1128                                 obj = Py_BuildValue("(fff)", self->shi->mirr, self->shi->mirg, self->shi->mirb);
1129                                 break;
1130                         case AMBIENT_COLOR:
1131                                 obj = Py_BuildValue("(fff)", self->shi->ambr, self->shi->ambg, self->shi->ambb);
1132                                 break;
1133                         case AMBIENT:
1134                                 obj = PyFloat_FromDouble((double)(self->shi->amb));
1135                                 break;
1136                         case EMIT:
1137                                 obj = PyFloat_FromDouble((double)(self->shi->emit));
1138                                 break;
1139                         case DISPLACE:
1140                                 obj = Py_BuildValue("(fff)", self->shi->displace[0], self->shi->displace[1], self->shi->displace[2]);
1141                                 break;
1142                         case STRAND:
1143                                 obj = PyFloat_FromDouble((double)(self->shi->strandco));
1144                                 break;
1145                         case STRESS:
1146                                 obj = PyFloat_FromDouble((double)(self->shi->stress));
1147                                 break;
1148                         case TANGENT:
1149                                 obj = Py_BuildValue("(fff)", self->shi->tang[0], self->shi->tang[1], self->shi->tang[2]);
1150                                 break;
1151                         case SURFACE_D:
1152                                 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]);
1153                                 break;
1154                         case TEXTURE_D:
1155                                 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]);
1156                                 break;
1157                         case GLOBALTEXTURE_D:
1158                                 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]);
1159                                 break;
1160                         case REFLECTION_D:
1161                                 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]);
1162                                 break;
1163                         case NORMAL_D:
1164                                 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]);
1165                                 break;
1166                         case STICKY_D:
1167                                 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]);
1168                                 break;
1169                         case REFRACT_D:
1170                                 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]);
1171                                 break;
1172                         case STRAND_D:
1173                                 obj = Py_BuildValue("(ff)", self->shi->dxstrand, self->shi->dystrand);
1174                                 break;
1175                         default:
1176                                 break;
1177                 }
1178         }
1179
1180         if(!obj) {
1181                 Py_RETURN_NONE;
1182         }
1183         return obj;
1184 }
1185
1186 static BPy_SockMap *Node_CreateOutputMap(bNode *node, bNodeStack **stack) {
1187         BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockOutMap_Type);
1188         map->node = node;
1189         map->stack = stack;
1190         return map;
1191 }
1192
1193 static PyObject *Node_GetOutputMap(BPy_Node *self) {
1194         BPy_SockMap *outmap = Node_CreateOutputMap(self->node, self->out);
1195         return (PyObject *)outmap;
1196 }
1197
1198 static PyObject *Node_GetShi(BPy_Node *self) {
1199         BPy_ShadeInput *shi = ShadeInput_CreatePyObject(self->shi);
1200         return (PyObject *)shi;
1201 }
1202
1203 static PyObject *node_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1204 {
1205         PyObject *self;
1206         self = type->tp_alloc(type, 1);
1207         return self;
1208 }
1209
1210 static int node_init(BPy_Node *self, PyObject *args, PyObject *kwds)
1211 {
1212         return 0;
1213 }
1214
1215 static PyGetSetDef BPy_Node_getseters[] = {
1216         {"input",
1217                 (getter)Node_GetInputMap, (setter)NULL,
1218                 "Get the input sockets mapping (dictionary)",
1219                 NULL},
1220         {"i", /* alias */
1221                 (getter)Node_GetInputMap, (setter)NULL,
1222                 "Get the input sockets mapping (dictionary)",
1223                 NULL},
1224         {"output",
1225                 (getter)Node_GetOutputMap, (setter)NULL,
1226                 "Get the output sockets mapping (dictionary)",
1227                 NULL},
1228         {"o", /* alias */
1229                 (getter)Node_GetOutputMap, (setter)NULL,
1230                 "Get the output sockets mapping (dictionary)",
1231                 NULL},
1232         {"shi",
1233                 (getter)Node_GetShi, (setter)NULL,
1234                 "Get the Shade Input data (ShadeInput)",
1235                 NULL},
1236         {"s", /* alias */
1237                 (getter)Node_GetShi, (setter)NULL,
1238                 "Get the Shade Input data (ShadeInput)",
1239                 NULL},
1240         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1241 };
1242
1243 static PyGetSetDef BPy_ShadeInput_getseters[] = {
1244         {"texture",
1245           (getter)ShadeInput_getAttribute, (setter)NULL,
1246           "Get the current texture coordinate (tuple)",
1247           (void*)TEXTURE},
1248         {"textureGlobal",
1249           (getter)ShadeInput_getAttribute, (setter)NULL,
1250           "Get the current global texture coordinate (tuple)",
1251           (void*)GLOBALTEXTURE},
1252         {"surfaceNormal",
1253           (getter)ShadeInput_getAttribute, (setter)NULL,
1254           "Get the current surface normal (tuple)",
1255           (void*)SURFACENORMAL},
1256         {"viewNormal",
1257           (getter)ShadeInput_getAttribute, (setter)NULL,
1258           "Get the current view normal (tuple)",
1259           (void*)VIEWNORMAL},
1260         {"surfaceViewVector",
1261           (getter)ShadeInput_getAttribute, (setter)NULL,
1262           "Get the vector pointing to the viewpoint from the point being shaded (tuple)",
1263           (void*)SURFACEVIEWVECTOR},
1264         {"pixel",
1265           (getter)ShadeInput_getAttribute, (setter)NULL,
1266           "Get the x,y-coordinate for the pixel rendered (tuple)",
1267           (void*)PIXEL},
1268         {"color",
1269           (getter)ShadeInput_getAttribute, (setter)NULL,
1270           "Get the color for the point being shaded (tuple)",
1271           (void*)COLOR},
1272         {"specularColor",
1273           (getter)ShadeInput_getAttribute, (setter)NULL,
1274           "Get the specular color for the point being shaded (tuple)",
1275           (void*)SPECULAR_COLOR},
1276         {"mirrorColor",
1277           (getter)ShadeInput_getAttribute, (setter)NULL,
1278           "Get the mirror color for the point being shaded (tuple)",
1279           (void*)MIRROR_COLOR},
1280         {"ambientColor",
1281           (getter)ShadeInput_getAttribute, (setter)NULL,
1282           "Get the ambient color for the point being shaded (tuple)",
1283           (void*)AMBIENT_COLOR},
1284         {"ambient",
1285           (getter)ShadeInput_getAttribute, (setter)NULL,
1286           "Get the ambient factor for the point being shaded (float)",
1287           (void*)AMBIENT},
1288         {"emit",
1289           (getter)ShadeInput_getAttribute, (setter)NULL,
1290           "Get the emit factor for the point being shaded (float)",
1291           (void*)EMIT},
1292         {"displace",
1293           (getter)ShadeInput_getAttribute, (setter)NULL,
1294           "Get the displace vector for the point being shaded (tuple)",
1295           (void*)DISPLACE},
1296         {"strand",
1297           (getter)ShadeInput_getAttribute, (setter)NULL,
1298           "Get the strand factor(float)",
1299           (void*)STRAND},
1300         {"stress",
1301           (getter)ShadeInput_getAttribute, (setter)NULL,
1302           "Get the stress factor(float)",
1303           (void*)STRESS},
1304         {"tangent",
1305           (getter)ShadeInput_getAttribute, (setter)NULL,
1306           "Get the tangent vector (tuple)",
1307           (void*)TANGENT},
1308         {"surfaceD",
1309           (getter)ShadeInput_getAttribute, (setter)NULL,
1310           "Get the surface d (tuple of tuples)",
1311           (void*)SURFACE_D},
1312         {"textureD",
1313           (getter)ShadeInput_getAttribute, (setter)NULL,
1314           "Get the texture d (tuple of tuples)",
1315           (void*)TEXTURE_D},
1316         {"textureGlobalD",
1317           (getter)ShadeInput_getAttribute, (setter)NULL,
1318           "Get the global texture d (tuple of tuples)",
1319           (void*)GLOBALTEXTURE_D},
1320         {"reflectionD",
1321           (getter)ShadeInput_getAttribute, (setter)NULL,
1322           "Get the reflection d (tuple of tuples)",
1323           (void*)REFLECTION_D},
1324         {"normalD",
1325           (getter)ShadeInput_getAttribute, (setter)NULL,
1326           "Get the normal d (tuple of tuples)",
1327           (void*)NORMAL_D},
1328         {"stickyD",
1329           (getter)ShadeInput_getAttribute, (setter)NULL,
1330           "Get the sticky d (tuple of tuples)",
1331           (void*)STICKY_D},
1332         {"refractD",
1333           (getter)ShadeInput_getAttribute, (setter)NULL,
1334           "Get the refract d (tuple of tuples)",
1335           (void*)REFRACT_D},
1336         {"strandD",
1337           (getter)ShadeInput_getAttribute, (setter)NULL,
1338           "Get the strand d (tuple)",
1339           (void*)STRAND_D},
1340         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1341 };
1342
1343 PyTypeObject Node_Type = {
1344         PyObject_HEAD_INIT( NULL )  /* required py macro */
1345         0,                          /* ob_size */
1346         /*  For printing, in format "<module>.<name>" */
1347         "Blender.Node.node",             /* char *tp_name; */
1348         sizeof( BPy_Node ),         /* int tp_basicsize; */
1349         0,                          /* tp_itemsize;  For allocation */
1350
1351         /* Methods to implement standard operations */
1352
1353         NULL,/* destructor tp_dealloc; */
1354         NULL,                       /* printfunc tp_print; */
1355         NULL /*( getattrfunc ) PyObject_GenericGetAttr*/,                       /* getattrfunc tp_getattr; */
1356         NULL /*( setattrfunc ) PyObject_GenericSetAttr*/,                       /* setattrfunc tp_setattr; */
1357         ( cmpfunc ) Node_compare,   /* cmpfunc tp_compare; */
1358         ( reprfunc ) Node_repr,     /* reprfunc tp_repr; */
1359
1360         /* Method suites for standard classes */
1361
1362         NULL,                       /* PyNumberMethods *tp_as_number; */
1363         NULL,                       /* PySequenceMethods *tp_as_sequence; */
1364         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1365
1366         /* More standard operations (here for binary compatibility) */
1367
1368         NULL,                       /* hashfunc tp_hash; */
1369         NULL,                       /* ternaryfunc tp_call; */
1370         NULL,                       /* reprfunc tp_str; */
1371         NULL,                       /* getattrofunc tp_getattro; */
1372         NULL,                       /* setattrofunc tp_setattro; */
1373
1374         /* Functions to access object as input/output buffer */
1375         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1376
1377   /*** Flags to define presence of optional/expanded features ***/
1378         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* long tp_flags; */
1379
1380         NULL,                       /*  char *tp_doc;  Documentation string */
1381   /*** Assigned meaning in release 2.0 ***/
1382         /* call function for all accessible objects */
1383         NULL,                       /* traverseproc tp_traverse; */
1384
1385         /* delete references to contained objects */
1386         NULL,                       /* inquiry tp_clear; */
1387
1388   /***  Assigned meaning in release 2.1 ***/
1389   /*** rich comparisons ***/
1390         NULL,                       /* richcmpfunc tp_richcompare; */
1391
1392   /***  weak reference enabler ***/
1393         0,                          /* long tp_weaklistoffset; */
1394
1395   /*** Added in release 2.2 ***/
1396         /*   Iterators */
1397         NULL,                       /* getiterfunc tp_iter; */
1398         NULL,                       /* iternextfunc tp_iternext; */
1399
1400   /*** Attribute descriptor and subclassing stuff ***/
1401         NULL, /*BPy_Node_methods,*/          /* struct PyMethodDef *tp_methods; */
1402         NULL,                       /* struct PyMemberDef *tp_members; */
1403         BPy_Node_getseters,        /* struct PyGetSetDef *tp_getset; */
1404         NULL,                       /* struct _typeobject *tp_base; */
1405         NULL,                       /* PyObject *tp_dict; */
1406         NULL,                       /* descrgetfunc tp_descr_get; */
1407         NULL,                       /* descrsetfunc tp_descr_set; */
1408         0,                          /* long tp_dictoffset; */
1409         (initproc)node_init,                       /* initproc tp_init; */
1410         /*PyType_GenericAlloc*/NULL,                       /* allocfunc tp_alloc; */
1411         node_new,                       /* newfunc tp_new; */
1412         /*  Low-level free-memory routine */
1413         NULL,                       /* freefunc tp_free;  */
1414         /* For PyObject_IS_GC */
1415         NULL,                       /* inquiry tp_is_gc;  */
1416         NULL,                       /* PyObject *tp_bases; */
1417         /* method resolution order */
1418         NULL,                       /* PyObject *tp_mro;  */
1419         NULL,                       /* PyObject *tp_cache; */
1420         NULL,                       /* PyObject *tp_subclasses; */
1421         NULL,                       /* PyObject *tp_weaklist; */
1422         NULL
1423 };
1424
1425 PyTypeObject ShadeInput_Type = {
1426         PyObject_HEAD_INIT( NULL )  /* required py macro */
1427         0,                          /* ob_size */
1428         /*  For printing, in format "<module>.<name>" */
1429         "Blender.Node.ShadeInput",             /* char *tp_name; */
1430         sizeof( BPy_ShadeInput ),         /* int tp_basicsize; */
1431         0,                          /* tp_itemsize;  For allocation */
1432
1433         /* Methods to implement standard operations */
1434
1435         NULL,/* destructor tp_dealloc; */
1436         NULL,                       /* printfunc tp_print; */
1437         NULL,                       /* getattrfunc tp_getattr; */
1438         NULL,                       /* setattrfunc tp_setattr; */
1439         ( cmpfunc ) ShadeInput_compare,   /* cmpfunc tp_compare; */
1440         ( reprfunc ) ShadeInput_repr,     /* reprfunc tp_repr; */
1441
1442         /* Method suites for standard classes */
1443
1444         NULL,                       /* PyNumberMethods *tp_as_number; */
1445         NULL,                       /* PySequenceMethods *tp_as_sequence; */
1446         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1447
1448         /* More standard operations (here for binary compatibility) */
1449
1450         NULL,                       /* hashfunc tp_hash; */
1451         NULL,                       /* ternaryfunc tp_call; */
1452         NULL,                       /* reprfunc tp_str; */
1453         NULL,                       /* getattrofunc tp_getattro; */
1454         NULL,                       /* setattrofunc tp_setattro; */
1455
1456         /* Functions to access object as input/output buffer */
1457         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1458
1459   /*** Flags to define presence of optional/expanded features ***/
1460         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1461
1462         NULL,                       /*  char *tp_doc;  Documentation string */
1463   /*** Assigned meaning in release 2.0 ***/
1464         /* call function for all accessible objects */
1465         NULL,                       /* traverseproc tp_traverse; */
1466
1467         /* delete references to contained objects */
1468         NULL,                       /* inquiry tp_clear; */
1469
1470   /***  Assigned meaning in release 2.1 ***/
1471   /*** rich comparisons ***/
1472         NULL,                       /* richcmpfunc tp_richcompare; */
1473
1474   /***  weak reference enabler ***/
1475         0,                          /* long tp_weaklistoffset; */
1476
1477   /*** Added in release 2.2 ***/
1478         /*   Iterators */
1479         NULL,                       /* getiterfunc tp_iter; */
1480         NULL,                       /* iternextfunc tp_iternext; */
1481
1482   /*** Attribute descriptor and subclassing stuff ***/
1483         NULL, /*BPy_Node_methods,*/          /* struct PyMethodDef *tp_methods; */
1484         NULL,                       /* struct PyMemberDef *tp_members; */
1485         BPy_ShadeInput_getseters,        /* struct PyGetSetDef *tp_getset; */
1486         NULL,                       /* struct _typeobject *tp_base; */
1487         NULL,                       /* PyObject *tp_dict; */
1488         NULL,                       /* descrgetfunc tp_descr_get; */
1489         NULL,                       /* descrsetfunc tp_descr_set; */
1490         0,                          /* long tp_dictoffset; */
1491         NULL,                       /* initproc tp_init; */
1492         NULL,                       /* allocfunc tp_alloc; */
1493         NULL,                       /* newfunc tp_new; */
1494         /*  Low-level free-memory routine */
1495         NULL,                       /* freefunc tp_free;  */
1496         /* For PyObject_IS_GC */
1497         NULL,                       /* inquiry tp_is_gc;  */
1498         NULL,                       /* PyObject *tp_bases; */
1499         /* method resolution order */
1500         NULL,                       /* PyObject *tp_mro;  */
1501         NULL,                       /* PyObject *tp_cache; */
1502         NULL,                       /* PyObject *tp_subclasses; */
1503         NULL,                       /* PyObject *tp_weaklist; */
1504         NULL
1505 };
1506
1507 /* Initialise Node module */
1508 PyObject *Node_Init(void)
1509 {
1510         PyObject *submodule;
1511
1512         if( PyType_Ready( &Node_Type ) < 0 )
1513                 return NULL;
1514         if( PyType_Ready( &ShadeInput_Type ) < 0 )
1515                 return NULL;
1516         if( PyType_Ready( &NodeSocket_Type ) < 0 )
1517                 return NULL;
1518         if( PyType_Ready( &NodeSocketLists_Type ) < 0 )
1519                 return NULL;
1520         if( PyType_Ready( &SockInMap_Type ) < 0 )
1521                 return NULL;
1522         if( PyType_Ready( &SockOutMap_Type ) < 0 )
1523                 return NULL;
1524         submodule = Py_InitModule3( "Blender.Node", NULL, "");
1525
1526         PyModule_AddIntConstant(submodule, "VALUE", SOCK_VALUE);
1527         PyModule_AddIntConstant(submodule, "RGBA", SOCK_RGBA);
1528         PyModule_AddIntConstant(submodule, "VECTOR", SOCK_VECTOR);
1529
1530         Py_INCREF(&NodeSocket_Type);
1531         PyModule_AddObject(submodule, "Socket", (PyObject *)&NodeSocket_Type);
1532
1533         Py_INCREF(&Node_Type);
1534         PyModule_AddObject(submodule, "Scripted", (PyObject *)&Node_Type);
1535
1536         return submodule;
1537 }
1538
1539 static int Node_compare(BPy_Node *a, BPy_Node *b)
1540 {
1541         bNode *pa = a->node, *pb = b->node;
1542         return (pa == pb) ? 0 : -1;
1543 }
1544
1545 static PyObject *Node_repr(BPy_Node *self)
1546 {
1547         return PyString_FromFormat( "[Node \"%s\"]",
1548                 self->node ? self->node->id->name+2 : "empty node");
1549 }
1550
1551 BPy_Node *Node_CreatePyObject(bNode *node)
1552 {
1553         BPy_Node *pynode;
1554
1555         pynode = (BPy_Node *)PyObject_NEW(BPy_Node, &Node_Type);
1556         if(!pynode) {
1557                 fprintf(stderr,"Couldn't create BPy_Node object\n");
1558                 return (BPy_Node *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_Node object"));
1559         }
1560
1561         pynode->node = node;
1562
1563         return pynode;
1564 }
1565
1566 int pytype_is_pynode(PyObject *pyob)
1567 {
1568         return PyObject_TypeCheck(pyob, &Node_Type);
1569 }
1570
1571 void InitNode(BPy_Node *self, bNode *node) {
1572         self->node = node;
1573 }
1574
1575 bNode *Node_FromPyObject(PyObject *pyobj)
1576 {
1577         return ((BPy_Node *)pyobj)->node;
1578 }
1579
1580 void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type)
1581 {
1582         if(type == NODE_INPUTSTACK) {
1583                 self->in = stack;
1584         } else if(type == NODE_OUTPUTSTACK) {
1585                 self->out = stack;
1586         }
1587 }
1588
1589 void Node_SetShi(BPy_Node *self, ShadeInput *shi)
1590 {
1591         self->shi = shi;
1592 }
1593
1594 /*********************/
1595
1596 static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b)
1597 {
1598         ShadeInput *pa = a->shi, *pb = b->shi;
1599         return (pa == pb) ? 0 : -1;
1600 }
1601
1602 static PyObject *ShadeInput_repr(BPy_ShadeInput *self)
1603 {
1604         return PyString_FromFormat( "[ShadeInput at \"%p\"]", self);
1605 }
1606
1607 BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi)
1608 {
1609         BPy_ShadeInput *pyshi;
1610
1611         pyshi = (BPy_ShadeInput *)PyObject_NEW(BPy_ShadeInput, &ShadeInput_Type);
1612         if(!pyshi) {
1613                 fprintf(stderr,"Couldn't create BPy_ShadeInput object\n");
1614                 return (BPy_ShadeInput *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_ShadeInput object"));
1615         }
1616
1617         pyshi->shi = shi;
1618
1619         return pyshi;
1620 }
1621