2
* $Id: Node.c 14872 2008-05-16 20:57:06Z ianwill $
4
* ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20
* The Original Code is Copyright (C) 2006, Blender Foundation
21
* All rights reserved.
23
* Original code is this file
25
* Contributor(s): Nathan Letwory
27
* ***** END GPL LICENSE BLOCK *****
32
#include "BKE_global.h"
35
#include "BKE_utildefines.h"
37
#include "DNA_material_types.h"
39
#include "MEM_guardedalloc.h"
41
#include "BLI_blenlib.h"
42
#include "gen_utils.h"
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);
51
/* node socket type */
53
static PyObject *NodeSocket_getName(BPy_NodeSocket *self, void *unused)
55
return PyString_FromString(self->name);
58
static int NodeSocket_setName(BPy_NodeSocket *self, PyObject *value, void *unused)
62
if (!PyString_Check(value))
63
return EXPP_ReturnIntError( PyExc_TypeError,
64
"expected a string" );
66
name = PyString_AsString(value);
69
return EXPP_ReturnIntError(PyExc_RuntimeError,
70
"couldn't convert value to string!");
72
BLI_strncpy(self->name, name, NODE_MAXSTR);
77
static PyObject *NodeSocket_getVal(BPy_NodeSocket *self, void *unused)
79
PyObject *pyret = NULL;
81
if (self->type == SOCK_VALUE) {
82
pyret = PyFloat_FromDouble(self->val[0]);
84
else { /* VECTOR or RGBA */
85
pyret = newVectorObject(self->val, self->type, Py_NEW);
88
return EXPP_ReturnPyObjError(PyExc_RuntimeError,
89
"couldn't create vector object!");
95
static int NodeSocket_setVal(BPy_NodeSocket *self, PyObject *value, void *unused)
99
if (PySequence_Check(value)) {
100
PyObject *item, *fpyval;
103
len = PySequence_Size(value);
105
if (len == 3 || len == 4) {
106
for (i = 0; i < len; i++) {
107
item = PySequence_GetItem(value, i);
108
fpyval = PyNumber_Float(item);
114
self->val[i] = (float)PyFloat_AsDouble(fpyval);
119
self->type = SOCK_VECTOR;
121
self->type = SOCK_RGBA;
125
else if (VectorObject_Check(value)) {
126
VectorObject *vecOb = (VectorObject *)value;
127
short vlen = vecOb->size;
129
if (vlen == 3 || vlen == 4) {
130
VECCOPY(self->val, vecOb->vec); /* copies 3 values */
132
self->type = SOCK_VECTOR;
134
self->val[3] = vecOb->vec[3];
135
self->type = SOCK_RGBA;
140
else if (PyNumber_Check(value)) {
141
self->val[0] = (float)PyFloat_AsDouble(value);
142
self->type = SOCK_VALUE;
147
return EXPP_ReturnIntError( PyExc_TypeError,
148
"expected a float or a sequence (or vector) of 3 or 4 floats" );
152
static PyObject *NodeSocket_getMin(BPy_NodeSocket *self, void *unused)
154
return PyFloat_FromDouble(self->min);
157
static int NodeSocket_setMin(BPy_NodeSocket *self, PyObject *value, void *unused)
159
PyObject *pyval = PyNumber_Float(value);
162
return EXPP_ReturnIntError( PyExc_TypeError,
163
"expected a float number" );
165
self->min = (float)PyFloat_AsDouble(pyval);
171
static PyObject *NodeSocket_getMax(BPy_NodeSocket *self, void *unused)
173
return PyFloat_FromDouble(self->max);
176
static int NodeSocket_setMax(BPy_NodeSocket *self, PyObject *value, void *unused)
178
PyObject *pyval = PyNumber_Float(value);
181
return EXPP_ReturnIntError( PyExc_TypeError,
182
"expected a float number" );
184
self->max = (float)PyFloat_AsDouble(pyval);
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 */
202
static void NodeSocket_dealloc(BPy_NodeSocket *self)
204
self->ob_type->tp_free((PyObject *)self);
207
static PyObject *NodeSocket_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
209
PyObject *pysocket = type->tp_alloc(type, 0);
212
return EXPP_ReturnPyObjError(PyExc_RuntimeError, "couldn't create socket type!");
217
static int NodeSocket_init(BPy_NodeSocket *self, PyObject *args, PyObject *kwargs)
220
float min = 0.0f, max = 1.0f;
221
PyObject *val = NULL;
222
static char *kwlist[] = {"name", "val", "min", "max", NULL};
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");
228
BLI_strncpy(self->name, name, NODE_MAXSTR);
234
return NodeSocket_setVal(self, val, NULL);
236
self->type = SOCK_VALUE;
242
static PyObject *NodeSocket_copy(BPy_NodeSocket *self)
244
BPy_NodeSocket *copied;
246
copied = (BPy_NodeSocket*)NodeSocket_new(&NodeSocket_Type, NULL, NULL);
248
if (!copied) return NULL; /* error already set in NodeSocket_new */
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));
256
return (PyObject *)copied;
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}
267
PyTypeObject NodeSocket_Type = {
268
PyObject_HEAD_INIT( NULL ) /* required py macro */
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 */
275
/* Methods to implement standard operations */
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; */
284
/* Method suites for standard classes */
286
NULL, /* PyNumberMethods *tp_as_number; */
287
NULL, /* PySequenceMethods *tp_as_sequence; */
288
NULL, /* PyMappingMethods *tp_as_mapping; */
290
/* More standard operations (here for binary compatibility) */
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; */
298
/* Functions to access object as input/input buffer */
299
NULL, /* PyBufferProcs *tp_as_buffer; */
301
/*** Flags to define presence of optional/expanded features ***/
302
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* long tp_flags; */
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; */
309
/* delete references to contained objects */
310
NULL, /* inquiry tp_clear; */
312
/*** Assigned meaning in release 2.1 ***/
313
/*** rich comparisons ***/
314
NULL, /* richcmpfunc tp_richcompare; */
316
/*** weak reference enabler ***/
317
0, /* long tp_weaklistoffset; */
319
/*** Added in release 2.2 ***/
321
0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
322
0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
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; */
350
* Take the descriptions from tuple and create sockets for those in socks
351
* socks is a socketstack from a bNodeTypeInfo
353
static int pysockets_to_blendersockets(PyObject *tuple, bNodeSocketType **socks, int stage, int limit) {
354
int len = 0, a = 0, pos = 0, retval = 0;
356
BPy_NodeSocket *pysock;
357
bNodeSocketType *nsocks = NULL;
359
if (BTST2(stage, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST))
360
return 0; /* already has sockets */
362
len = PyTuple_Size(tuple);
364
if (len >= MAX_SOCKET) {
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);
373
nsocks = MEM_callocN(sizeof(bNodeSocketType)*(len+1), "bNodeSocketType in Node.c");
375
for (pos = 0, a = 0; pos< len; pos++, a++) {
376
pysock = (BPy_NodeSocket *)PyTuple_GetItem(tuple, pos);/*borrowed*/
378
if (!BPy_NodeSocket_Check(pysock)) {
379
PyErr_SetString(PyExc_AttributeError, "expected a sequence of node sockets");
384
stype = pysock->type;
386
nsocks[a].type = stype;
387
nsocks[a].limit = limit;
389
nsocks[a].name = BLI_strdupn(pysock->name, NODE_MAXSTR);
391
nsocks[a].min = pysock->min;
392
nsocks[a].max = pysock->max;
394
if (stype > SOCK_VALUE) {
395
float *vec = pysock->val;
397
nsocks[a].val1 = vec[0];
398
nsocks[a].val2 = vec[1];
399
nsocks[a].val3 = vec[2];
401
if (stype == SOCK_RGBA)
402
nsocks[a].val4 = vec[3];
404
else /* SOCK_VALUE */
405
nsocks[a].val1 = pysock->val[0];
415
static void NodeSocketLists_dealloc(BPy_NodeSocketLists *self)
417
Py_DECREF(self->input);
418
Py_DECREF(self->output);
419
self->ob_type->tp_free((PyObject *)self);
422
static PyObject *Map_socketdef_getter(BPy_NodeSocketLists *self, void *closure)
424
PyObject *sockets = NULL;
426
switch (GET_INT_FROM_POINTER(closure)) {
427
case 'I': /* inputs */
428
Py_INCREF(self->input);
429
sockets = self->input;
431
case 'O': /* outputs */
432
Py_INCREF(self->output);
433
sockets = self->output;
436
fprintf(stderr, "DEBUG pynodes: wrong option in Map_socketdef_getter\n");
445
static int Map_socketdef(BPy_NodeSocketLists *self, PyObject *args, void *closure)
448
PyObject *tuple = NULL;
454
fprintf(stderr,"DEBUG pynodes: No bNode in BPy_Node (Map_socketdef)\n");
458
if(BTST2(node->custom1, NODE_DYNAMIC_READY, NODE_DYNAMIC_ADDEXIST))
461
switch(GET_INT_FROM_POINTER(closure)) {
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);
471
return(EXPP_ReturnIntError( PyExc_AttributeError, "INPUT must be a List of Lists or Tuples"));
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;
484
return(EXPP_ReturnIntError( PyExc_AttributeError, "OUTPUT must be a List of Lists or Tuples"));
489
fprintf(stderr,"DEBUG pynodes: got no list in Map_socketdef\n");
494
node->custom1 = BSET(node->custom1, NODE_DYNAMIC_ERROR);
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)",
504
{"i" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef,
505
"Set this node's input sockets (list of lists or tuples)",
507
{"output", (getter)Map_socketdef_getter, (setter)Map_socketdef,
508
"Set this node's output sockets (list of lists or tuples)",
510
{"o" /*alias*/, (getter)Map_socketdef_getter, (setter)Map_socketdef,
511
"Set this node's output sockets (list of lists or tuples)",
513
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
516
PyTypeObject NodeSocketLists_Type = {
517
PyObject_HEAD_INIT( NULL ) /* required py macro */
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 */
524
/* Methods to implement standard operations */
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; */
533
/* Method suites for standard classes */
535
NULL, /* PyNumberMethods *tp_as_number; */
536
NULL, /* PySequenceMethods *tp_as_sequence; */
537
NULL, /* PyMappingMethods *tp_as_mapping; */
539
/* More standard operations (here for binary compatibility) */
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; */
547
/* Functions to access object as input/input buffer */
548
NULL, /* PyBufferProcs *tp_as_buffer; */
550
/*** Flags to define presence of optional/expanded features ***/
551
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
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; */
558
/* delete references to contained objects */
559
NULL, /* inquiry tp_clear; */
561
/*** Assigned meaning in release 2.1 ***/
562
/*** rich comparisons ***/
563
NULL, /* richcmpfunc tp_richcompare; */
565
/*** weak reference enabler ***/
566
0, /* long tp_weaklistoffset; */
568
/*** Added in release 2.2 ***/
570
0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
571
0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
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; */
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);
606
/***************************************/
608
static int Sockinmap_len ( BPy_SockMap * self) {
609
bNode *node = self->node;
615
tinfo = node->typeinfo;
617
if (BNTST(node->custom1, NODE_DYNAMIC_READY)) return 0;
619
if (tinfo && tinfo->inputs) {
620
while(self->node->typeinfo->inputs[a].type!=-1)
626
static int sockinmap_has_key( BPy_SockMap *self, char *strkey) {
627
bNode *node = self->node;
631
if (!node || !strkey) return -1;
633
tinfo = node->typeinfo;
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)) {
646
PyObject *Sockinmap_subscript(BPy_SockMap *self, PyObject *pyidx) {
650
return EXPP_ReturnPyObjError(PyExc_RuntimeError, "no access to Blender node data!");
652
if (PyString_Check(pyidx)) {
653
idx = sockinmap_has_key(self, PyString_AsString(pyidx));
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");
661
else if (PySlice_Check(pyidx)) {
662
return EXPP_ReturnPyObjError(PyExc_ValueError, "slices not implemented");
664
return EXPP_ReturnPyObjError(PyExc_IndexError, "index must be an int or a string");
667
if(idx<0) { /* we're not as nice as Python */
668
return EXPP_ReturnPyObjError(PyExc_IndexError, "invalid socket index");
671
switch(self->node->typeinfo->inputs[idx].type) {
673
return Py_BuildValue("f", self->stack[idx]->vec[0]);
676
return Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
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]);
689
static PyObject *Sockinmap_getAttr(BPy_SockMap *self, char *attr)
691
PyObject *pyob = NULL;
694
idx = sockinmap_has_key(self, attr);
697
return EXPP_ReturnPyObjError(PyExc_AttributeError, "unknown input socket name");
699
switch(self->node->typeinfo->inputs[idx].type) {
701
pyob = Py_BuildValue("f", self->stack[idx]->vec[0]);
704
pyob = Py_BuildValue("(fff)", self->stack[idx]->vec[0], self->stack[idx]->vec[1], self->stack[idx]->vec[2]);
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]);
717
static PyMappingMethods Sockinmap_as_mapping = {
718
( inquiry ) Sockinmap_len, /* mp_length */
719
( binaryfunc ) Sockinmap_subscript, /* mp_subscript */
720
( objobjargproc ) 0 /* mp_ass_subscript */
723
PyTypeObject SockInMap_Type = {
724
PyObject_HEAD_INIT( NULL ) /* required py macro */
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 */
731
/* Methods to implement standard operations */
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; */
740
/* Method suites for standard classes */
742
NULL, /* PyNumberMethods *tp_as_number; */
743
NULL, /* PySequenceMethods *tp_as_sequence; */
744
&Sockinmap_as_mapping, /* PyMappingMethods *tp_as_mapping; */
746
/* More standard operations (here for binary compatibility) */
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; */
754
/* Functions to access object as input/output buffer */
755
NULL, /* PyBufferProcs *tp_as_buffer; */
757
/*** Flags to define presence of optional/expanded features ***/
758
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
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; */
765
/* delete references to contained objects */
766
NULL, /* inquiry tp_clear; */
768
/*** Assigned meaning in release 2.1 ***/
769
/*** rich comparisons ***/
770
NULL, /* richcmpfunc tp_richcompare; */
772
/*** weak reference enabler ***/
773
0, /* long tp_weaklistoffset; */
775
/*** Added in release 2.2 ***/
777
0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
778
0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
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; */
805
static int Sockoutmap_len ( BPy_SockMap * self) {
806
bNode *node = self->node;
812
tinfo = node->typeinfo;
814
if (tinfo && tinfo->outputs) {
815
while(self->node->typeinfo->outputs[a].type!=-1)
821
static int sockoutmap_has_key(BPy_SockMap *self, char *strkey) {
822
bNode *node = self->node;
826
if (!node) return -1;
828
tinfo = node->typeinfo;
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)) {
841
static int Sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObject *value) {
842
int i, idx, len, type, wanted_len = 0;
847
return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
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");
854
else if (PyString_Check(pyidx)) {
855
idx = sockoutmap_has_key(self, PyString_AsString(pyidx));
857
else if (PySlice_Check(pyidx)) {
858
return EXPP_ReturnIntError(PyExc_ValueError, "slices not yet implemented");
860
return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
864
return EXPP_ReturnIntError(PyExc_IndexError, "index must be a positive int or a string");
866
type = self->node->typeinfo->outputs[idx].type;
868
if (type == SOCK_VALUE) {
869
val = PyNumber_Float(value);
871
return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
872
self->stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
876
val = PySequence_Fast(value, "expected a numeric tuple or list");
879
len = PySequence_Fast_GET_SIZE(val);
881
if (type == SOCK_VECTOR) {
883
} else { /* SOCK_RGBA */
887
if (len != wanted_len) {
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);
894
for (i = 0; i < len; i++) {
895
items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
896
if (!PyNumber_Check(items[i])) {
898
return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
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]);
906
if (type == SOCK_RGBA)
907
self->stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
915
static int sockoutmap_set_attr(bNodeStack **stack, short type, short idx, PyObject *value)
920
short len, wanted_len;
922
if (!stack || !stack[idx]) return 0; /* no MaterialNode */
924
if (type == SOCK_VALUE) {
925
val = PyNumber_Float(value);
927
return EXPP_ReturnIntError(PyExc_AttributeError, "expected a float value");
928
stack[idx]->vec[0] = (float)PyFloat_AsDouble(val);
932
val = PySequence_Fast(value, "expected a numeric tuple or list");
935
len = PySequence_Fast_GET_SIZE(val);
937
if (type == SOCK_VECTOR) {
939
} else { /* SOCK_RGBA */
943
if (len != wanted_len) {
945
PyErr_SetString(PyExc_AttributeError, "wrong number of items in list or tuple");
946
fprintf(stderr, "\nExpected %d numeric values, got %d.", wanted_len, len);
950
for (i = 0; i < len; i++) {
951
items[i] = PySequence_Fast_GET_ITEM(val, i); /* borrowed */
952
if (!PyNumber_Check(items[i])) {
954
return EXPP_ReturnIntError(PyExc_AttributeError, "expected a *numeric* tuple or list");
958
stack[idx]->vec[0] = (float)PyFloat_AsDouble(items[0]);
959
stack[idx]->vec[1] = (float)PyFloat_AsDouble(items[1]);
960
stack[idx]->vec[2] = (float)PyFloat_AsDouble(items[2]);
962
if (type == SOCK_RGBA)
963
stack[idx]->vec[3] = (float)PyFloat_AsDouble(items[3]);
971
static int Sockoutmap_setAttr(BPy_SockMap *self, char *name, PyObject *value) {
975
return EXPP_ReturnIntError(PyExc_RuntimeError, "no access to Blender node data!");
977
idx = sockoutmap_has_key(self, name);
980
return EXPP_ReturnIntError(PyExc_AttributeError, "unknown output socket name");
982
type = self->node->typeinfo->outputs[idx].type;
984
return sockoutmap_set_attr(self->stack, type, idx, value);
987
static PyMappingMethods Sockoutmap_as_mapping = {
988
( inquiry ) Sockoutmap_len, /* mp_length */
989
( binaryfunc ) 0, /* mp_subscript */
990
( objobjargproc ) Sockoutmap_assign_subscript /* mp_ass_subscript */
993
PyTypeObject SockOutMap_Type = {
994
PyObject_HEAD_INIT( NULL ) /* required py macro */
996
/* For printing, in format "<module>.<name>" */
997
"Blender.Node.OutputSockets", /* char *tp_name; */
998
sizeof( BPy_SockMap ), /* int tp_basicsize; */
999
0, /* tp_itemsize; For allocation */
1001
/* Methods to implement standard operations */
1003
NULL,/* destructor tp_dealloc; */
1004
NULL, /* printfunc tp_print; */
1005
NULL, /* getattrfunc tp_getattr; */
1006
(setattrfunc) Sockoutmap_setAttr,/* setattrfunc tp_setattr; */
1007
NULL, /* cmpfunc tp_compare; */
1008
NULL, /* reprfunc tp_repr; */
1010
/* Method suites for standard classes */
1012
NULL, /* PyNumberMethods *tp_as_number; */
1013
NULL, /* PySequenceMethods *tp_as_sequence; */
1014
&Sockoutmap_as_mapping, /* PyMappingMethods *tp_as_mapping; */
1016
/* More standard operations (here for binary compatibility) */
1018
NULL, /* hashfunc tp_hash; */
1019
NULL, /* ternaryfunc tp_call; */
1020
NULL, /* reprfunc tp_str; */
1021
NULL, /* getattrofunc tp_getattro; */
1022
NULL, /* setattrofunc tp_setattro; */
1024
/* Functions to access object as input/output buffer */
1025
NULL, /* PyBufferProcs *tp_as_buffer; */
1027
/*** Flags to define presence of optional/expanded features ***/
1028
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1030
NULL, /* char *tp_doc; Documentation string */
1031
/*** Assigned meaning in release 2.0 ***/
1032
/* call function for all accessible objects */
1033
NULL, /* traverseproc tp_traverse; */
1035
/* delete references to contained objects */
1036
NULL, /* inquiry tp_clear; */
1038
/*** Assigned meaning in release 2.1 ***/
1039
/*** rich comparisons ***/
1040
NULL, /* richcmpfunc tp_richcompare; */
1042
/*** weak reference enabler ***/
1043
0, /* long tp_weaklistoffset; */
1045
/*** Added in release 2.2 ***/
1047
0, //( getiterfunc) MVertSeq_getIter, /* getiterfunc tp_iter; */
1048
0, //( iternextfunc ) MVertSeq_nextIter, /* iternextfunc tp_iternext; */
1050
/*** Attribute descriptor and subclassing stuff ***/
1051
0, //BPy_MVertSeq_methods, /* struct PyMethodDef *tp_methods; */
1052
NULL, /* struct PyMemberDef *tp_members; */
1053
NULL, /* struct PyGetSetDef *tp_getset; */
1054
NULL, /* struct _typeobject *tp_base; */
1055
NULL, /* PyObject *tp_dict; */
1056
NULL, /* descrgetfunc tp_descr_get; */
1057
NULL, /* descrsetfunc tp_descr_set; */
1058
0, /* long tp_dictoffset; */
1059
NULL, /* initproc tp_init; */
1060
NULL, /* allocfunc tp_alloc; */
1061
NULL, /* newfunc tp_new; */
1062
/* Low-level free-memory routine */
1063
NULL, /* freefunc tp_free; */
1064
/* For PyObject_IS_GC */
1065
NULL, /* inquiry tp_is_gc; */
1066
NULL, /* PyObject *tp_bases; */
1067
/* method resolution order */
1068
NULL, /* PyObject *tp_mro; */
1069
NULL, /* PyObject *tp_cache; */
1070
NULL, /* PyObject *tp_subclasses; */
1071
NULL, /* PyObject *tp_weaklist; */
1076
static BPy_SockMap *Node_CreateInputMap(bNode *node, bNodeStack **stack) {
1077
BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockInMap_Type);
1083
static PyObject *Node_GetInputMap(BPy_Node *self) {
1084
BPy_SockMap *inmap = Node_CreateInputMap(self->node, self->in);
1085
return (PyObject *)(inmap);
1088
#define SURFACEVIEWVECTOR 0
1089
#define VIEWNORMAL 1
1090
#define SURFACENORMAL 2
1091
#define GLOBALTEXTURE 3
1095
#define SPECULAR_COLOR 7
1096
#define MIRROR_COLOR 8
1097
#define AMBIENT_COLOR 9
1104
#define SURFACE_D 30
1105
#define TEXTURE_D 31
1106
#define GLOBALTEXTURE_D 32
1107
#define REFLECTION_D 33
1110
#define REFRACT_D 36
1113
/* MACRO time: defining shi getters */
1115
/* a couple checks that we can redefine to nothing for a tiny performance
1118
#define SHI_CHECK_SHI\
1120
return EXPP_ReturnPyObjError(PyExc_RuntimeError,\
1121
"no shade input data!");
1123
#define SHI_CHECK_OB\
1125
return EXPP_ReturnPyObjError(PyExc_RuntimeError,\
1126
"couldn't create vector object!");
1128
/* for shi getters: */
1130
#define SHI_GETATTR_f(name, var)\
1131
static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1133
PyObject *ob = NULL;\
1137
ob = PyFloat_FromDouble((double)(self->shi->var));\
1144
#define SHI_GETATTR_fvec(name, var, len)\
1145
static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1147
PyObject *ob = NULL;\
1151
ob = newVectorObject(self->shi->var, len, Py_NEW);\
1158
#define SHI_GETATTR_2fvec(name, v1, v2, len)\
1159
static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1161
PyObject *ob = NULL;\
1162
PyObject *tuple = NULL;\
1166
tuple = PyTuple_New(2);\
1168
ob = newVectorObject(self->shi->v1, len, Py_NEW);\
1169
PyTuple_SET_ITEM(tuple, 0, ob);\
1171
ob = newVectorObject(self->shi->v2, len, Py_NEW);\
1172
PyTuple_SET_ITEM(tuple, 1, ob);\
1177
#define SHI_GETATTR_3f(name, v1, v2, v3)\
1178
static PyObject *ShadeInput_get##name(BPy_ShadeInput *self, void *unused)\
1180
PyObject *ob = NULL;\
1185
vec[0] = self->shi->v1;\
1186
vec[1] = self->shi->v2;\
1187
vec[2] = self->shi->v3;\
1189
ob = newVectorObject(vec, 3, Py_NEW);\
1198
SHI_GETATTR_f(Ambient, amb);
1199
SHI_GETATTR_f(Emit, emit);
1200
SHI_GETATTR_f(Strand, strandco);
1201
SHI_GETATTR_f(Stress, stress);
1205
SHI_GETATTR_3f(Color, r, g, b)
1206
SHI_GETATTR_3f(ColorSpecular, specr, specg, specb)
1207
SHI_GETATTR_3f(ColorMirror, mirr, mirg, mirb)
1208
SHI_GETATTR_3f(ColorAmbient, ambr, ambg, ambb)
1212
SHI_GETATTR_fvec(SurfaceViewVector, view, 3)
1213
SHI_GETATTR_fvec(SurfaceNormal, facenor, 3)
1214
SHI_GETATTR_fvec(ViewNormal, vn, 3)
1215
SHI_GETATTR_fvec(TextureGlobal, gl, 3)
1216
SHI_GETATTR_fvec(Texture, lo, 3)
1217
SHI_GETATTR_fvec(Displace, displace, 3)
1218
SHI_GETATTR_fvec(Tangent, tang, 3)
1220
/* two float vectors */
1222
SHI_GETATTR_2fvec(SurfaceD, dxco, dyco, 3)
1223
SHI_GETATTR_2fvec(TextureD, dxlo, dylo, 3)
1224
SHI_GETATTR_2fvec(TextureGlobalD, dxgl, dygl, 3)
1225
SHI_GETATTR_2fvec(ReflectionD, dxref, dyref, 3)
1226
SHI_GETATTR_2fvec(NormalD, dxno, dyno, 3)
1227
SHI_GETATTR_2fvec(StickyD, dxsticky, dysticky, 3)
1228
SHI_GETATTR_2fvec(RefractD, dxrefract, dyrefract, 3)
1230
/* single cases (for now), not macros: */
1232
static PyObject *ShadeInput_getPixel(BPy_ShadeInput *self, void *unused)
1234
PyObject *ob = NULL;
1238
ob = Py_BuildValue("(ii)", self->shi->xs, self->shi->ys);
1245
static PyObject *ShadeInput_getStrandD(BPy_ShadeInput *self, void *unused)
1247
PyObject *ob = NULL;
1252
vec[0] = self->shi->dxstrand;
1253
vec[1] = self->shi->dystrand;
1255
ob = newVectorObject(vec, 2, Py_NEW);
1262
static BPy_SockMap *Node_CreateOutputMap(bNode *node, bNodeStack **stack) {
1263
BPy_SockMap *map = PyObject_NEW(BPy_SockMap, &SockOutMap_Type);
1269
static PyObject *Node_GetOutputMap(BPy_Node *self) {
1270
BPy_SockMap *outmap = Node_CreateOutputMap(self->node, self->out);
1271
return (PyObject *)outmap;
1274
static PyObject *Node_GetShi(BPy_Node *self) {
1275
BPy_ShadeInput *shi = ShadeInput_CreatePyObject(self->shi);
1276
return (PyObject *)shi;
1279
static PyObject *node_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1282
self = type->tp_alloc(type, 1);
1286
static int node_init(BPy_Node *self, PyObject *args, PyObject *kwds)
1291
static PyGetSetDef BPy_Node_getseters[] = {
1293
(getter)Node_GetInputMap, (setter)NULL,
1294
"Get the input sockets mapping (dictionary)",
1297
(getter)Node_GetInputMap, (setter)NULL,
1298
"Get the input sockets mapping (dictionary)",
1301
(getter)Node_GetOutputMap, (setter)NULL,
1302
"Get the output sockets mapping (dictionary)",
1305
(getter)Node_GetOutputMap, (setter)NULL,
1306
"Get the output sockets mapping (dictionary)",
1309
(getter)Node_GetShi, (setter)NULL,
1310
"Get the Shade Input data (ShadeInput)",
1313
(getter)Node_GetShi, (setter)NULL,
1314
"Get the Shade Input data (ShadeInput)",
1316
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
1319
static PyGetSetDef BPy_ShadeInput_getseters[] = {
1321
(getter)ShadeInput_getTexture, (setter)NULL,
1322
"Get the current texture coordinate (3-vector)", NULL},
1324
(getter)ShadeInput_getTextureGlobal, (setter)NULL,
1325
"Get the current global texture coordinate (3-vector)", NULL},
1327
(getter)ShadeInput_getSurfaceNormal, (setter)NULL,
1328
"Get the current surface normal (3-vector)", NULL},
1330
(getter)ShadeInput_getViewNormal, (setter)NULL,
1331
"Get the current view normal (3-vector)", NULL},
1332
{"surfaceViewVector",
1333
(getter)ShadeInput_getSurfaceViewVector, (setter)NULL,
1334
"Get the vector pointing to the viewpoint from the point being shaded (3-vector)", NULL},
1336
(getter)ShadeInput_getPixel, (setter)NULL,
1337
"Get the x,y-coordinate for the pixel rendered (3-vector)", NULL},
1339
(getter)ShadeInput_getColor, (setter)NULL,
1340
"Get the color for the point being shaded (3-vector)", NULL},
1342
(getter)ShadeInput_getColorSpecular, (setter)NULL,
1343
"Get the specular color for the point being shaded (3-vector)", NULL},
1345
(getter)ShadeInput_getColorMirror, (setter)NULL,
1346
"Get the mirror color for the point being shaded (3-vector)", NULL},
1348
(getter)ShadeInput_getColorAmbient, (setter)NULL,
1349
"Get the ambient color for the point being shaded (3-vector)", NULL},
1351
(getter)ShadeInput_getAmbient, (setter)NULL,
1352
"Get the ambient factor for the point being shaded (float)", NULL},
1354
(getter)ShadeInput_getEmit, (setter)NULL,
1355
"Get the emit factor for the point being shaded (float)", NULL},
1357
(getter)ShadeInput_getDisplace, (setter)NULL,
1358
"Get the displace vector for the point being shaded (3-vector)", NULL},
1360
(getter)ShadeInput_getStrand, (setter)NULL,
1361
"Get the strand factor(float)", NULL},
1363
(getter)ShadeInput_getStress, (setter)NULL,
1364
"Get the stress factor(float)", NULL},
1366
(getter)ShadeInput_getTangent, (setter)NULL,
1367
"Get the tangent vector (3-vector)", NULL},
1369
(getter)ShadeInput_getSurfaceD, (setter)NULL,
1370
"Get the surface d (tuple with pair of 3-vectors)", NULL},
1372
(getter)ShadeInput_getTextureD, (setter)NULL,
1373
"Get the texture d (tuple with pair of 3-vectors)", NULL},
1375
(getter)ShadeInput_getTextureGlobalD, (setter)NULL,
1376
"Get the global texture d (tuple with pair of 3-vectors)", NULL},
1378
(getter)ShadeInput_getReflectionD, (setter)NULL,
1379
"Get the reflection d (tuple with pair of 3-vectors)", NULL},
1381
(getter)ShadeInput_getNormalD, (setter)NULL,
1382
"Get the normal d (tuple with pair of 3-vectors)", NULL},
1384
(getter)ShadeInput_getStickyD, (setter)NULL,
1385
"Get the sticky d (tuple with pair of 3-vectors)", NULL},
1387
(getter)ShadeInput_getRefractD, (setter)NULL,
1388
"Get the refract d (tuple with pair of 3-vectors)", NULL},
1390
(getter)ShadeInput_getStrandD, (setter)NULL,
1391
"Get the strand d (2-vector)", NULL},
1392
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */
1395
PyTypeObject Node_Type = {
1396
PyObject_HEAD_INIT( NULL ) /* required py macro */
1398
/* For printing, in format "<module>.<name>" */
1399
"Blender.Node.Scripted", /* char *tp_name; */
1400
sizeof( BPy_Node ), /* int tp_basicsize; */
1401
0, /* tp_itemsize; For allocation */
1403
/* Methods to implement standard operations */
1405
NULL,/* destructor tp_dealloc; */
1406
NULL, /* printfunc tp_print; */
1407
NULL /*( getattrfunc ) PyObject_GenericGetAttr*/, /* getattrfunc tp_getattr; */
1408
NULL /*( setattrfunc ) PyObject_GenericSetAttr*/, /* setattrfunc tp_setattr; */
1409
( cmpfunc ) Node_compare, /* cmpfunc tp_compare; */
1410
( reprfunc ) Node_repr, /* reprfunc tp_repr; */
1412
/* Method suites for standard classes */
1414
NULL, /* PyNumberMethods *tp_as_number; */
1415
NULL, /* PySequenceMethods *tp_as_sequence; */
1416
NULL, /* PyMappingMethods *tp_as_mapping; */
1418
/* More standard operations (here for binary compatibility) */
1420
NULL, /* hashfunc tp_hash; */
1421
NULL, /* ternaryfunc tp_call; */
1422
NULL, /* reprfunc tp_str; */
1423
NULL, /* getattrofunc tp_getattro; */
1424
NULL, /* setattrofunc tp_setattro; */
1426
/* Functions to access object as input/output buffer */
1427
NULL, /* PyBufferProcs *tp_as_buffer; */
1429
/*** Flags to define presence of optional/expanded features ***/
1430
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* long tp_flags; */
1432
NULL, /* char *tp_doc; Documentation string */
1433
/*** Assigned meaning in release 2.0 ***/
1434
/* call function for all accessible objects */
1435
NULL, /* traverseproc tp_traverse; */
1437
/* delete references to contained objects */
1438
NULL, /* inquiry tp_clear; */
1440
/*** Assigned meaning in release 2.1 ***/
1441
/*** rich comparisons ***/
1442
NULL, /* richcmpfunc tp_richcompare; */
1444
/*** weak reference enabler ***/
1445
0, /* long tp_weaklistoffset; */
1447
/*** Added in release 2.2 ***/
1449
NULL, /* getiterfunc tp_iter; */
1450
NULL, /* iternextfunc tp_iternext; */
1452
/*** Attribute descriptor and subclassing stuff ***/
1453
NULL, /*BPy_Node_methods,*/ /* struct PyMethodDef *tp_methods; */
1454
NULL, /* struct PyMemberDef *tp_members; */
1455
BPy_Node_getseters, /* struct PyGetSetDef *tp_getset; */
1456
NULL, /* struct _typeobject *tp_base; */
1457
NULL, /* PyObject *tp_dict; */
1458
NULL, /* descrgetfunc tp_descr_get; */
1459
NULL, /* descrsetfunc tp_descr_set; */
1460
0, /* long tp_dictoffset; */
1461
(initproc)node_init, /* initproc tp_init; */
1462
/*PyType_GenericAlloc*/NULL, /* allocfunc tp_alloc; */
1463
node_new, /* newfunc tp_new; */
1464
/* Low-level free-memory routine */
1465
NULL, /* freefunc tp_free; */
1466
/* For PyObject_IS_GC */
1467
NULL, /* inquiry tp_is_gc; */
1468
NULL, /* PyObject *tp_bases; */
1469
/* method resolution order */
1470
NULL, /* PyObject *tp_mro; */
1471
NULL, /* PyObject *tp_cache; */
1472
NULL, /* PyObject *tp_subclasses; */
1473
NULL, /* PyObject *tp_weaklist; */
1477
PyTypeObject ShadeInput_Type = {
1478
PyObject_HEAD_INIT( NULL ) /* required py macro */
1480
/* For printing, in format "<module>.<name>" */
1481
"Blender.Node.ShadeInput", /* char *tp_name; */
1482
sizeof( BPy_ShadeInput ), /* int tp_basicsize; */
1483
0, /* tp_itemsize; For allocation */
1485
/* Methods to implement standard operations */
1487
NULL,/* destructor tp_dealloc; */
1488
NULL, /* printfunc tp_print; */
1489
NULL, /* getattrfunc tp_getattr; */
1490
NULL, /* setattrfunc tp_setattr; */
1491
( cmpfunc ) ShadeInput_compare, /* cmpfunc tp_compare; */
1492
( reprfunc ) ShadeInput_repr, /* reprfunc tp_repr; */
1494
/* Method suites for standard classes */
1496
NULL, /* PyNumberMethods *tp_as_number; */
1497
NULL, /* PySequenceMethods *tp_as_sequence; */
1498
NULL, /* PyMappingMethods *tp_as_mapping; */
1500
/* More standard operations (here for binary compatibility) */
1502
NULL, /* hashfunc tp_hash; */
1503
NULL, /* ternaryfunc tp_call; */
1504
NULL, /* reprfunc tp_str; */
1505
NULL, /* getattrofunc tp_getattro; */
1506
NULL, /* setattrofunc tp_setattro; */
1508
/* Functions to access object as input/output buffer */
1509
NULL, /* PyBufferProcs *tp_as_buffer; */
1511
/*** Flags to define presence of optional/expanded features ***/
1512
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1514
NULL, /* char *tp_doc; Documentation string */
1515
/*** Assigned meaning in release 2.0 ***/
1516
/* call function for all accessible objects */
1517
NULL, /* traverseproc tp_traverse; */
1519
/* delete references to contained objects */
1520
NULL, /* inquiry tp_clear; */
1522
/*** Assigned meaning in release 2.1 ***/
1523
/*** rich comparisons ***/
1524
NULL, /* richcmpfunc tp_richcompare; */
1526
/*** weak reference enabler ***/
1527
0, /* long tp_weaklistoffset; */
1529
/*** Added in release 2.2 ***/
1531
NULL, /* getiterfunc tp_iter; */
1532
NULL, /* iternextfunc tp_iternext; */
1534
/*** Attribute descriptor and subclassing stuff ***/
1535
NULL, /*BPy_Node_methods,*/ /* struct PyMethodDef *tp_methods; */
1536
NULL, /* struct PyMemberDef *tp_members; */
1537
BPy_ShadeInput_getseters, /* struct PyGetSetDef *tp_getset; */
1538
NULL, /* struct _typeobject *tp_base; */
1539
NULL, /* PyObject *tp_dict; */
1540
NULL, /* descrgetfunc tp_descr_get; */
1541
NULL, /* descrsetfunc tp_descr_set; */
1542
0, /* long tp_dictoffset; */
1543
NULL, /* initproc tp_init; */
1544
NULL, /* allocfunc tp_alloc; */
1545
NULL, /* newfunc tp_new; */
1546
/* Low-level free-memory routine */
1547
NULL, /* freefunc tp_free; */
1548
/* For PyObject_IS_GC */
1549
NULL, /* inquiry tp_is_gc; */
1550
NULL, /* PyObject *tp_bases; */
1551
/* method resolution order */
1552
NULL, /* PyObject *tp_mro; */
1553
NULL, /* PyObject *tp_cache; */
1554
NULL, /* PyObject *tp_subclasses; */
1555
NULL, /* PyObject *tp_weaklist; */
1559
/* Initialise Node module */
1560
PyObject *Node_Init(void)
1562
PyObject *submodule;
1564
if( PyType_Ready( &Node_Type ) < 0 )
1566
if( PyType_Ready( &ShadeInput_Type ) < 0 )
1568
if( PyType_Ready( &NodeSocket_Type ) < 0 )
1570
if( PyType_Ready( &NodeSocketLists_Type ) < 0 )
1572
if( PyType_Ready( &SockInMap_Type ) < 0 )
1574
if( PyType_Ready( &SockOutMap_Type ) < 0 )
1576
submodule = Py_InitModule3( "Blender.Node", NULL, "");
1578
PyModule_AddIntConstant(submodule, "VALUE", SOCK_VALUE);
1579
PyModule_AddIntConstant(submodule, "RGBA", SOCK_RGBA);
1580
PyModule_AddIntConstant(submodule, "VECTOR", SOCK_VECTOR);
1582
Py_INCREF(&NodeSocket_Type);
1583
PyModule_AddObject(submodule, "Socket", (PyObject *)&NodeSocket_Type);
1585
Py_INCREF(&Node_Type);
1586
PyModule_AddObject(submodule, "Scripted", (PyObject *)&Node_Type);
1591
static int Node_compare(BPy_Node *a, BPy_Node *b)
1593
bNode *pa = a->node, *pb = b->node;
1594
return (pa == pb) ? 0 : -1;
1597
static PyObject *Node_repr(BPy_Node *self)
1599
return PyString_FromFormat( "[Node \"%s\"]",
1600
self->node ? self->node->id->name+2 : "empty node");
1603
BPy_Node *Node_CreatePyObject(bNode *node)
1607
pynode = (BPy_Node *)PyObject_NEW(BPy_Node, &Node_Type);
1609
fprintf(stderr,"Couldn't create BPy_Node object\n");
1610
return (BPy_Node *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_Node object"));
1613
pynode->node = node;
1618
int pytype_is_pynode(PyObject *pyob)
1620
return PyObject_TypeCheck(pyob, &Node_Type);
1623
void InitNode(BPy_Node *self, bNode *node) {
1627
bNode *Node_FromPyObject(PyObject *pyobj)
1629
return ((BPy_Node *)pyobj)->node;
1632
void Node_SetStack(BPy_Node *self, bNodeStack **stack, int type)
1634
if(type == NODE_INPUTSTACK) {
1636
} else if(type == NODE_OUTPUTSTACK) {
1641
void Node_SetShi(BPy_Node *self, ShadeInput *shi)
1646
/*********************/
1648
static int ShadeInput_compare(BPy_ShadeInput *a, BPy_ShadeInput *b)
1650
ShadeInput *pa = a->shi, *pb = b->shi;
1651
return (pa == pb) ? 0 : -1;
1654
static PyObject *ShadeInput_repr(BPy_ShadeInput *self)
1656
return PyString_FromFormat( "[ShadeInput at \"%p\"]", self);
1659
BPy_ShadeInput *ShadeInput_CreatePyObject(ShadeInput *shi)
1661
BPy_ShadeInput *pyshi;
1663
pyshi = (BPy_ShadeInput *)PyObject_NEW(BPy_ShadeInput, &ShadeInput_Type);
1665
fprintf(stderr,"Couldn't create BPy_ShadeInput object\n");
1666
return (BPy_ShadeInput *)(EXPP_ReturnPyObjError(PyExc_MemoryError, "couldn't create BPy_ShadeInput object"));