Merged changes from trunk to soc-2008-mxcurioni: svn merge -r 14534:14595 https:...
[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         nsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType in Node.c");
365
366         for (pos = 0, a = 0; pos< len; pos++, a++) {
367                 pysock = (BPy_NodeSocket *)PyTuple_GetItem(tuple, pos);/*borrowed*/
368
369                 if (!BPy_NodeSocket_Check(pysock)) {
370                         PyErr_SetString(PyExc_AttributeError, "expected a sequence of node sockets");
371                         retval = -1;
372                         break;
373                 }
374
375                 stype = pysock->type;
376
377                 nsocks[a].type = stype;
378                 nsocks[a].limit = limit;
379
380                 nsocks[a].name = BLI_strdupn(pysock->name, NODE_MAXSTR);
381
382                 nsocks[a].min = pysock->min;
383                 nsocks[a].max = pysock->max;
384
385                 if (stype > SOCK_VALUE) {
386                         float *vec = pysock->val;
387
388                         nsocks[a].val1 = vec[0];
389                         nsocks[a].val2 = vec[1];
390                         nsocks[a].val3 = vec[2];
391
392                         if (stype == SOCK_RGBA)
393                                 nsocks[a].val4 = vec[3];
394                 }
395                 else /* SOCK_VALUE */
396                         nsocks[a].val1 = pysock->val[0];
397         }
398
399         nsocks[a].type = -1;
400
401         *socks = nsocks;
402
403         return retval;
404 }
405
406 static void NodeSocketLists_dealloc(BPy_NodeSocketLists *self)
407 {
408         Py_DECREF(self->input);
409         Py_DECREF(self->output);
410         self->ob_type->tp_free((PyObject *)self);
411 }
412
413 static PyObject *Map_socketdef_getter(BPy_NodeSocketLists *self, void *closure)
414 {
415         PyObject *sockets = NULL;
416
417         switch (GET_INT_FROM_POINTER(closure)) {
418                 case 'I': /* inputs */
419                         Py_INCREF(self->input);
420                         sockets = self->input;
421                         break;
422                 case 'O': /* outputs */
423                         Py_INCREF(self->output);
424                         sockets = self->output;
425                         break;
426                 default:
427                         fprintf(stderr, "DEBUG pynodes: wrong option in Map_socketdef_getter\n");
428                         Py_INCREF(Py_None);
429                         sockets = Py_None;
430                         break;
431         }
432
433         return sockets;
434 }
435
436 static int Map_socketdef(BPy_NodeSocketLists *self, PyObject *args, void *closure)
437 {
438         bNode *node = NULL;
439         PyObject *tuple = NULL;
440
441         node = self->node;
442
443         if(!node) {
444                 fprintf(stderr,"DEBUG pynodes: No bNode in BPy_Node (Map_socketdef)\n");
445                 return 0;
446         }
447
448         if(BTST2(node->custom1, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST))
449                 return 0;
450
451         switch(GET_INT_FROM_POINTER(closure)) {
452                 case 'I':
453                         if (args) {
454                                 if(PySequence_Check(args)) {
455                                         tuple = PySequence_Tuple(args);
456                                         pysockets_to_blendersockets(tuple,
457                                                         &(node->typeinfo->inputs), node->custom1, 1);
458                                         Py_DECREF(self->input);
459                                         self->input = tuple;
460                                 } else {
461                                         return(EXPP_ReturnIntError( PyExc_AttributeError, "INPUT must be a List of Lists or Tuples"));
462                                 }
463                         }
464                         break;
465                 case 'O':
466                         if (args) {
467                                 if(PyList_Check(args)) {
468                                         tuple = PySequence_Tuple(args);
469                                         pysockets_to_blendersockets(tuple,
470                                                         &(node->typeinfo->outputs), node->custom1, 0);
471                                         Py_DECREF(self->output);
472                                         self->output = tuple;
473                                 } else {
474                                         return(EXPP_ReturnIntError( PyExc_AttributeError, "OUTPUT must be a List of Lists or Tuples"));
475                                 }
476                         }
477                         break;
478                 default:
479                         fprintf(stderr,"DEBUG pynodes: got no list in Map_socketdef\n");
480                         break;
481         }
482         return 0;
483 }
484
485 static PyGetSetDef NodeSocketLists_getseters[] = {
486         {"input", (getter)Map_socketdef_getter, (setter)Map_socketdef,
487                 "Set this node's input sockets (list of lists or tuples)",
488                 (void *)'I'},
489         {"i" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef,
490                 "Set this node's input sockets (list of lists or tuples)",
491                 (void *)'I'},
492         {"output", (getter)Map_socketdef_getter, (setter)Map_socketdef,
493                 "Set this node's output sockets (list of lists or tuples)",
494                 (void *)'O'},
495         {"o" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef,
496                 "Set this node's output sockets (list of lists or tuples)",
497                 (void *)'O'},
498         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
499 };
500
501 PyTypeObject NodeSocketLists_Type = {
502         PyObject_HEAD_INIT( NULL )  /* required py macro */
503         0,                          /* ob_size */
504         /*  For printing, in format "<module>.<name>" */
505         "Blender.Node.SocketLists",           /* char *tp_name; */
506         sizeof( BPy_NodeSocketLists ),       /* int tp_basicsize; */
507         0,                          /* tp_itemsize;  For allocation */
508
509         /* Methods to implement standard operations */
510
511         (destructor)NodeSocketLists_dealloc,/* destructor tp_dealloc; */
512         NULL,                       /* printfunc tp_print; */
513         NULL,                       /* getattrfunc tp_getattr; */
514         NULL,                       /* setattrfunc tp_setattr; */
515         NULL,                       /* cmpfunc tp_compare; */
516         NULL,                       /* reprfunc tp_repr; */
517
518         /* Method suites for standard classes */
519
520         NULL,                                           /* PyNumberMethods *tp_as_number; */
521         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
522         NULL,      /* PyMappingMethods *tp_as_mapping; */
523
524         /* More standard operations (here for binary compatibility) */
525
526         NULL,                       /* hashfunc tp_hash; */
527         NULL,                       /* ternaryfunc tp_call; */
528         NULL,                       /* reprfunc tp_str; */
529         NULL,                       /* getattrofunc tp_getattro; */
530         NULL,                       /* setattrofunc tp_setattro; */
531
532         /* Functions to access object as input/input buffer */
533         NULL,                       /* PyBufferProcs *tp_as_buffer; */
534
535   /*** Flags to define presence of optional/expanded features ***/
536         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
537
538         NULL,                       /*  char *tp_doc;  Documentation string */
539   /*** Assigned meaning in release 2.0 ***/
540         /* call function for all accessible objects */
541         NULL,                       /* traverseproc tp_traverse; */
542
543         /* delete references to contained objects */
544         NULL,                       /* inquiry tp_clear; */
545
546   /***  Assigned meaning in release 2.1 ***/
547   /*** rich comparisons ***/
548         NULL,                       /* richcmpfunc tp_richcompare; */
549
550   /***  weak reference enabler ***/
551         0,                          /* long tp_weaklistoffset; */
552
553   /*** Added in release 2.2 ***/
554         /*   Iterators */
555         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
556         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
557
558   /*** Attribute descriptor and subclassing stuff ***/
559         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
560         NULL,                       /* struct PyMemberDef *tp_members; */
561         NodeSocketLists_getseters,      /* struct PyGetSetDef *tp_getset; */
562         NULL,                       /* struct _typeobject *tp_base; */
563         NULL,                       /* PyObject *tp_dict; */
564         NULL,                       /* descrgetfunc tp_descr_get; */
565         NULL,                       /* descrsetfunc tp_descr_set; */
566         0,                          /* long tp_dictoffset; */
567         NULL,                       /* initproc tp_init; */
568         NULL,                       /* allocfunc tp_alloc; */
569         NULL,                       /* newfunc tp_new; */
570         /*  Low-level free-memory routine */
571         NULL,                       /* freefunc tp_free;  */
572         /* For PyObject_IS_GC */
573         NULL,                       /* inquiry tp_is_gc;  */
574         NULL,                       /* PyObject *tp_bases; */
575         /* method resolution order */
576         NULL,                       /* PyObject *tp_mro;  */
577         NULL,                       /* PyObject *tp_cache; */
578         NULL,                       /* PyObject *tp_subclasses; */
579         NULL,                       /* PyObject *tp_weaklist; */
580         NULL
581 };
582
583 BPy_NodeSocketLists *Node_CreateSocketLists(bNode *node) {
584         BPy_NodeSocketLists *socklists = PyObject_NEW(BPy_NodeSocketLists, &NodeSocketLists_Type);
585         socklists->node = node;
586         socklists->input = PyList_New(0);
587         socklists->output = PyList_New(0);
588         return socklists;
589 }
590
591 /***************************************/
592
593 static int Sockinmap_len ( BPy_SockMap * self) {
594         bNode *node = self->node;
595         bNodeType *tinfo;
596         int a = 0;
597
598         if (!node) return 0;
599
600         tinfo = node->typeinfo;
601
602         if (BNTST(node->custom1, NODE_DYNAMIC_READY)) return 0;
603
604         if (tinfo && tinfo->inputs) {
605                 while(self->node->typeinfo->inputs[a].type!=-1)
606                         a++;
607         }
608         return a;
609 }
610
611 static int sockinmap_has_key( BPy_SockMap *self, char *strkey) {
612         bNode *node = self->node;
613         bNodeType *tinfo;
614         int a = 0;
615
616         if (!node || !strkey) return -1;
617
618         tinfo = node->typeinfo;
619
620         if(tinfo && tinfo->inputs){
621                 while(self->node->typeinfo->inputs[a].type!=-1) {
622                         if(BLI_strcaseeq(self->node->typeinfo->inputs[a].name, strkey)) {
623                                 return a;
624                         }
625                         a++;
626                 }
627         }
628         return -1;
629 }
630
631 PyObject *Sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) {
632         int idx;
633
634         if (!self->node)
635                 return EXPP_ReturnPyObjError(PyExc_RuntimeError, "no access to Blender node data!");
636
637         if (PyString_Check(pyidx)) {
638                 idx = sockinmap_has_key(self, PyString_AsString(pyidx));
639         }
640         else if(PyInt_Check(pyidx)) {
641                 int len = Sockinmap_len(self);
642                 idx = (int)PyInt_AsLong(pyidx);
643                 if (idx < 0 || idx >= len)
644                         return EXPP_ReturnPyObjError(PyExc_IndexError, "index out of range");
645         }
646         else if (PySlice_Check(pyidx)) {
647                 return EXPP_ReturnPyObjError(PyExc_ValueError, "slices not implemented");
648         } else {
649                 return EXPP_ReturnPyObjError(PyExc_IndexError, "index must be an int or a string");
650         }
651
652         if(idx<0) { /* we're not as nice as Python */
653                 return EXPP_ReturnPyObjError(PyExc_IndexError, "invalid socket index");
654         }
655         
656         switch(self->node->typeinfo->inputs[idx].type) {
657                 case SOCK_VALUE:
658                         return Py_BuildValue("f", self->stack[idx]->vec[0]);
659                         break;
660                 case SOCK_VECTOR:
661                         return Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
662                         break;
663                 case SOCK_RGBA:
664                         /* otherwise RGBA tuple */
665                         return Py_BuildValue("(ffff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2], self->stack[idx]->vec[3]);
666                         break;
667                 default:
668                         break;
669         }
670
671         Py_RETURN_NONE;
672 }
673
674 static PyObject *Sockinmap_getAttr(BPy_SockMap *self, char *attr)
675 {
676         PyObject *pyob = NULL;
677         int idx;
678
679         idx = sockinmap_has_key(self, attr);
680
681         if (idx < 0)
682                 return EXPP_ReturnPyObjError(PyExc_AttributeError, "unknown input socket name");
683
684         switch(self->node->typeinfo->inputs[idx].type) {
685                 case SOCK_VALUE:
686                         pyob = Py_BuildValue("f", self->stack[idx]->vec[0]);
687                         break;
688                 case SOCK_VECTOR:
689                         pyob = Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
690                         break;
691                 case SOCK_RGBA:
692                         pyob = Py_BuildValue("(ffff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2], self->stack[idx]->vec[3]);
693                         break;
694                 default:
695                         break;
696         }
697
698         return pyob;
699 }
700
701 /* read only */
702 static PyMappingMethods Sockinmap_as_mapping = {
703         ( inquiry ) Sockinmap_len,  /* mp_length */
704         ( binaryfunc ) Sockinmap_subscript, /* mp_subscript */
705         ( objobjargproc ) 0 /* mp_ass_subscript */
706 };
707
708 PyTypeObject SockInMap_Type = {
709         PyObject_HEAD_INIT( NULL )  /* required py macro */
710         0,                          /* ob_size */
711         /*  For printing, in format "<module>.<name>" */
712         "Blender.Node.InputSockets",           /* char *tp_name; */
713         sizeof( BPy_SockMap ),       /* int tp_basicsize; */
714         0,                          /* tp_itemsize;  For allocation */
715
716         /* Methods to implement standard operations */
717
718         NULL,/* destructor tp_dealloc; */
719         NULL,                       /* printfunc tp_print; */
720         (getattrfunc) Sockinmap_getAttr,/* getattrfunc tp_getattr; */
721         NULL,                       /* setattrfunc tp_setattr; */
722         NULL,                       /* cmpfunc tp_compare; */
723         NULL,                       /* reprfunc tp_repr; */
724
725         /* Method suites for standard classes */
726
727         NULL,                                           /* PyNumberMethods *tp_as_number; */
728         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
729         &Sockinmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
730
731         /* More standard operations (here for binary compatibility) */
732
733         NULL,                       /* hashfunc tp_hash; */
734         NULL,                       /* ternaryfunc tp_call; */
735         NULL,                       /* reprfunc tp_str; */
736         NULL,                       /* getattrofunc tp_getattro; */
737         NULL,                       /* setattrofunc tp_setattro; */
738
739         /* Functions to access object as input/output buffer */
740         NULL,                       /* PyBufferProcs *tp_as_buffer; */
741
742   /*** Flags to define presence of optional/expanded features ***/
743         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
744
745         NULL,                       /*  char *tp_doc;  Documentation string */
746   /*** Assigned meaning in release 2.0 ***/
747         /* call function for all accessible objects */
748         NULL,                       /* traverseproc tp_traverse; */
749
750         /* delete references to contained objects */
751         NULL,                       /* inquiry tp_clear; */
752
753   /***  Assigned meaning in release 2.1 ***/
754   /*** rich comparisons ***/
755         NULL,                       /* richcmpfunc tp_richcompare; */
756
757   /***  weak reference enabler ***/
758         0,                          /* long tp_weaklistoffset; */
759
760   /*** Added in release 2.2 ***/
761         /*   Iterators */
762         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
763         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
764
765   /*** Attribute descriptor and subclassing stuff ***/
766         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
767         NULL,                       /* struct PyMemberDef *tp_members; */
768         NULL,                       /* struct PyGetSetDef *tp_getset; */
769         NULL,                       /* struct _typeobject *tp_base; */
770         NULL,                       /* PyObject *tp_dict; */
771         NULL,                       /* descrgetfunc tp_descr_get; */
772         NULL,                       /* descrsetfunc tp_descr_set; */
773         0,                          /* long tp_dictoffset; */
774         NULL,                       /* initproc tp_init; */
775         NULL,                       /* allocfunc tp_alloc; */
776         NULL,                       /* newfunc tp_new; */
777         /*  Low-level free-memory routine */
778         NULL,                       /* freefunc tp_free;  */
779         /* For PyObject_IS_GC */
780         NULL,                       /* inquiry tp_is_gc;  */
781         NULL,                       /* PyObject *tp_bases; */
782         /* method resolution order */
783         NULL,                       /* PyObject *tp_mro;  */
784         NULL,                       /* PyObject *tp_cache; */
785         NULL,                       /* PyObject *tp_subclasses; */
786         NULL,                       /* PyObject *tp_weaklist; */
787         NULL
788 };
789
790 static int Sockoutmap_len ( BPy_SockMap * self) {
791         bNode *node = self->node;
792         bNodeType *tinfo;
793         int a = 0;
794
795         if (!node) return 0;
796
797         tinfo = node->typeinfo;
798
799         if (tinfo && tinfo->outputs) {
800                 while(self->node->typeinfo->outputs[a].type!=-1)
801                         a++;
802         }
803         return a;
804 }
805
806 static int sockoutmap_has_key(BPy_SockMap *self, char *strkey) {
807         bNode *node = self->node;
808         bNodeType *tinfo;
809         int a = 0;
810
811         if (!node) return -1;
812
813         tinfo = node->typeinfo;
814
815         if(tinfo && tinfo->outputs){
816                 while(self->node->typeinfo->outputs[a].type!=-1) {
817                         if(BLI_strcaseeq(self->node->typeinfo->outputs[a].name, strkey)) {
818                                 return a;
819                         }
820                         a++;
821                 }
822         }
823         return -1;
824 }
825
826 static int Sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObject *value) {
827         int i, idx, len, type, wanted_len = 0;
828         PyObject *val;
829         PyObject *items[4];
830
831         if (!self->node)
832                 return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
833
834         if (PyInt_Check(pyidx)) {
835                 idx = (int)PyInt_AsLong(pyidx);
836                 if (idx < 0 || idx >= Sockinmap_len(self))
837                         return EXPP_ReturnIntError(PyExc_IndexError, "index out of range");
838         }
839         else if (PyString_Check(pyidx)) {
840                 idx = sockoutmap_has_key(self, PyString_AsString(pyidx));
841         }
842         else if (PySlice_Check(pyidx)) {
843                 return EXPP_ReturnIntError(PyExc_ValueError, "slices not yet implemented");
844         } else {
845                 return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
846         }
847
848         if (idx < 0)
849                 return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
850
851         type = self->node->typeinfo->outputs[idx].type;
852
853         if (type == SOCK_VALUE) {
854                 val = PyNumber_Float(value);
855                 if (!val)
856                         return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
857                 self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
858                 Py_DECREF(val);
859         }
860         else {
861                 val = PySequence_Fast(value, "expected a numeric tuple or list");
862                 if (!val) return -1;
863
864                 len = PySequence_Fast_GET_SIZE(val);
865
866                 if (type == SOCK_VECTOR) {
867                         wanted_len = 3;
868                 } else { /* SOCK_RGBA */
869                         wanted_len = 4;
870                 }
871
872                 if (len != wanted_len) {
873                         Py_DECREF(val);
874                         PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
875                         fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
876                         return -1;
877                 }
878
879                 for (i = 0; i < len; i++) {
880                         items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
881                         if (!PyNumber_Check(items[i])) {
882                                 Py_DECREF(val);
883                                 return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
884                         }
885                 }
886
887                 self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
888                 self->stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
889                 self->stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
890
891                 if (type == SOCK_RGBA)
892                         self->stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
893
894                 Py_DECREF(val);
895         }
896
897         return 0;
898 }
899
900 static int sockoutmap_set_attr(bNodeStack **stack, short type, short idx, PyObject *value)
901 {
902         PyObject *val;
903         PyObject *items[4];
904         int i;
905         short len, wanted_len;
906
907         if (type == SOCK_VALUE) {
908                 val = PyNumber_Float(value);
909                 if (!val)
910                         return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
911                 stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
912                 Py_DECREF(val);
913         }
914         else {
915                 val = PySequence_Fast(value, "expected a numeric tuple or list");
916                 if (!val) return -1;
917
918                 len = PySequence_Fast_GET_SIZE(val);
919
920                 if (type == SOCK_VECTOR) {
921                         wanted_len = 3;
922                 } else { /* SOCK_RGBA */
923                         wanted_len = 4;
924                 }
925
926                 if (len != wanted_len) {
927                         Py_DECREF(val);
928                         PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
929                         fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
930                         return -1;
931                 }
932
933                 for (i = 0; i < len; i++) {
934                         items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
935                         if (!PyNumber_Check(items[i])) {
936                                 Py_DECREF(val);
937                                 return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
938                         }
939                 }
940
941                 stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
942                 stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
943                 stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
944
945                 if (type == SOCK_RGBA)
946                         stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
947
948                 Py_DECREF(val);
949         }
950
951         return 0;
952 }
953
954 static int Sockoutmap_setAttr(BPy_SockMap *self, char *name, PyObject *value) {
955         short idx, type;
956
957         if (!self->node)
958                 return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
959
960         idx = sockoutmap_has_key(self, name);
961
962         if (idx < 0)
963                 return EXPP_ReturnIntError(PyExc_AttributeError, "unknown output socket name");
964
965         type = self->node->typeinfo->outputs[idx].type;
966
967         return sockoutmap_set_attr(self->stack, type, idx, value);
968 }
969 /* write only */
970 static PyMappingMethods Sockoutmap_as_mapping = {
971         ( inquiry ) Sockoutmap_len,  /* mp_length */
972         ( binaryfunc ) 0, /* mp_subscript */
973         ( objobjargproc ) Sockoutmap_assign_subscript /* mp_ass_subscript */
974 };
975
976 PyTypeObject SockOutMap_Type = {
977         PyObject_HEAD_INIT( NULL )  /* required py macro */
978         0,                          /* ob_size */
979         /*  For printing, in format "<module>.<name>" */
980         "Blender.Node.OutputSockets",           /* char *tp_name; */
981         sizeof( BPy_SockMap ),       /* int tp_basicsize; */
982         0,                          /* tp_itemsize;  For allocation */
983
984         /* Methods to implement standard operations */
985
986         NULL,/* destructor tp_dealloc; */
987         NULL,                       /* printfunc tp_print; */
988         NULL,                       /* getattrfunc tp_getattr; */
989         (setattrfunc) Sockoutmap_setAttr,/* setattrfunc tp_setattr; */
990         NULL,                       /* cmpfunc tp_compare; */
991         NULL,                       /* reprfunc tp_repr; */
992
993         /* Method suites for standard classes */
994
995         NULL,                                           /* PyNumberMethods *tp_as_number; */
996         NULL,                                       /* PySequenceMethods *tp_as_sequence; */
997         &Sockoutmap_as_mapping,      /* PyMappingMethods *tp_as_mapping; */
998
999         /* More standard operations (here for binary compatibility) */
1000
1001         NULL,                       /* hashfunc tp_hash; */
1002         NULL,                       /* ternaryfunc tp_call; */
1003         NULL,                       /* reprfunc tp_str; */
1004         NULL,                       /* getattrofunc tp_getattro; */
1005         NULL,                       /* setattrofunc tp_setattro; */
1006
1007         /* Functions to access object as input/output buffer */
1008         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1009
1010   /*** Flags to define presence of optional/expanded features ***/
1011         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1012
1013         NULL,                       /*  char *tp_doc;  Documentation string */
1014   /*** Assigned meaning in release 2.0 ***/
1015         /* call function for all accessible objects */
1016         NULL,                       /* traverseproc tp_traverse; */
1017
1018         /* delete references to contained objects */
1019         NULL,                       /* inquiry tp_clear; */
1020
1021   /***  Assigned meaning in release 2.1 ***/
1022   /*** rich comparisons ***/
1023         NULL,                       /* richcmpfunc tp_richcompare; */
1024
1025   /***  weak reference enabler ***/
1026         0,                          /* long tp_weaklistoffset; */
1027
1028   /*** Added in release 2.2 ***/
1029         /*   Iterators */
1030         0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
1031         0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
1032
1033   /*** Attribute descriptor and subclassing stuff ***/
1034         0, //BPy_MVertSeq_methods,       /* struct PyMethodDef *tp_methods; */
1035         NULL,                       /* struct PyMemberDef *tp_members; */
1036         NULL,                       /* struct PyGetSetDef *tp_getset; */
1037         NULL,                       /* struct _typeobject *tp_base; */
1038         NULL,                       /* PyObject *tp_dict; */
1039         NULL,                       /* descrgetfunc tp_descr_get; */
1040         NULL,                       /* descrsetfunc tp_descr_set; */
1041         0,                          /* long tp_dictoffset; */
1042         NULL,                       /* initproc tp_init; */
1043         NULL,                       /* allocfunc tp_alloc; */
1044         NULL,                       /* newfunc tp_new; */
1045         /*  Low-level free-memory routine */
1046         NULL,                       /* freefunc tp_free;  */
1047         /* For PyObject_IS_GC */
1048         NULL,                       /* inquiry tp_is_gc;  */
1049         NULL,                       /* PyObject *tp_bases; */
1050         /* method resolution order */
1051         NULL,                       /* PyObject *tp_mro;  */
1052         NULL,                       /* PyObject *tp_cache; */
1053         NULL,                       /* PyObject *tp_subclasses; */
1054         NULL,                       /* PyObject *tp_weaklist; */
1055         NULL
1056 };
1057
1058
1059 static BPy_SockMap *Node_CreateInputMap(bNode *node, bNodeStack **stack) {
1060         BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockInMap_Type);
1061         map->node = node;
1062         map->stack = stack;
1063         return map;
1064 }
1065
1066 static PyObject *Node_GetInputMap(BPy_Node *self) {
1067         BPy_SockMap *inmap = Node_CreateInputMap(self->node, self->in);
1068         return (PyObject *)(inmap);
1069 }
1070
1071 #define SURFACEVIEWVECTOR       0
1072 #define VIEWNORMAL                      1
1073 #define SURFACENORMAL           2
1074 #define GLOBALTEXTURE           3
1075 #define TEXTURE                         4
1076 #define PIXEL                           5
1077 #define COLOR                           6
1078 #define SPECULAR_COLOR          7
1079 #define MIRROR_COLOR            8
1080 #define AMBIENT_COLOR           9
1081 #define AMBIENT                         10
1082 #define EMIT                            11
1083 #define DISPLACE                        12
1084 #define STRAND                          13
1085 #define STRESS                          14
1086 #define TANGENT                         15
1087 #define SURFACE_D                       30
1088 #define TEXTURE_D                       31
1089 #define GLOBALTEXTURE_D         32
1090 #define REFLECTION_D            33
1091 #define NORMAL_D                        34
1092 #define STICKY_D                        35
1093 #define REFRACT_D                       36
1094 #define STRAND_D                        37
1095
1096 static PyObject *ShadeInput_getAttribute(BPy_ShadeInput *self, void *type) {
1097         PyObject *obj = NULL;
1098         if(self->shi) {
1099                 switch(GET_INT_FROM_POINTER(type)) {
1100                         case SURFACEVIEWVECTOR:
1101                                 obj = Py_BuildValue("(fff)", self->shi->view[0], self->shi->view[1], self->shi->view[2]);
1102                                 break;
1103                         case VIEWNORMAL:
1104                                 obj = Py_BuildValue("(fff)", self->shi->vn[0], self->shi->vn[1], self->shi->vn[2]);
1105                                 break;
1106                         case SURFACENORMAL:
1107                                 obj = Py_BuildValue("(fff)", self->shi->facenor[0], self->shi->facenor[1], self->shi->facenor[2]);
1108                                 break;
1109                         case GLOBALTEXTURE:
1110                                 obj = Py_BuildValue("(fff)", self->shi->gl[0], self->shi->gl[1], self->shi->gl[2]);
1111                                 break;
1112                         case TEXTURE:
1113                                 obj = Py_BuildValue("(fff)", self->shi->lo[0], self->shi->lo[1], self->shi->lo[2]);
1114                                 break;
1115                         case PIXEL:
1116                                 obj = Py_BuildValue("(ii)", self->shi->xs, self->shi->ys);
1117                                 break;
1118                         case COLOR:
1119                                 obj = Py_BuildValue("(fff)", self->shi->r, self->shi->g, self->shi->b);
1120                                 break;
1121                         case SPECULAR_COLOR:
1122                                 obj = Py_BuildValue("(fff)", self->shi->specr, self->shi->specg, self->shi->specb);
1123                                 break;
1124                         case MIRROR_COLOR:
1125                                 obj = Py_BuildValue("(fff)", self->shi->mirr, self->shi->mirg, self->shi->mirb);
1126                                 break;
1127                         case AMBIENT_COLOR:
1128                                 obj = Py_BuildValue("(fff)", self->shi->ambr, self->shi->ambg, self->shi->ambb);
1129                                 break;
1130                         case AMBIENT:
1131                                 obj = PyFloat_FromDouble((double)(self->shi->amb));
1132                                 break;
1133                         case EMIT:
1134                                 obj = PyFloat_FromDouble((double)(self->shi->emit));
1135                                 break;
1136                         case DISPLACE:
1137                                 obj = Py_BuildValue("(fff)", self->shi->displace[0], self->shi->displace[1], self->shi->displace[2]);
1138                                 break;
1139                         case STRAND:
1140                                 obj = PyFloat_FromDouble((double)(self->shi->strandco));
1141                                 break;
1142                         case STRESS:
1143                                 obj = PyFloat_FromDouble((double)(self->shi->stress));
1144                                 break;
1145                         case TANGENT:
1146                                 obj = Py_BuildValue("(fff)", self->shi->tang[0], self->shi->tang[1], self->shi->tang[2]);
1147                                 break;
1148                         case SURFACE_D:
1149                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxco[0], self->shi->dxco[1], self->shi->dxco[2], self->shi->dyco[0], self->shi->dyco[1], self->shi->dyco[2]);
1150                                 break;
1151                         case TEXTURE_D:
1152                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxlo[0], self->shi->dxlo[1], self->shi->dxlo[2], self->shi->dylo[0], self->shi->dylo[1], self->shi->dylo[2]);
1153                                 break;
1154                         case GLOBALTEXTURE_D:
1155                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxgl[0], self->shi->dxgl[1], self->shi->dxgl[2], self->shi->dygl[0], self->shi->dygl[1], self->shi->dygl[2]);
1156                                 break;
1157                         case REFLECTION_D:
1158                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxref[0], self->shi->dxref[1], self->shi->dxref[2], self->shi->dyref[0], self->shi->dyref[1], self->shi->dyref[2]);
1159                                 break;
1160                         case NORMAL_D:
1161                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxno[0], self->shi->dxno[1], self->shi->dxno[2], self->shi->dyno[0], self->shi->dyno[1], self->shi->dyno[2]);
1162                                 break;
1163                         case STICKY_D:
1164                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxsticky[0], self->shi->dxsticky[1], self->shi->dxsticky[2], self->shi->dysticky[0], self->shi->dysticky[1], self->shi->dysticky[2]);
1165                                 break;
1166                         case REFRACT_D:
1167                                 obj = Py_BuildValue("(fff)(fff)", self->shi->dxrefract[0], self->shi->dxrefract[1], self->shi->dxrefract[2], self->shi->dyrefract[0], self->shi->dyrefract[1], self->shi->dyrefract[2]);
1168                                 break;
1169                         case STRAND_D:
1170                                 obj = Py_BuildValue("(ff)", self->shi->dxstrand, self->shi->dystrand);
1171                                 break;
1172                         default:
1173                                 break;
1174                 }
1175         }
1176
1177         if(!obj) {
1178                 Py_RETURN_NONE;
1179         }
1180         return obj;
1181 }
1182
1183 static BPy_SockMap *Node_CreateOutputMap(bNode *node, bNodeStack **stack) {
1184         BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockOutMap_Type);
1185         map->node = node;
1186         map->stack = stack;
1187         return map;
1188 }
1189
1190 static PyObject *Node_GetOutputMap(BPy_Node *self) {
1191         BPy_SockMap *outmap = Node_CreateOutputMap(self->node, self->out);
1192         return (PyObject *)outmap;
1193 }
1194
1195 static PyObject *Node_GetShi(BPy_Node *self) {
1196         BPy_ShadeInput *shi = ShadeInput_CreatePyObject(self->shi);
1197         return (PyObject *)shi;
1198 }
1199
1200 static PyObject *node_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1201 {
1202         PyObject *self;
1203         self = type->tp_alloc(type, 1);
1204         return self;
1205 }
1206
1207 static int node_init(BPy_Node *self, PyObject *args, PyObject *kwds)
1208 {
1209         return 0;
1210 }
1211
1212 static PyGetSetDef BPy_Node_getseters[] = {
1213         {"input",
1214                 (getter)Node_GetInputMap, (setter)NULL,
1215                 "Get the input sockets mapping (dictionary)",
1216                 NULL},
1217         {"i", /* alias */
1218                 (getter)Node_GetInputMap, (setter)NULL,
1219                 "Get the input sockets mapping (dictionary)",
1220                 NULL},
1221         {"output",
1222                 (getter)Node_GetOutputMap, (setter)NULL,
1223                 "Get the output sockets mapping (dictionary)",
1224                 NULL},
1225         {"o", /* alias */
1226                 (getter)Node_GetOutputMap, (setter)NULL,
1227                 "Get the output sockets mapping (dictionary)",
1228                 NULL},
1229         {"shi",
1230                 (getter)Node_GetShi, (setter)NULL,
1231                 "Get the Shade Input data (ShadeInput)",
1232                 NULL},
1233         {"s", /* alias */
1234                 (getter)Node_GetShi, (setter)NULL,
1235                 "Get the Shade Input data (ShadeInput)",
1236                 NULL},
1237         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1238 };
1239
1240 static PyGetSetDef BPy_ShadeInput_getseters[] = {
1241         {"texture",
1242           (getter)ShadeInput_getAttribute, (setter)NULL,
1243           "Get the current texture coordinate (tuple)",
1244           (void*)TEXTURE},
1245         {"textureGlobal",
1246           (getter)ShadeInput_getAttribute, (setter)NULL,
1247           "Get the current global texture coordinate (tuple)",
1248           (void*)GLOBALTEXTURE},
1249         {"surfaceNormal",
1250           (getter)ShadeInput_getAttribute, (setter)NULL,
1251           "Get the current surface normal (tuple)",
1252           (void*)SURFACENORMAL},
1253         {"viewNormal",
1254           (getter)ShadeInput_getAttribute, (setter)NULL,
1255           "Get the current view normal (tuple)",
1256           (void*)VIEWNORMAL},
1257         {"surfaceViewVector",
1258           (getter)ShadeInput_getAttribute, (setter)NULL,
1259           "Get the vector pointing to the viewpoint from the point being shaded (tuple)",
1260           (void*)SURFACEVIEWVECTOR},
1261         {"pixel",
1262           (getter)ShadeInput_getAttribute, (setter)NULL,
1263           "Get the x,y-coordinate for the pixel rendered (tuple)",
1264           (void*)PIXEL},
1265         {"color",
1266           (getter)ShadeInput_getAttribute, (setter)NULL,
1267           "Get the color for the point being shaded (tuple)",
1268           (void*)COLOR},
1269         {"specularColor",
1270           (getter)ShadeInput_getAttribute, (setter)NULL,
1271           "Get the specular color for the point being shaded (tuple)",
1272           (void*)SPECULAR_COLOR},
1273         {"mirrorColor",
1274           (getter)ShadeInput_getAttribute, (setter)NULL,
1275           "Get the mirror color for the point being shaded (tuple)",
1276           (void*)MIRROR_COLOR},
1277         {"ambientColor",
1278           (getter)ShadeInput_getAttribute, (setter)NULL,
1279           "Get the ambient color for the point being shaded (tuple)",
1280           (void*)AMBIENT_COLOR},
1281         {"ambient",
1282           (getter)ShadeInput_getAttribute, (setter)NULL,
1283           "Get the ambient factor for the point being shaded (float)",
1284           (void*)AMBIENT},
1285         {"emit",
1286           (getter)ShadeInput_getAttribute, (setter)NULL,
1287           "Get the emit factor for the point being shaded (float)",
1288           (void*)EMIT},
1289         {"displace",
1290           (getter)ShadeInput_getAttribute, (setter)NULL,
1291           "Get the displace vector for the point being shaded (tuple)",
1292           (void*)DISPLACE},
1293         {"strand",
1294           (getter)ShadeInput_getAttribute, (setter)NULL,
1295           "Get the strand factor(float)",
1296           (void*)STRAND},
1297         {"stress",
1298           (getter)ShadeInput_getAttribute, (setter)NULL,
1299           "Get the stress factor(float)",
1300           (void*)STRESS},
1301         {"tangent",
1302           (getter)ShadeInput_getAttribute, (setter)NULL,
1303           "Get the tangent vector (tuple)",
1304           (void*)TANGENT},
1305         {"surfaceD",
1306           (getter)ShadeInput_getAttribute, (setter)NULL,
1307           "Get the surface d (tuple of tuples)",
1308           (void*)SURFACE_D},
1309         {"textureD",
1310           (getter)ShadeInput_getAttribute, (setter)NULL,
1311           "Get the texture d (tuple of tuples)",
1312           (void*)TEXTURE_D},
1313         {"textureGlobalD",
1314           (getter)ShadeInput_getAttribute, (setter)NULL,
1315           "Get the global texture d (tuple of tuples)",
1316           (void*)GLOBALTEXTURE_D},
1317         {"reflectionD",
1318           (getter)ShadeInput_getAttribute, (setter)NULL,
1319           "Get the reflection d (tuple of tuples)",
1320           (void*)REFLECTION_D},
1321         {"normalD",
1322           (getter)ShadeInput_getAttribute, (setter)NULL,
1323           "Get the normal d (tuple of tuples)",
1324           (void*)NORMAL_D},
1325         {"stickyD",
1326           (getter)ShadeInput_getAttribute, (setter)NULL,
1327           "Get the sticky d (tuple of tuples)",
1328           (void*)STICKY_D},
1329         {"refractD",
1330           (getter)ShadeInput_getAttribute, (setter)NULL,
1331           "Get the refract d (tuple of tuples)",
1332           (void*)REFRACT_D},
1333         {"strandD",
1334           (getter)ShadeInput_getAttribute, (setter)NULL,
1335           "Get the strand d (tuple)",
1336           (void*)STRAND_D},
1337         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1338 };
1339
1340 PyTypeObject Node_Type = {
1341         PyObject_HEAD_INIT( NULL )  /* required py macro */
1342         0,                          /* ob_size */
1343         /*  For printing, in format "<module>.<name>" */
1344         "Blender.Node.Scripted",    /* char *tp_name; */
1345         sizeof( BPy_Node ),         /* int tp_basicsize; */
1346         0,                          /* tp_itemsize;  For allocation */
1347
1348         /* Methods to implement standard operations */
1349
1350         NULL,/* destructor tp_dealloc; */
1351         NULL,                       /* printfunc tp_print; */
1352         NULL /*( getattrfunc ) PyObject_GenericGetAttr*/,                       /* getattrfunc tp_getattr; */
1353         NULL /*( setattrfunc ) PyObject_GenericSetAttr*/,                       /* setattrfunc tp_setattr; */
1354         ( cmpfunc ) Node_compare,   /* cmpfunc tp_compare; */
1355         ( reprfunc ) Node_repr,     /* reprfunc tp_repr; */
1356
1357         /* Method suites for standard classes */
1358
1359         NULL,                       /* PyNumberMethods *tp_as_number; */
1360         NULL,                       /* PySequenceMethods *tp_as_sequence; */
1361         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1362
1363         /* More standard operations (here for binary compatibility) */
1364
1365         NULL,                       /* hashfunc tp_hash; */
1366         NULL,                       /* ternaryfunc tp_call; */
1367         NULL,                       /* reprfunc tp_str; */
1368         NULL,                       /* getattrofunc tp_getattro; */
1369         NULL,                       /* setattrofunc tp_setattro; */
1370
1371         /* Functions to access object as input/output buffer */
1372         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1373
1374   /*** Flags to define presence of optional/expanded features ***/
1375         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,         /* long tp_flags; */
1376
1377         NULL,                       /*  char *tp_doc;  Documentation string */
1378   /*** Assigned meaning in release 2.0 ***/
1379         /* call function for all accessible objects */
1380         NULL,                       /* traverseproc tp_traverse; */
1381
1382         /* delete references to contained objects */
1383         NULL,                       /* inquiry tp_clear; */
1384
1385   /***  Assigned meaning in release 2.1 ***/
1386   /*** rich comparisons ***/
1387         NULL,                       /* richcmpfunc tp_richcompare; */
1388
1389   /***  weak reference enabler ***/
1390         0,                          /* long tp_weaklistoffset; */
1391
1392   /*** Added in release 2.2 ***/
1393         /*   Iterators */
1394         NULL,                       /* getiterfunc tp_iter; */
1395         NULL,                       /* iternextfunc tp_iternext; */
1396
1397   /*** Attribute descriptor and subclassing stuff ***/
1398         NULL, /*BPy_Node_methods,*/          /* struct PyMethodDef *tp_methods; */
1399         NULL,                       /* struct PyMemberDef *tp_members; */
1400         BPy_Node_getseters,        /* struct PyGetSetDef *tp_getset; */
1401         NULL,                       /* struct _typeobject *tp_base; */
1402         NULL,                       /* PyObject *tp_dict; */
1403         NULL,                       /* descrgetfunc tp_descr_get; */
1404         NULL,                       /* descrsetfunc tp_descr_set; */
1405         0,                          /* long tp_dictoffset; */
1406         (initproc)node_init,                       /* initproc tp_init; */
1407         /*PyType_GenericAlloc*/NULL,                       /* allocfunc tp_alloc; */
1408         node_new,                       /* newfunc tp_new; */
1409         /*  Low-level free-memory routine */
1410         NULL,                       /* freefunc tp_free;  */
1411         /* For PyObject_IS_GC */
1412         NULL,                       /* inquiry tp_is_gc;  */
1413         NULL,                       /* PyObject *tp_bases; */
1414         /* method resolution order */
1415         NULL,                       /* PyObject *tp_mro;  */
1416         NULL,                       /* PyObject *tp_cache; */
1417         NULL,                       /* PyObject *tp_subclasses; */
1418         NULL,                       /* PyObject *tp_weaklist; */
1419         NULL
1420 };
1421
1422 PyTypeObject ShadeInput_Type = {
1423         PyObject_HEAD_INIT( NULL )  /* required py macro */
1424         0,                          /* ob_size */
1425         /*  For printing, in format "<module>.<name>" */
1426         "Blender.Node.ShadeInput",             /* char *tp_name; */
1427         sizeof( BPy_ShadeInput ),         /* int tp_basicsize; */
1428         0,                          /* tp_itemsize;  For allocation */
1429
1430         /* Methods to implement standard operations */
1431
1432         NULL,/* destructor tp_dealloc; */
1433         NULL,                       /* printfunc tp_print; */
1434         NULL,                       /* getattrfunc tp_getattr; */
1435         NULL,                       /* setattrfunc tp_setattr; */
1436         ( cmpfunc ) ShadeInput_compare,   /* cmpfunc tp_compare; */
1437         ( reprfunc ) ShadeInput_repr,     /* reprfunc tp_repr; */
1438
1439         /* Method suites for standard classes */
1440
1441         NULL,                       /* PyNumberMethods *tp_as_number; */
1442         NULL,                       /* PySequenceMethods *tp_as_sequence; */
1443         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1444
1445         /* More standard operations (here for binary compatibility) */
1446
1447         NULL,                       /* hashfunc tp_hash; */
1448         NULL,                       /* ternaryfunc tp_call; */
1449         NULL,                       /* reprfunc tp_str; */
1450         NULL,                       /* getattrofunc tp_getattro; */
1451         NULL,                       /* setattrofunc tp_setattro; */
1452
1453         /* Functions to access object as input/output buffer */
1454         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1455
1456   /*** Flags to define presence of optional/expanded features ***/
1457         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
1458
1459         NULL,                       /*  char *tp_doc;  Documentation string */
1460   /*** Assigned meaning in release 2.0 ***/
1461         /* call function for all accessible objects */
1462         NULL,                       /* traverseproc tp_traverse; */
1463
1464         /* delete references to contained objects */
1465         NULL,                       /* inquiry tp_clear; */
1466
1467   /***  Assigned meaning in release 2.1 ***/
1468   /*** rich comparisons ***/
1469         NULL,                       /* richcmpfunc tp_richcompare; */
1470
1471   /***  weak reference enabler ***/
1472         0,                          /* long tp_weaklistoffset; */
1473
1474   /*** Added in release 2.2 ***/
1475         /*   Iterators */
1476         NULL,                       /* getiterfunc tp_iter; */
1477         NULL,                       /* iternextfunc tp_iternext; */
1478
1479   /*** Attribute descriptor and subclassing stuff ***/
1480         NULL, /*BPy_Node_methods,*/          /* struct PyMethodDef *tp_methods; */
1481         NULL,                       /* struct PyMemberDef *tp_members; */
1482         BPy_ShadeInput_getseters,        /* struct PyGetSetDef *tp_getset; */
1483         NULL,                       /* struct _typeobject *tp_base; */
1484         NULL,                       /* PyObject *tp_dict; */
1485         NULL,                       /* descrgetfunc tp_descr_get; */
1486         NULL,                       /* descrsetfunc tp_descr_set; */
1487         0,                          /* long tp_dictoffset; */
1488         NULL,                       /* initproc tp_init; */
1489         NULL,                       /* allocfunc tp_alloc; */
1490         NULL,                       /* newfunc tp_new; */
1491         /*  Low-level free-memory routine */
1492         NULL,                       /* freefunc tp_free;  */
1493         /* For PyObject_IS_GC */
1494         NULL,                       /* inquiry tp_is_gc;  */
1495         NULL,                       /* PyObject *tp_bases; */
1496         /* method resolution order */
1497         NULL,                       /* PyObject *tp_mro;  */
1498         NULL,                       /* PyObject *tp_cache; */
1499         NULL,                       /* PyObject *tp_subclasses; */
1500         NULL,                       /* PyObject *tp_weaklist; */
1501         NULL
1502 };
1503
1504 /* Initialise Node module */
1505 PyObject *Node_Init(void)
1506 {
1507         PyObject *submodule;
1508
1509         if( PyType_Ready( &Node_Type ) < 0 )
1510                 return NULL;
1511         if( PyType_Ready( &ShadeInput_Type ) < 0 )
1512                 return NULL;
1513         if( PyType_Ready( &NodeSocket_Type ) < 0 )
1514                 return NULL;
1515         if( PyType_Ready( &NodeSocketLists_Type ) < 0 )
1516                 return NULL;
1517         if( PyType_Ready( &SockInMap_Type ) < 0 )
1518                 return NULL;
1519         if( PyType_Ready( &SockOutMap_Type ) < 0 )
1520                 return NULL;
1521         submodule = Py_InitModule3( "Blender.Node", NULL, "");
1522
1523         PyModule_AddIntConstant(submodule, "VALUE", SOCK_VALUE);
1524         PyModule_AddIntConstant(submodule, "RGBA", SOCK_RGBA);
1525         PyModule_AddIntConstant(submodule, "VECTOR", SOCK_VECTOR);
1526
1527         Py_INCREF(&NodeSocket_Type);
1528         PyModule_AddObject(submodule, "Socket", (PyObject *)&NodeSocket_Type);
1529
1530         Py_INCREF(&Node_Type);
1531         PyModule_AddObject(submodule, "Scripted", (PyObject *)&Node_Type);
1532
1533         return submodule;
1534 }
1535
1536 static int Node_compare(BPy_Node *a, BPy_Node *b)
1537 {
1538         bNode *pa = a->node, *pb = b->node;
1539         return (pa == pb) ? 0 : -1;
1540 }
1541
1542 static PyObject *Node_repr(BPy_Node *self)
1543 {
1544         return PyString_FromFormat( "[Node \"%s\"]",
1545                 self->node ? self->node->id->name+2 : "empty node");
1546 }
1547
1548 BPy_Node *Node_CreatePyObject(bNode *node)
1549 {
1550         BPy_Node *pynode;
1551
1552         pynode = (BPy_Node *)PyObject_NEW(BPy_Node, &Node_Type);
1553         if(!pynode) {
1554                 fprintf(stderr,"Couldn't create BPy_Node object\n");
1555                 return (BPy_Node *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_Node object"));
1556         }
1557
1558         pynode->node = node;
1559
1560         return pynode;
1561 }
1562
1563 int pytype_is_pynode(PyObject *pyob)
1564 {
1565         return PyObject_TypeCheck(pyob, &Node_Type);
1566 }
1567
1568 void InitNode(BPy_Node *self, bNode *node) {
1569         self->node = node;
1570 }
1571
1572 bNode *Node_FromPyObject(PyObject *pyobj)
1573 {
1574         return ((BPy_Node *)pyobj)->node;
1575 }
1576
1577 void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type)
1578 {
1579         if(type == NODE_INPUTSTACK) {
1580                 self->in = stack;
1581         } else if(type == NODE_OUTPUTSTACK) {
1582                 self->out = stack;
1583         }
1584 }
1585
1586 void Node_SetShi(BPy_Node *self, ShadeInput *shi)
1587 {
1588         self->shi = shi;
1589 }
1590
1591 /*********************/
1592
1593 static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b)
1594 {
1595         ShadeInput *pa = a->shi, *pb = b->shi;
1596         return (pa == pb) ? 0 : -1;
1597 }
1598
1599 static PyObject *ShadeInput_repr(BPy_ShadeInput *self)
1600 {
1601         return PyString_FromFormat( "[ShadeInput at \"%p\"]", self);
1602 }
1603
1604 BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi)
1605 {
1606         BPy_ShadeInput *pyshi;
1607
1608         pyshi = (BPy_ShadeInput *)PyObject_NEW(BPy_ShadeInput, &ShadeInput_Type);
1609         if(!pyshi) {
1610                 fprintf(stderr,"Couldn't create BPy_ShadeInput object\n");
1611                 return (BPy_ShadeInput *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_ShadeInput object"));
1612         }
1613
1614         pyshi->shi = shi;
1615
1616         return pyshi;
1617 }
1618