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