== 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 >= Sockinmap_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 (type == SOCK_VALUE) {
923                 val = PyNumber_Float(value);
924                 if (!val)
925                         return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
926                 stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
927                 Py_DECREF(val);
928         }
929         else {
930                 val = PySequence_Fast(value, "expected a numeric tuple or list");
931                 if (!val) return -1;
932
933                 len = PySequence_Fast_GET_SIZE(val);
934
935                 if (type == SOCK_VECTOR) {
936                         wanted_len = 3;
937                 } else { /* SOCK_RGBA */
938                         wanted_len = 4;
939                 }
940
941                 if (len != wanted_len) {
942                         Py_DECREF(val);
943                         PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
944                         fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
945                         return -1;
946                 }
947
948                 for (i = 0; i < len; i++) {
949                         items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
950                         if (!PyNumber_Check(items[i])) {
951                                 Py_DECREF(val);
952                                 return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
953                         }
954                 }
955
956                 stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
957                 stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
958                 stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
959
960                 if (type == SOCK_RGBA)
961                         stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
962
963                 Py_DECREF(val);
964         }
965
966         return 0;
967 }
968
969 static int Sockoutmap_setAttr(BPy_SockMap *self, char *name, PyObject *value) {
970         short idx, type;
971
972         if (!self->node)
973                 return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
974
975         idx = sockoutmap_has_key(self, name);
976
977         if (idx < 0)
978                 return EXPP_ReturnIntError(PyExc_AttributeError, "unknown output socket name");
979
980         type = self->node->typeinfo->outputs[idx].type;
981
982         return sockoutmap_set_attr(self->stack, type, idx, value);
983 }
984 /* write only */
985 static PyMappingMethods Sockoutmap_as_mapping = {
986         ( inquiry ) Sockoutmap_len,  /* mp_length */
987         ( binaryfunc ) 0, /* mp_subscript */
988         ( objobjargproc ) Sockoutmap_assign_subscript /* mp_ass_subscript */
989 };
990
991 PyTypeObject SockOutMap_Type = {
992         PyObject_HEAD_INIT( NULL )  /* required py macro */
993         0,                          /* ob_size */
994         /*  For printing, in format "<module>.<name>" */
995         "Blender.Node.OutputSockets",           /* char *tp_name; */
996         sizeof( BPy_SockMap ),       /* int tp_basicsize; */
997         0,                          /* tp_itemsize;  For allocation */
998
999         /* Methods to implement standard operations */
1000
1001         NULL,/* destructor tp_dealloc; */
1002         NULL,                       /* printfunc tp_print; */
1003         NULL,                       /* getattrfunc tp_getattr; */
1004         (setattrfunc) Sockoutmap_setAttr,/* setattrfunc tp_setattr; */
1005         NULL,                       /* cmpfunc tp_compare; */
1006         NULL,                       /* reprfunc tp_repr; */
1007
1008         /* Method suites for standard classes */
1009
1010         NULL,                                           /* PyNumberMethods *tp_as_number; */
1011         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
1012         &Sockoutmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
1013
1014         /* More standard operations (here for binary compatibility) */
1015
1016         NULL,                       /* hashfunc tp_hash; */
1017         NULL,                       /* ternaryfunc tp_call; */
1018         NULL,                       /* reprfunc tp_str; */
1019         NULL,                       /* getattrofunc tp_getattro; */
1020         NULL,                       /* setattrofunc tp_setattro; */
1021
1022         /* Functions to access object as input/output buffer */
1023         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1024
1025   /*** Flags to define presence of optional/expanded features ***/
1026         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1027
1028         NULL,                       /*  char *tp_doc;  Documentation string */
1029   /*** Assigned meaning in release 2.0 ***/
1030         /* call function for all accessible objects */
1031         NULL,                       /* traverseproc tp_traverse; */
1032
1033         /* delete references to contained objects */
1034         NULL,                       /* inquiry tp_clear; */
1035
1036   /***  Assigned meaning in release 2.1 ***/
1037   /*** rich comparisons ***/
1038         NULL,                       /* richcmpfunc tp_richcompare; */
1039
1040   /***  weak reference enabler ***/
1041         0,                          /* long tp_weaklistoffset; */
1042
1043   /*** Added in release 2.2 ***/
1044         /*   Iterators */
1045         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
1046         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
1047
1048   /*** Attribute descriptor and subclassing stuff ***/
1049         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
1050         NULL,                       /* struct PyMemberDef *tp_members; */
1051         NULL,                       /* struct PyGetSetDef *tp_getset; */
1052         NULL,                       /* struct _typeobject *tp_base; */
1053         NULL,                       /* PyObject *tp_dict; */
1054         NULL,                       /* descrgetfunc tp_descr_get; */
1055         NULL,                       /* descrsetfunc tp_descr_set; */
1056         0,                          /* long tp_dictoffset; */
1057         NULL,                       /* initproc tp_init; */
1058         NULL,                       /* allocfunc tp_alloc; */
1059         NULL,                       /* newfunc tp_new; */
1060         /*  Low-level free-memory routine */
1061         NULL,                       /* freefunc tp_free;  */
1062         /* For PyObject_IS_GC */
1063         NULL,                       /* inquiry tp_is_gc;  */
1064         NULL,                       /* PyObject *tp_bases; */
1065         /* method resolution order */
1066         NULL,                       /* PyObject *tp_mro;  */
1067         NULL,                       /* PyObject *tp_cache; */
1068         NULL,                       /* PyObject *tp_subclasses; */
1069         NULL,                       /* PyObject *tp_weaklist; */
1070         NULL
1071 };
1072
1073
1074 static BPy_SockMap *Node_CreateInputMap(bNode *node, bNodeStack **stack) {
1075         BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockInMap_Type);
1076         map->node = node;
1077         map->stack = stack;
1078         return map;
1079 }
1080
1081 static PyObject *Node_GetInputMap(BPy_Node *self) {
1082         BPy_SockMap *inmap = Node_CreateInputMap(self->node, self->in);
1083         return (PyObject *)(inmap);
1084 }
1085
1086 #define SURFACEVIEWVECTOR       0
1087 #define VIEWNORMAL                      1
1088 #define SURFACENORMAL           2
1089 #define GLOBALTEXTURE           3
1090 #define TEXTURE                         4
1091 #define PIXEL                           5
1092 #define COLOR                           6
1093 #define SPECULAR_COLOR          7
1094 #define MIRROR_COLOR            8
1095 #define AMBIENT_COLOR           9
1096 #define AMBIENT                         10
1097 #define EMIT                            11
1098 #define DISPLACE                        12
1099 #define STRAND                          13
1100 #define STRESS                          14
1101 #define TANGENT                         15
1102 #define SURFACE_D                       30
1103 #define TEXTURE_D                       31
1104 #define GLOBALTEXTURE_D         32
1105 #define REFLECTION_D            33
1106 #define NORMAL_D                        34
1107 #define STICKY_D                        35
1108 #define REFRACT_D                       36
1109 #define STRAND_D                        37
1110
1111 /* MACRO time: defining shi getters */
1112
1113 /* a couple checks that we can redefine to nothing for a tiny performance
1114  * gain */
1115
1116 #define SHI_CHECK_SHI\
1117         if (!self->shi)\
1118                 return EXPP_ReturnPyObjError(PyExc_RuntimeError,\
1119                                 "no shade input data!");
1120
1121 #define SHI_CHECK_OB\
1122         if (!ob)\
1123                 return EXPP_ReturnPyObjError(PyExc_RuntimeError,\
1124                                 "couldn't create vector object!");
1125
1126 /* for shi getters: */
1127
1128 #define SHI_GETATTR_f(name, var)\
1129 static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1130 {\
1131         PyObject *ob = NULL;\
1132 \
1133         SHI_CHECK_SHI\
1134 \
1135         ob = PyFloat_FromDouble((double)(self->shi->var));\
1136 \
1137         SHI_CHECK_OB\
1138 \
1139         return ob;\
1140 }
1141
1142 #define SHI_GETATTR_fvec(name, var, len)\
1143 static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1144 {\
1145         PyObject *ob = NULL;\
1146 \
1147         SHI_CHECK_SHI\
1148 \
1149         ob = newVectorObject(self->shi->var, len, Py_NEW);\
1150 \
1151         SHI_CHECK_OB\
1152 \
1153         return ob;\
1154 }
1155
1156 #define SHI_GETATTR_2fvec(name, v1, v2, len)\
1157 static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1158 {\
1159         PyObject *ob = NULL;\
1160         PyObject *tuple = NULL;\
1161 \
1162         SHI_CHECK_SHI\
1163 \
1164         tuple = PyTuple_New(2);\
1165 \
1166         ob = newVectorObject(self->shi->v1, len, Py_NEW);\
1167         PyTuple_SET_ITEM(tuple, 0, ob);\
1168 \
1169         ob = newVectorObject(self->shi->v2, len, Py_NEW);\
1170         PyTuple_SET_ITEM(tuple, 1, ob);\
1171 \
1172         return tuple;\
1173 }
1174
1175 #define SHI_GETATTR_3f(name, v1, v2, v3)\
1176 static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1177 {\
1178         PyObject *ob = NULL;\
1179         float vec[3];\
1180 \
1181         SHI_CHECK_SHI\
1182 \
1183         vec[0] = self->shi->v1;\
1184         vec[1] = self->shi->v2;\
1185         vec[2] = self->shi->v3;\
1186 \
1187         ob = newVectorObject(vec, 3, Py_NEW);\
1188 \
1189         SHI_CHECK_OB\
1190 \
1191         return ob;\
1192 }
1193
1194 /* float */
1195
1196 SHI_GETATTR_f(Ambient, amb);
1197 SHI_GETATTR_f(Emit, emit);
1198 SHI_GETATTR_f(Strand, strandco);
1199 SHI_GETATTR_f(Stress, stress);
1200
1201 /* 3 float vars */
1202
1203 SHI_GETATTR_3f(Color, r, g, b)
1204 SHI_GETATTR_3f(ColorSpecular, specr, specg, specb)
1205 SHI_GETATTR_3f(ColorMirror, mirr, mirg, mirb)
1206 SHI_GETATTR_3f(ColorAmbient, ambr, ambg, ambb)
1207
1208 /* float vector */
1209
1210 SHI_GETATTR_fvec(SurfaceViewVector, view, 3)
1211 SHI_GETATTR_fvec(SurfaceNormal, facenor, 3)
1212 SHI_GETATTR_fvec(ViewNormal, vn, 3)
1213 SHI_GETATTR_fvec(TextureGlobal, gl, 3)
1214 SHI_GETATTR_fvec(Texture, lo, 3)
1215 SHI_GETATTR_fvec(Displace, displace, 3)
1216 SHI_GETATTR_fvec(Tangent, tang, 3)
1217
1218 /* two float vectors */
1219
1220 SHI_GETATTR_2fvec(SurfaceD, dxco, dyco, 3)
1221 SHI_GETATTR_2fvec(TextureD, dxlo, dylo, 3)
1222 SHI_GETATTR_2fvec(TextureGlobalD, dxgl, dygl, 3)
1223 SHI_GETATTR_2fvec(ReflectionD, dxref, dyref, 3)
1224 SHI_GETATTR_2fvec(NormalD, dxno, dyno, 3)
1225 SHI_GETATTR_2fvec(StickyD, dxsticky, dysticky, 3)
1226 SHI_GETATTR_2fvec(RefractD, dxrefract, dyrefract, 3)
1227
1228 /* single cases (for now), not macros: */
1229
1230 static PyObject *ShadeInput_getPixel(BPy_ShadeInput *self, void *unused)
1231 {
1232         PyObject *ob = NULL;
1233
1234         SHI_CHECK_SHI
1235
1236         ob = Py_BuildValue("(ii)", self->shi->xs, self->shi->ys);
1237
1238         SHI_CHECK_OB
1239
1240         return ob;
1241 }
1242
1243 static PyObject *ShadeInput_getStrandD(BPy_ShadeInput *self, void *unused)
1244 {
1245         PyObject *ob = NULL;
1246         float vec[2];
1247
1248         SHI_CHECK_SHI
1249
1250         vec[0] = self->shi->dxstrand;
1251         vec[1] = self->shi->dystrand;
1252
1253         ob = newVectorObject(vec, 2, Py_NEW);
1254
1255         SHI_CHECK_OB
1256
1257         return ob;
1258 }
1259
1260 static BPy_SockMap *Node_CreateOutputMap(bNode *node, bNodeStack **stack) {
1261         BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockOutMap_Type);
1262         map->node = node;
1263         map->stack = stack;
1264         return map;
1265 }
1266
1267 static PyObject *Node_GetOutputMap(BPy_Node *self) {
1268         BPy_SockMap *outmap = Node_CreateOutputMap(self->node, self->out);
1269         return (PyObject *)outmap;
1270 }
1271
1272 static PyObject *Node_GetShi(BPy_Node *self) {
1273         BPy_ShadeInput *shi = ShadeInput_CreatePyObject(self->shi);
1274         return (PyObject *)shi;
1275 }
1276
1277 static PyObject *node_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1278 {
1279         PyObject *self;
1280         self = type->tp_alloc(type, 1);
1281         return self;
1282 }
1283
1284 static int node_init(BPy_Node *self, PyObject *args, PyObject *kwds)
1285 {
1286         return 0;
1287 }
1288
1289 static PyGetSetDef BPy_Node_getseters[] = {
1290         {"input",
1291                 (getter)Node_GetInputMap, (setter)NULL,
1292                 "Get the input sockets mapping (dictionary)",
1293                 NULL},
1294         {"i", /* alias */
1295                 (getter)Node_GetInputMap, (setter)NULL,
1296                 "Get the input sockets mapping (dictionary)",
1297                 NULL},
1298         {"output",
1299                 (getter)Node_GetOutputMap, (setter)NULL,
1300                 "Get the output sockets mapping (dictionary)",
1301                 NULL},
1302         {"o", /* alias */
1303                 (getter)Node_GetOutputMap, (setter)NULL,
1304                 "Get the output sockets mapping (dictionary)",
1305                 NULL},
1306         {"shi",
1307                 (getter)Node_GetShi, (setter)NULL,
1308                 "Get the Shade Input data (ShadeInput)",
1309                 NULL},
1310         {"s", /* alias */
1311                 (getter)Node_GetShi, (setter)NULL,
1312                 "Get the Shade Input data (ShadeInput)",
1313                 NULL},
1314         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1315 };
1316
1317 static PyGetSetDef BPy_ShadeInput_getseters[] = {
1318         {"texture",
1319           (getter)ShadeInput_getTexture, (setter)NULL,
1320           "Get the current texture coordinate (3-vector)", NULL},
1321         {"textureGlobal",
1322           (getter)ShadeInput_getTextureGlobal, (setter)NULL,
1323           "Get the current global texture coordinate (3-vector)", NULL},
1324         {"surfaceNormal",
1325           (getter)ShadeInput_getSurfaceNormal, (setter)NULL,
1326           "Get the current surface normal (3-vector)", NULL},
1327         {"viewNormal",
1328           (getter)ShadeInput_getViewNormal, (setter)NULL,
1329           "Get the current view normal (3-vector)", NULL},
1330         {"surfaceViewVector",
1331           (getter)ShadeInput_getSurfaceViewVector, (setter)NULL,
1332           "Get the vector pointing to the viewpoint from the point being shaded (3-vector)", NULL},
1333         {"pixel",
1334           (getter)ShadeInput_getPixel, (setter)NULL,
1335           "Get the x,y-coordinate for the pixel rendered (3-vector)", NULL},
1336         {"color",
1337           (getter)ShadeInput_getColor, (setter)NULL,
1338           "Get the color for the point being shaded (3-vector)", NULL},
1339         {"specularColor",
1340           (getter)ShadeInput_getColorSpecular, (setter)NULL,
1341           "Get the specular color for the point being shaded (3-vector)", NULL},
1342         {"mirrorColor",
1343           (getter)ShadeInput_getColorMirror, (setter)NULL,
1344           "Get the mirror color for the point being shaded (3-vector)", NULL},
1345         {"ambientColor",
1346           (getter)ShadeInput_getColorAmbient, (setter)NULL,
1347           "Get the ambient color for the point being shaded (3-vector)", NULL},
1348         {"ambient",
1349           (getter)ShadeInput_getAmbient, (setter)NULL,
1350           "Get the ambient factor for the point being shaded (float)", NULL},
1351         {"emit",
1352           (getter)ShadeInput_getEmit, (setter)NULL,
1353           "Get the emit factor for the point being shaded (float)", NULL},
1354         {"displace",
1355           (getter)ShadeInput_getDisplace, (setter)NULL,
1356           "Get the displace vector for the point being shaded (3-vector)", NULL},
1357         {"strand",
1358           (getter)ShadeInput_getStrand, (setter)NULL,
1359           "Get the strand factor(float)", NULL},
1360         {"stress",
1361           (getter)ShadeInput_getStress, (setter)NULL,
1362           "Get the stress factor(float)", NULL},
1363         {"tangent",
1364           (getter)ShadeInput_getTangent, (setter)NULL,
1365           "Get the tangent vector (3-vector)", NULL},
1366         {"surfaceD",
1367           (getter)ShadeInput_getSurfaceD, (setter)NULL,
1368           "Get the surface d (tuple with pair of 3-vectors)", NULL},
1369         {"textureD",
1370           (getter)ShadeInput_getTextureD, (setter)NULL,
1371           "Get the texture d (tuple with pair of 3-vectors)", NULL},
1372         {"textureGlobalD",
1373           (getter)ShadeInput_getTextureGlobalD, (setter)NULL,
1374           "Get the global texture d (tuple with pair of 3-vectors)", NULL},
1375         {"reflectionD",
1376           (getter)ShadeInput_getReflectionD, (setter)NULL,
1377           "Get the reflection d (tuple with pair of 3-vectors)", NULL},
1378         {"normalD",
1379           (getter)ShadeInput_getNormalD, (setter)NULL,
1380           "Get the normal d (tuple with pair of 3-vectors)", NULL},
1381         {"stickyD",
1382           (getter)ShadeInput_getStickyD, (setter)NULL,
1383           "Get the sticky d (tuple with pair of 3-vectors)", NULL},
1384         {"refractD",
1385           (getter)ShadeInput_getRefractD, (setter)NULL,
1386           "Get the refract d (tuple with pair of 3-vectors)", NULL},
1387         {"strandD",
1388           (getter)ShadeInput_getStrandD, (setter)NULL,
1389           "Get the strand d (2-vector)", NULL},
1390         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1391 };
1392
1393 PyTypeObject Node_Type = {
1394         PyObject_HEAD_INIT( NULL )  /* required py macro */
1395         0,                          /* ob_size */
1396         /*  For printing, in format "<module>.<name>" */
1397         "Blender.Node.Scripted",    /* char *tp_name; */
1398         sizeof( BPy_Node ),         /* int tp_basicsize; */
1399         0,                          /* tp_itemsize;  For allocation */
1400
1401         /* Methods to implement standard operations */
1402
1403         NULL,/* destructor tp_dealloc; */
1404         NULL,                       /* printfunc tp_print; */
1405         NULL /*( getattrfunc ) PyObject_GenericGetAttr*/,                       /* getattrfunc tp_getattr; */
1406         NULL /*( setattrfunc ) PyObject_GenericSetAttr*/,                       /* setattrfunc tp_setattr; */
1407         ( cmpfunc ) Node_compare,   /* cmpfunc tp_compare; */
1408         ( reprfunc ) Node_repr,     /* reprfunc tp_repr; */
1409
1410         /* Method suites for standard classes */
1411
1412         NULL,                       /* PyNumberMethods *tp_as_number; */
1413         NULL,                       /* PySequenceMethods *tp_as_sequence; */
1414         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1415
1416         /* More standard operations (here for binary compatibility) */
1417
1418         NULL,                       /* hashfunc tp_hash; */
1419         NULL,                       /* ternaryfunc tp_call; */
1420         NULL,                       /* reprfunc tp_str; */
1421         NULL,                       /* getattrofunc tp_getattro; */
1422         NULL,                       /* setattrofunc tp_setattro; */
1423
1424         /* Functions to access object as input/output buffer */
1425         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1426
1427   /*** Flags to define presence of optional/expanded features ***/
1428         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* long tp_flags; */
1429
1430         NULL,                       /*  char *tp_doc;  Documentation string */
1431   /*** Assigned meaning in release 2.0 ***/
1432         /* call function for all accessible objects */
1433         NULL,                       /* traverseproc tp_traverse; */
1434
1435         /* delete references to contained objects */
1436         NULL,                       /* inquiry tp_clear; */
1437
1438   /***  Assigned meaning in release 2.1 ***/
1439   /*** rich comparisons ***/
1440         NULL,                       /* richcmpfunc tp_richcompare; */
1441
1442   /***  weak reference enabler ***/
1443         0,                          /* long tp_weaklistoffset; */
1444
1445   /*** Added in release 2.2 ***/
1446         /*   Iterators */
1447         NULL,                       /* getiterfunc tp_iter; */
1448         NULL,                       /* iternextfunc tp_iternext; */
1449
1450   /*** Attribute descriptor and subclassing stuff ***/
1451         NULL, /*BPy_Node_methods,*/          /* struct PyMethodDef *tp_methods; */
1452         NULL,                       /* struct PyMemberDef *tp_members; */
1453         BPy_Node_getseters,        /* struct PyGetSetDef *tp_getset; */
1454         NULL,                       /* struct _typeobject *tp_base; */
1455         NULL,                       /* PyObject *tp_dict; */
1456         NULL,                       /* descrgetfunc tp_descr_get; */
1457         NULL,                       /* descrsetfunc tp_descr_set; */
1458         0,                          /* long tp_dictoffset; */
1459         (initproc)node_init,                       /* initproc tp_init; */
1460         /*PyType_GenericAlloc*/NULL,                       /* allocfunc tp_alloc; */
1461         node_new,                       /* newfunc tp_new; */
1462         /*  Low-level free-memory routine */
1463         NULL,                       /* freefunc tp_free;  */
1464         /* For PyObject_IS_GC */
1465         NULL,                       /* inquiry tp_is_gc;  */
1466         NULL,                       /* PyObject *tp_bases; */
1467         /* method resolution order */
1468         NULL,                       /* PyObject *tp_mro;  */
1469         NULL,                       /* PyObject *tp_cache; */
1470         NULL,                       /* PyObject *tp_subclasses; */
1471         NULL,                       /* PyObject *tp_weaklist; */
1472         NULL
1473 };
1474
1475 PyTypeObject ShadeInput_Type = {
1476         PyObject_HEAD_INIT( NULL )  /* required py macro */
1477         0,                          /* ob_size */
1478         /*  For printing, in format "<module>.<name>" */
1479         "Blender.Node.ShadeInput",             /* char *tp_name; */
1480         sizeof( BPy_ShadeInput ),         /* int tp_basicsize; */
1481         0,                          /* tp_itemsize;  For allocation */
1482
1483         /* Methods to implement standard operations */
1484
1485         NULL,/* destructor tp_dealloc; */
1486         NULL,                       /* printfunc tp_print; */
1487         NULL,                       /* getattrfunc tp_getattr; */
1488         NULL,                       /* setattrfunc tp_setattr; */
1489         ( cmpfunc ) ShadeInput_compare,   /* cmpfunc tp_compare; */
1490         ( reprfunc ) ShadeInput_repr,     /* reprfunc tp_repr; */
1491
1492         /* Method suites for standard classes */
1493
1494         NULL,                       /* PyNumberMethods *tp_as_number; */
1495         NULL,                       /* PySequenceMethods *tp_as_sequence; */
1496         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1497
1498         /* More standard operations (here for binary compatibility) */
1499
1500         NULL,                       /* hashfunc tp_hash; */
1501         NULL,                       /* ternaryfunc tp_call; */
1502         NULL,                       /* reprfunc tp_str; */
1503         NULL,                       /* getattrofunc tp_getattro; */
1504         NULL,                       /* setattrofunc tp_setattro; */
1505
1506         /* Functions to access object as input/output buffer */
1507         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1508
1509   /*** Flags to define presence of optional/expanded features ***/
1510         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1511
1512         NULL,                       /*  char *tp_doc;  Documentation string */
1513   /*** Assigned meaning in release 2.0 ***/
1514         /* call function for all accessible objects */
1515         NULL,                       /* traverseproc tp_traverse; */
1516
1517         /* delete references to contained objects */
1518         NULL,                       /* inquiry tp_clear; */
1519
1520   /***  Assigned meaning in release 2.1 ***/
1521   /*** rich comparisons ***/
1522         NULL,                       /* richcmpfunc tp_richcompare; */
1523
1524   /***  weak reference enabler ***/
1525         0,                          /* long tp_weaklistoffset; */
1526
1527   /*** Added in release 2.2 ***/
1528         /*   Iterators */
1529         NULL,                       /* getiterfunc tp_iter; */
1530         NULL,                       /* iternextfunc tp_iternext; */
1531
1532   /*** Attribute descriptor and subclassing stuff ***/
1533         NULL, /*BPy_Node_methods,*/          /* struct PyMethodDef *tp_methods; */
1534         NULL,                       /* struct PyMemberDef *tp_members; */
1535         BPy_ShadeInput_getseters,   /* struct PyGetSetDef *tp_getset; */
1536         NULL,                       /* struct _typeobject *tp_base; */
1537         NULL,                       /* PyObject *tp_dict; */
1538         NULL,                       /* descrgetfunc tp_descr_get; */
1539         NULL,                       /* descrsetfunc tp_descr_set; */
1540         0,                          /* long tp_dictoffset; */
1541         NULL,                       /* initproc tp_init; */
1542         NULL,                       /* allocfunc tp_alloc; */
1543         NULL,                       /* newfunc tp_new; */
1544         /*  Low-level free-memory routine */
1545         NULL,                       /* freefunc tp_free;  */
1546         /* For PyObject_IS_GC */
1547         NULL,                       /* inquiry tp_is_gc;  */
1548         NULL,                       /* PyObject *tp_bases; */
1549         /* method resolution order */
1550         NULL,                       /* PyObject *tp_mro;  */
1551         NULL,                       /* PyObject *tp_cache; */
1552         NULL,                       /* PyObject *tp_subclasses; */
1553         NULL,                       /* PyObject *tp_weaklist; */
1554         NULL
1555 };
1556
1557 /* Initialise Node module */
1558 PyObject *Node_Init(void)
1559 {
1560         PyObject *submodule;
1561
1562         if( PyType_Ready( &Node_Type ) < 0 )
1563                 return NULL;
1564         if( PyType_Ready( &ShadeInput_Type ) < 0 )
1565                 return NULL;
1566         if( PyType_Ready( &NodeSocket_Type ) < 0 )
1567                 return NULL;
1568         if( PyType_Ready( &NodeSocketLists_Type ) < 0 )
1569                 return NULL;
1570         if( PyType_Ready( &SockInMap_Type ) < 0 )
1571                 return NULL;
1572         if( PyType_Ready( &SockOutMap_Type ) < 0 )
1573                 return NULL;
1574         submodule = Py_InitModule3( "Blender.Node", NULL, "");
1575
1576         PyModule_AddIntConstant(submodule, "VALUE", SOCK_VALUE);
1577         PyModule_AddIntConstant(submodule, "RGBA", SOCK_RGBA);
1578         PyModule_AddIntConstant(submodule, "VECTOR", SOCK_VECTOR);
1579
1580         Py_INCREF(&NodeSocket_Type);
1581         PyModule_AddObject(submodule, "Socket", (PyObject *)&NodeSocket_Type);
1582
1583         Py_INCREF(&Node_Type);
1584         PyModule_AddObject(submodule, "Scripted", (PyObject *)&Node_Type);
1585
1586         return submodule;
1587 }
1588
1589 static int Node_compare(BPy_Node *a, BPy_Node *b)
1590 {
1591         bNode *pa = a->node, *pb = b->node;
1592         return (pa == pb) ? 0 : -1;
1593 }
1594
1595 static PyObject *Node_repr(BPy_Node *self)
1596 {
1597         return PyString_FromFormat( "[Node \"%s\"]",
1598                 self->node ? self->node->id->name+2 : "empty node");
1599 }
1600
1601 BPy_Node *Node_CreatePyObject(bNode *node)
1602 {
1603         BPy_Node *pynode;
1604
1605         pynode = (BPy_Node *)PyObject_NEW(BPy_Node, &Node_Type);
1606         if(!pynode) {
1607                 fprintf(stderr,"Couldn't create BPy_Node object\n");
1608                 return (BPy_Node *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_Node object"));
1609         }
1610
1611         pynode->node = node;
1612
1613         return pynode;
1614 }
1615
1616 int pytype_is_pynode(PyObject *pyob)
1617 {
1618         return PyObject_TypeCheck(pyob, &Node_Type);
1619 }
1620
1621 void InitNode(BPy_Node *self, bNode *node) {
1622         self->node = node;
1623 }
1624
1625 bNode *Node_FromPyObject(PyObject *pyobj)
1626 {
1627         return ((BPy_Node *)pyobj)->node;
1628 }
1629
1630 void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type)
1631 {
1632         if(type == NODE_INPUTSTACK) {
1633                 self->in = stack;
1634         } else if(type == NODE_OUTPUTSTACK) {
1635                 self->out = stack;
1636         }
1637 }
1638
1639 void Node_SetShi(BPy_Node *self, ShadeInput *shi)
1640 {
1641         self->shi = shi;
1642 }
1643
1644 /*********************/
1645
1646 static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b)
1647 {
1648         ShadeInput *pa = a->shi, *pb = b->shi;
1649         return (pa == pb) ? 0 : -1;
1650 }
1651
1652 static PyObject *ShadeInput_repr(BPy_ShadeInput *self)
1653 {
1654         return PyString_FromFormat( "[ShadeInput at \"%p\"]", self);
1655 }
1656
1657 BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi)
1658 {
1659         BPy_ShadeInput *pyshi;
1660
1661         pyshi = (BPy_ShadeInput *)PyObject_NEW(BPy_ShadeInput, &ShadeInput_Type);
1662         if(!pyshi) {
1663                 fprintf(stderr,"Couldn't create BPy_ShadeInput object\n");
1664                 return (BPy_ShadeInput *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_ShadeInput object"));
1665         }
1666
1667         pyshi->shi = shi;
1668
1669         return pyshi;
1670 }
1671