2
* $Id: IDProp.c 27639 2010-03-21 01:14:04Z gsrb3d $
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
* Contributor(s): Joseph Eagar, Campbell Barton
23
* ***** END GPL LICENSE BLOCK *****
26
#include "BKE_idprop.h"
28
#include "MEM_guardedalloc.h"
30
/*** Function to wrap ID properties ***/
31
PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent);
33
extern PyTypeObject IDArray_Type;
34
extern PyTypeObject IDGroup_Iter_Type;
36
/*********************** ID Property Main Wrapper Stuff ***************/
38
PyObject *IDGroup_repr( BPy_IDProperty *self )
40
return PyUnicode_FromFormat( "<bpy ID property from \"%s\">", self->id->name);
43
extern PyTypeObject IDGroup_Type;
45
PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
47
switch ( prop->type ) {
49
return PyUnicode_FromString( prop->data.pointer );
51
return PyLong_FromLong( (long)prop->data.val );
53
return PyFloat_FromDouble( (double)(*(float*)(&prop->data.val)) );
55
return PyFloat_FromDouble( (*(double*)(&prop->data.val)) );
59
BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &IDGroup_Type);
62
return (PyObject*) group;
66
BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &IDArray_Type);
69
return (PyObject*) array;
71
case IDP_IDPARRAY: /* this could be better a internal type */
73
PyObject *seq = PyList_New(prop->len), *wrap;
74
IDProperty *array= IDP_IDPArray(prop);
78
PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len);
82
for (i=0; i<prop->len; i++) {
83
wrap= BPy_IDGroup_WrapData(id, array++);
85
if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */
88
PyList_SET_ITEM(seq, i, wrap);
93
/* case IDP_IDPARRAY: TODO */
98
int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject *value)
100
switch (prop->type) {
104
if (!PyUnicode_Check(value)) {
105
PyErr_SetString(PyExc_TypeError, "expected a string!");
109
st = _PyUnicode_AsString(value);
110
IDP_ResizeArray(prop, strlen(st)+1);
111
strcpy(prop->data.pointer, st);
117
int ivalue= PyLong_AsSsize_t(value);
118
if (ivalue==-1 && PyErr_Occurred()) {
119
PyErr_SetString(PyExc_TypeError, "expected an int type");
122
prop->data.val = ivalue;
127
float fvalue= (float)PyFloat_AsDouble(value);
128
if (fvalue==-1 && PyErr_Occurred()) {
129
PyErr_SetString(PyExc_TypeError, "expected a float");
132
*(float*)&self->prop->data.val = fvalue;
137
double dvalue= PyFloat_AsDouble(value);
138
if (dvalue==-1 && PyErr_Occurred()) {
139
PyErr_SetString(PyExc_TypeError, "expected a float");
142
*(double*)&self->prop->data.val = dvalue;
146
PyErr_SetString(PyExc_AttributeError, "attempt to set read-only attribute!");
152
PyObject *BPy_IDGroup_GetName(BPy_IDProperty *self, void *bleh)
154
return PyUnicode_FromString(self->prop->name);
157
static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *bleh)
160
if (!PyUnicode_Check(value)) {
161
PyErr_SetString(PyExc_TypeError, "expected a string!");
165
st = _PyUnicode_AsString(value);
166
if (strlen(st) >= MAX_IDPROP_NAME) {
167
PyErr_SetString(PyExc_TypeError, "string length cannot exceed 31 characters!");
171
strcpy(self->prop->name, st);
176
static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self)
178
return PyLong_FromSsize_t(self->prop->type);
182
static PyGetSetDef BPy_IDGroup_getseters[] = {
184
(getter)BPy_IDGroup_GetName, (setter)BPy_IDGroup_SetName,
185
"The name of this Group.",
187
{NULL, NULL, NULL, NULL, NULL}
190
static Py_ssize_t BPy_IDGroup_Map_Len(BPy_IDProperty *self)
192
if (self->prop->type != IDP_GROUP) {
193
PyErr_SetString( PyExc_TypeError, "len() of unsized object");
197
return self->prop->len;
200
static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item)
205
if (self->prop->type != IDP_GROUP) {
206
PyErr_SetString( PyExc_TypeError, "unsubscriptable object");
210
name= _PyUnicode_AsString(item);
213
PyErr_SetString( PyExc_TypeError, "only strings are allowed as keys of ID properties");
217
idprop= IDP_GetPropertyFromGroup(self->prop, name);
220
PyErr_SetString( PyExc_KeyError, "key not in subgroup dict");
224
return BPy_IDGroup_WrapData(self->id, idprop);
228
/*returns NULL on success, error string on failure*/
229
static int idp_sequence_type(PyObject *seq)
234
int i, len = PySequence_Length(seq);
235
for (i=0; i < len; i++) {
236
item = PySequence_GetItem(seq, i);
237
if (PyFloat_Check(item)) {
238
if(type == IDP_IDPARRAY) { /* mixed dict/int */
244
else if (PyLong_Check(item)) {
245
if(type == IDP_IDPARRAY) { /* mixed dict/int */
250
else if (PyMapping_Check(item)) {
251
if(i != 0 && (type != IDP_IDPARRAY)) { /* mixed dict/int */
268
/* note: group can be a pointer array or a group */
269
char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob)
271
IDProperty *prop = NULL;
272
IDPropertyTemplate val = {0};
274
if(strlen(name) >= sizeof(group->name))
275
return "the length of IDProperty names is limited to 31 characters";
277
if (PyFloat_Check(ob)) {
278
val.d = PyFloat_AsDouble(ob);
279
prop = IDP_New(IDP_DOUBLE, val, name);
280
} else if (PyLong_Check(ob)) {
281
val.i = (int) PyLong_AsSsize_t(ob);
282
prop = IDP_New(IDP_INT, val, name);
283
} else if (PyUnicode_Check(ob)) {
284
val.str = _PyUnicode_AsString(ob);
285
prop = IDP_New(IDP_STRING, val, name);
286
} else if (PySequence_Check(ob)) {
290
if((val.array.type= idp_sequence_type(ob)) == -1)
291
return "only floats, ints and dicts are allowed in ID property arrays";
293
/*validate sequence and derive type.
294
we assume IDP_INT unless we hit a float
295
number; then we assume it's */
297
val.array.len = PySequence_Length(ob);
299
switch(val.array.type) {
301
prop = IDP_New(IDP_ARRAY, val, name);
302
for (i=0; i<val.array.len; i++) {
303
item = PySequence_GetItem(ob, i);
304
((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
309
prop = IDP_New(IDP_ARRAY, val, name);
310
for (i=0; i<val.array.len; i++) {
311
item = PySequence_GetItem(ob, i);
312
((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item);
317
prop= IDP_NewIDPArray(name);
318
for (i=0; i<val.array.len; i++) {
320
item = PySequence_GetItem(ob, i);
321
error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item);
329
} else if (PyMapping_Check(ob)) {
330
PyObject *keys, *vals, *key, *pval;
332
/*yay! we get into recursive stuff now!*/
333
keys = PyMapping_Keys(ob);
334
vals = PyMapping_Values(ob);
336
/*we allocate the group first; if we hit any invalid data,
337
we can delete it easily enough.*/
338
prop = IDP_New(IDP_GROUP, val, name);
339
len = PyMapping_Length(ob);
340
for (i=0; i<len; i++) {
341
key = PySequence_GetItem(keys, i);
342
pval = PySequence_GetItem(vals, i);
343
if (!PyUnicode_Check(key)) {
344
IDP_FreeProperty(prop);
350
return "invalid element in subgroup dict template!";
352
if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) {
353
IDP_FreeProperty(prop);
359
return "invalid element in subgroup dict template!";
366
} else return "invalid property value";
368
if(group->type==IDP_IDPARRAY) {
369
IDP_AppendArray(group, prop);
370
// IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory
373
IDP_ReplaceInGroup(group, prop);
379
int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val)
381
if (prop->type != IDP_GROUP) {
382
PyErr_SetString( PyExc_TypeError, "unsubscriptable object");
386
if (val == NULL) { /* del idprop[key] */
387
IDProperty *pkey = IDP_GetPropertyFromGroup(prop, _PyUnicode_AsString(key));
389
IDP_RemFromGroup(prop, pkey);
390
IDP_FreeProperty(pkey);
394
PyErr_SetString( PyExc_KeyError, "property not found in group" );
401
if (!PyUnicode_Check(key)) {
402
PyErr_SetString( PyExc_TypeError, "only strings are allowed as subgroup keys" );
406
err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, val);
408
PyErr_SetString( PyExc_KeyError, err );
416
static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject *val)
418
return BPy_Wrap_SetMapItem(self->prop, key, val);
421
static PyObject *BPy_IDGroup_SpawnIterator(BPy_IDProperty *self)
423
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
425
iter->mode = IDPROP_ITER_KEYS;
426
iter->cur = self->prop->data.group.first;
428
return (PyObject*) iter;
431
static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
433
switch (prop->type) {
435
return PyUnicode_FromString(prop->data.pointer);
438
return PyFloat_FromDouble(*((float*)&prop->data.val));
441
return PyFloat_FromDouble(*((double*)&prop->data.val));
444
return PyLong_FromSsize_t( prop->data.val );
448
PyObject *seq = PyList_New(prop->len);
452
PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_ARRAY: PyList_New(%d) failed", prop->len);
456
for (i=0; i<prop->len; i++) {
457
if (prop->subtype == IDP_FLOAT) {
458
PyList_SET_ITEM(seq, i,
459
PyFloat_FromDouble(((float*)prop->data.pointer)[i]));
460
} else if (prop->subtype == IDP_DOUBLE) {
461
PyList_SET_ITEM(seq, i,
462
PyFloat_FromDouble(((double*)prop->data.pointer)[i]));
464
PyList_SET_ITEM(seq, i,
465
PyLong_FromLong(((int*)prop->data.pointer)[i]));
472
PyObject *seq = PyList_New(prop->len), *wrap;
473
IDProperty *array= IDP_IDPArray(prop);
477
PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len);
481
for (i=0; i<prop->len; i++) {
482
wrap= BPy_IDGroup_MapDataToPy(array++);
484
if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */
487
PyList_SET_ITEM(seq, i, wrap);
493
PyObject *dict = PyDict_New(), *wrap;
496
for (loop=prop->data.group.first; loop; loop=loop->next) {
497
wrap = BPy_IDGroup_MapDataToPy(loop);
499
if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */
502
PyDict_SetItemString(dict, loop->name, wrap);
508
PyErr_Format(PyExc_RuntimeError, "eek!! '%s' property exists with a bad type code '%d' !!!", prop->name, prop->type);
512
static PyObject *BPy_IDGroup_Pop(BPy_IDProperty *self, PyObject *value)
516
char *name = _PyUnicode_AsString(value);
519
PyErr_SetString( PyExc_TypeError, "pop expected at least 1 argument, got 0" );
523
idprop= IDP_GetPropertyFromGroup(self->prop, name);
526
pyform = BPy_IDGroup_MapDataToPy(idprop);
529
/*ok something bad happened with the pyobject,
530
so don't remove the prop from the group. if pyform is
531
NULL, then it already should have raised an exception.*/
535
IDP_RemFromGroup(self->prop, idprop);
539
PyErr_SetString( PyExc_KeyError, "item not in group" );
543
static PyObject *BPy_IDGroup_IterItems(BPy_IDProperty *self)
545
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
547
iter->mode = IDPROP_ITER_ITEMS;
548
iter->cur = self->prop->data.group.first;
550
return (PyObject*) iter;
553
/* utility function */
554
static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len)
558
printf("ID Property Error found and corrected in BPy_IDGroup_GetKeys/Values/Items!\n");
560
/*fill rest of list with valid references to None*/
561
for (j=len; j<prop->len; j++) {
563
PyList_SET_ITEM(seq, j, Py_None);
566
/*set correct group length*/
570
PyObject *BPy_Wrap_GetKeys(IDProperty *prop)
572
PyObject *seq = PyList_New(prop->len);
576
for (i=0, loop=prop->data.group.first; loop && (i < prop->len); loop=loop->next, i++)
577
PyList_SET_ITEM(seq, i, PyUnicode_FromString(loop->name));
579
/* if the id prop is corrupt, count the remaining */
580
for (; loop; loop=loop->next, i++) {}
582
if (i != prop->len) { /* if the loop didnt finish, we know the length is wrong */
583
BPy_IDGroup_CorrectListLen(prop, seq, i);
584
Py_DECREF(seq); /*free the list*/
586
return BPy_Wrap_GetKeys(prop);
592
PyObject *BPy_Wrap_GetValues(ID *id, IDProperty *prop)
594
PyObject *seq = PyList_New(prop->len);
598
for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) {
599
PyList_SET_ITEM(seq, i, BPy_IDGroup_WrapData(id, loop));
602
if (i != prop->len) {
603
BPy_IDGroup_CorrectListLen(prop, seq, i);
604
Py_DECREF(seq); /*free the list*/
606
return BPy_Wrap_GetValues(id, prop);
612
PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
614
PyObject *seq = PyList_New(prop->len);
618
for (i=0, loop=prop->data.group.first; loop; loop=loop->next, i++) {
619
PyObject *item= PyTuple_New(2);
620
PyTuple_SET_ITEM(item, 0, PyUnicode_FromString(loop->name));
621
PyTuple_SET_ITEM(item, 1, BPy_IDGroup_WrapData(id, loop));
622
PyList_SET_ITEM(seq, i, item);
625
if (i != prop->len) {
626
BPy_IDGroup_CorrectListLen(prop, seq, i);
627
Py_DECREF(seq); /*free the list*/
629
return BPy_Wrap_GetItems(id, prop);
636
static PyObject *BPy_IDGroup_GetKeys(BPy_IDProperty *self)
638
return BPy_Wrap_GetKeys(self->prop);
641
static PyObject *BPy_IDGroup_GetValues(BPy_IDProperty *self)
643
return BPy_Wrap_GetValues(self->id, self->prop);
646
static PyObject *BPy_IDGroup_GetItems(BPy_IDProperty *self)
648
return BPy_Wrap_GetItems(self->id, self->prop);
651
static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value)
653
char *name = _PyUnicode_AsString(value);
656
PyErr_SetString( PyExc_TypeError, "expected a string");
660
return IDP_GetPropertyFromGroup(self->prop, name) ? 1:0;
663
static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value)
665
PyObject *pkey, *pval;
668
if (!PyDict_Check(value)) {
669
PyErr_SetString( PyExc_TypeError, "expected an object derived from dict.");
673
while (PyDict_Next(value, &i, &pkey, &pval)) {
674
BPy_IDGroup_Map_SetItem(self, pkey, pval);
675
if (PyErr_Occurred()) return NULL;
681
static PyObject *BPy_IDGroup_ConvertToPy(BPy_IDProperty *self)
683
return BPy_IDGroup_MapDataToPy(self->prop);
687
/* Matches python dict.get(key, [default]) */
688
PyObject* BPy_IDGroup_Get(BPy_IDProperty *self, PyObject *args)
692
PyObject* def = Py_None;
694
if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
697
idprop= IDP_GetPropertyFromGroup(self->prop, key);
699
PyObject* pyobj = BPy_IDGroup_WrapData(self->id, idprop);
708
static struct PyMethodDef BPy_IDGroup_methods[] = {
709
{"pop", (PyCFunction)BPy_IDGroup_Pop, METH_O,
710
"pop an item from the group; raises KeyError if the item doesn't exist"},
711
{"iteritems", (PyCFunction)BPy_IDGroup_IterItems, METH_NOARGS,
712
"iterate through the items in the dict; behaves like dictionary method iteritems"},
713
{"keys", (PyCFunction)BPy_IDGroup_GetKeys, METH_NOARGS,
714
"get the keys associated with this group as a list of strings"},
715
{"values", (PyCFunction)BPy_IDGroup_GetValues, METH_NOARGS,
716
"get the values associated with this group"},
717
{"items", (PyCFunction)BPy_IDGroup_GetItems, METH_NOARGS,
718
"get the items associated with this group"},
719
{"update", (PyCFunction)BPy_IDGroup_Update, METH_O,
720
"updates the values in the group with the values of another or a dict"},
721
{"get", (PyCFunction)BPy_IDGroup_Get, METH_VARARGS,
722
"idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None"},
723
{"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS,
724
"return a purely python version of the group"},
728
static PySequenceMethods BPy_IDGroup_Seq = {
729
(lenfunc) BPy_IDGroup_Map_Len, /* lenfunc sq_length */
730
0, /* binaryfunc sq_concat */
731
0, /* ssizeargfunc sq_repeat */
732
0, /* ssizeargfunc sq_item */ /* TODO - setting this will allow PySequence_Check to return True */
733
0, /* intintargfunc ***was_sq_slice*** */
734
0, /* intobjargproc sq_ass_item */
735
0, /* ssizeobjargproc ***was_sq_ass_slice*** */
736
(objobjproc) BPy_IDGroup_Contains, /* objobjproc sq_contains */
737
0, /* binaryfunc sq_inplace_concat */
738
0, /* ssizeargfunc sq_inplace_repeat */
741
PyMappingMethods BPy_IDGroup_Mapping = {
742
(lenfunc)BPy_IDGroup_Map_Len, /*inquiry mp_length */
743
(binaryfunc)BPy_IDGroup_Map_GetItem, /*binaryfunc mp_subscript */
744
(objobjargproc)BPy_IDGroup_Map_SetItem, /*objobjargproc mp_ass_subscript */
747
PyTypeObject IDGroup_Type = {
748
PyVarObject_HEAD_INIT(NULL, 0)
749
/* For printing, in format "<module>.<name>" */
750
"Blender IDProperty", /* char *tp_name; */
751
sizeof( BPy_IDProperty ), /* int tp_basicsize; */
752
0, /* tp_itemsize; For allocation */
754
/* Methods to implement standard operations */
756
NULL, /* destructor tp_dealloc; */
757
NULL, /* printfunc tp_print; */
758
NULL, /* getattrfunc tp_getattr; */
759
NULL, /* setattrfunc tp_setattr; */
760
NULL, /* cmpfunc tp_compare; */
761
( reprfunc ) IDGroup_repr, /* reprfunc tp_repr; */
763
/* Method suites for standard classes */
765
NULL, /* PyNumberMethods *tp_as_number; */
766
&BPy_IDGroup_Seq, /* PySequenceMethods *tp_as_sequence; */
767
&BPy_IDGroup_Mapping, /* PyMappingMethods *tp_as_mapping; */
769
/* More standard operations (here for binary compatibility) */
771
NULL, /* hashfunc tp_hash; */
772
NULL, /* ternaryfunc tp_call; */
773
NULL, /* reprfunc tp_str; */
774
NULL, /* getattrofunc tp_getattro; */
775
NULL, /* setattrofunc tp_setattro; */
777
/* Functions to access object as input/output buffer */
778
NULL, /* PyBufferProcs *tp_as_buffer; */
780
/*** Flags to define presence of optional/expanded features ***/
781
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
783
NULL, /* char *tp_doc; Documentation string */
784
/*** Assigned meaning in release 2.0 ***/
785
/* call function for all accessible objects */
786
NULL, /* traverseproc tp_traverse; */
788
/* delete references to contained objects */
789
NULL, /* inquiry tp_clear; */
791
/*** Assigned meaning in release 2.1 ***/
792
/*** rich comparisons ***/
793
NULL, /* richcmpfunc tp_richcompare; */
795
/*** weak reference enabler ***/
796
0, /* long tp_weaklistoffset; */
798
/*** Added in release 2.2 ***/
800
(getiterfunc)BPy_IDGroup_SpawnIterator, /* getiterfunc tp_iter; */
801
NULL, /* iternextfunc tp_iternext; */
802
/*** Attribute descriptor and subclassing stuff ***/
803
BPy_IDGroup_methods, /* struct PyMethodDef *tp_methods; */
804
NULL, /* struct PyMemberDef *tp_members; */
805
BPy_IDGroup_getseters, /* struct PyGetSetDef *tp_getset; */
808
/*********** Main external wrapping function *******/
809
PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent)
811
BPy_IDProperty *wrap = PyObject_New(BPy_IDProperty, &IDGroup_Type);
813
wrap->parent = parent;
816
return (PyObject*) wrap;
820
/********Array Wrapper********/
822
static PyObject *IDArray_repr(BPy_IDArray *self)
824
return PyUnicode_FromString("(ID Array)");
828
static PyObject *BPy_IDArray_GetType(BPy_IDArray *self)
830
return PyLong_FromSsize_t( self->prop->subtype );
833
static PyObject *BPy_IDArray_GetLen(BPy_IDArray *self)
835
return PyLong_FromSsize_t( self->prop->len );
838
static PyGetSetDef BPy_IDArray_getseters[] = {
840
(getter)BPy_IDArray_GetLen, (setter)NULL,
841
"The length of the array, can also be gotten with len(array).",
844
(getter)BPy_IDArray_GetType, (setter)NULL,
845
"The type of the data in the array, is an ant.",
847
{NULL, NULL, NULL, NULL, NULL},
850
static PyObject *BPy_IDArray_ConvertToPy(BPy_IDArray *self)
852
return BPy_IDGroup_MapDataToPy(self->prop);
855
static PyMethodDef BPy_IDArray_methods[] = {
856
{"convert_to_pyobject", (PyCFunction)BPy_IDArray_ConvertToPy, METH_NOARGS,
857
"return a purely python version of the group"},
861
static int BPy_IDArray_Len(BPy_IDArray *self)
863
return self->prop->len;
866
static PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index)
868
if (index < 0 || index >= self->prop->len) {
869
PyErr_SetString( PyExc_IndexError, "index out of range!");
873
switch (self->prop->subtype) {
875
return PyFloat_FromDouble( (double)(((float*)self->prop->data.pointer)[index]));
878
return PyFloat_FromDouble( (((double*)self->prop->data.pointer)[index]));
881
return PyLong_FromLong( (long)((int*)self->prop->data.pointer)[index] );
885
PyErr_SetString( PyExc_RuntimeError, "invalid/corrupt array type!");
889
static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
895
if (index < 0 || index >= self->prop->len) {
896
PyErr_SetString( PyExc_RuntimeError, "index out of range!");
900
switch (self->prop->subtype) {
902
f= (float)PyFloat_AsDouble(value);
903
if (f==-1 && PyErr_Occurred()) {
904
PyErr_SetString(PyExc_TypeError, "expected a float");
907
((float*)self->prop->data.pointer)[index] = f;
910
d= PyFloat_AsDouble(value);
911
if (d==-1 && PyErr_Occurred()) {
912
PyErr_SetString(PyExc_TypeError, "expected a float");
915
((double*)self->prop->data.pointer)[index] = d;
918
i= PyLong_AsSsize_t(value);
919
if (i==-1 && PyErr_Occurred()) {
920
PyErr_SetString(PyExc_TypeError, "expected an int type");
924
((int*)self->prop->data.pointer)[index] = i;
930
static PySequenceMethods BPy_IDArray_Seq = {
931
(lenfunc) BPy_IDArray_Len, /* inquiry sq_length */
932
0, /* binaryfunc sq_concat */
933
0, /* intargfunc sq_repeat */
934
(ssizeargfunc)BPy_IDArray_GetItem, /* intargfunc sq_item */
935
0, /* intintargfunc sq_slice */
936
(ssizeobjargproc)BPy_IDArray_SetItem, /* intobjargproc sq_ass_item */
937
0, /* intintobjargproc sq_ass_slice */
938
0, /* objobjproc sq_contains */
939
/* Added in release 2.0 */
940
0, /* binaryfunc sq_inplace_concat */
941
0, /* intargfunc sq_inplace_repeat */
944
PyTypeObject IDArray_Type = {
945
PyVarObject_HEAD_INIT(NULL, 0)
946
/* For printing, in format "<module>.<name>" */
947
"Blender IDArray", /* char *tp_name; */
948
sizeof( BPy_IDArray ), /* int tp_basicsize; */
949
0, /* tp_itemsize; For allocation */
951
/* Methods to implement standard operations */
953
NULL, /* destructor tp_dealloc; */
954
NULL, /* printfunc tp_print; */
955
NULL, /* getattrfunc tp_getattr; */
956
NULL, /* setattrfunc tp_setattr; */
957
NULL, /* cmpfunc tp_compare; */
958
( reprfunc ) IDArray_repr, /* reprfunc tp_repr; */
960
/* Method suites for standard classes */
962
NULL, /* PyNumberMethods *tp_as_number; */
963
&BPy_IDArray_Seq, /* PySequenceMethods *tp_as_sequence; */
964
NULL, /* PyMappingMethods *tp_as_mapping; */
966
/* More standard operations (here for binary compatibility) */
968
NULL, /* hashfunc tp_hash; */
969
NULL, /* ternaryfunc tp_call; */
970
NULL, /* reprfunc tp_str; */
971
NULL, /* getattrofunc tp_getattro; */
972
NULL, /* setattrofunc tp_setattro; */
974
/* Functions to access object as input/output buffer */
975
NULL, /* PyBufferProcs *tp_as_buffer; */
977
/*** Flags to define presence of optional/expanded features ***/
978
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
980
NULL, /* char *tp_doc; Documentation string */
981
/*** Assigned meaning in release 2.0 ***/
982
/* call function for all accessible objects */
983
NULL, /* traverseproc tp_traverse; */
985
/* delete references to contained objects */
986
NULL, /* inquiry tp_clear; */
988
/*** Assigned meaning in release 2.1 ***/
989
/*** rich comparisons ***/
990
NULL, /* richcmpfunc tp_richcompare; */
992
/*** weak reference enabler ***/
993
0, /* long tp_weaklistoffset; */
995
/*** Added in release 2.2 ***/
997
NULL, /* getiterfunc tp_iter; */
998
NULL, /* iternextfunc tp_iternext; */
1000
/*** Attribute descriptor and subclassing stuff ***/
1001
BPy_IDArray_methods, /* struct PyMethodDef *tp_methods; */
1002
NULL, /* struct PyMemberDef *tp_members; */
1003
BPy_IDArray_getseters, /* struct PyGetSetDef *tp_getset; */
1004
NULL, /* struct _typeobject *tp_base; */
1005
NULL, /* PyObject *tp_dict; */
1006
NULL, /* descrgetfunc tp_descr_get; */
1007
NULL, /* descrsetfunc tp_descr_set; */
1008
0, /* long tp_dictoffset; */
1009
NULL, /* initproc tp_init; */
1010
NULL, /* allocfunc tp_alloc; */
1011
NULL, /* newfunc tp_new; */
1012
/* Low-level free-memory routine */
1013
NULL, /* freefunc tp_free; */
1014
/* For PyObject_IS_GC */
1015
NULL, /* inquiry tp_is_gc; */
1016
NULL, /* PyObject *tp_bases; */
1017
/* method resolution order */
1018
NULL, /* PyObject *tp_mro; */
1019
NULL, /* PyObject *tp_cache; */
1020
NULL, /* PyObject *tp_subclasses; */
1021
NULL, /* PyObject *tp_weaklist; */
1025
/*********** ID Property Group iterator ********/
1027
static PyObject *IDGroup_Iter_iterself(PyObject *self)
1033
static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
1035
return PyUnicode_FromString("(ID Property Group)");
1038
static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
1040
IDProperty *cur=NULL;
1045
self->cur = self->cur->next;
1046
if (self->mode == IDPROP_ITER_ITEMS) {
1047
ret = PyTuple_New(2);
1048
PyTuple_SET_ITEM(ret, 0, PyUnicode_FromString(cur->name));
1049
PyTuple_SET_ITEM(ret, 1, BPy_IDGroup_WrapData(self->group->id, cur));
1052
return PyUnicode_FromString(cur->name);
1055
PyErr_SetString( PyExc_StopIteration, "iterator at end" );
1060
PyTypeObject IDGroup_Iter_Type = {
1061
PyVarObject_HEAD_INIT(NULL, 0)
1062
/* For printing, in format "<module>.<name>" */
1063
"Blender IDGroup_Iter", /* char *tp_name; */
1064
sizeof( BPy_IDGroup_Iter ), /* int tp_basicsize; */
1065
0, /* tp_itemsize; For allocation */
1067
/* Methods to implement standard operations */
1069
NULL, /* destructor tp_dealloc; */
1070
NULL, /* printfunc tp_print; */
1071
NULL, /* getattrfunc tp_getattr; */
1072
NULL, /* setattrfunc tp_setattr; */
1073
NULL, /* cmpfunc tp_compare; */
1074
( reprfunc ) IDGroup_Iter_repr, /* reprfunc tp_repr; */
1076
/* Method suites for standard classes */
1078
NULL, /* PyNumberMethods *tp_as_number; */
1079
NULL, /* PySequenceMethods *tp_as_sequence; */
1080
NULL, /* PyMappingMethods *tp_as_mapping; */
1082
/* More standard operations (here for binary compatibility) */
1084
NULL, /* hashfunc tp_hash; */
1085
NULL, /* ternaryfunc tp_call; */
1086
NULL, /* reprfunc tp_str; */
1087
NULL, /* getattrofunc tp_getattro; */
1088
NULL, /* setattrofunc tp_setattro; */
1090
/* Functions to access object as input/output buffer */
1091
NULL, /* PyBufferProcs *tp_as_buffer; */
1093
/*** Flags to define presence of optional/expanded features ***/
1094
Py_TPFLAGS_DEFAULT, /* long tp_flags; */
1096
NULL, /* char *tp_doc; Documentation string */
1097
/*** Assigned meaning in release 2.0 ***/
1098
/* call function for all accessible objects */
1099
NULL, /* traverseproc tp_traverse; */
1101
/* delete references to contained objects */
1102
NULL, /* inquiry tp_clear; */
1104
/*** Assigned meaning in release 2.1 ***/
1105
/*** rich comparisons ***/
1106
NULL, /* richcmpfunc tp_richcompare; */
1108
/*** weak reference enabler ***/
1109
0, /* long tp_weaklistoffset; */
1111
/*** Added in release 2.2 ***/
1113
IDGroup_Iter_iterself, /* getiterfunc tp_iter; */
1114
(iternextfunc) BPy_Group_Iter_Next, /* iternextfunc tp_iternext; */
1117
void IDProp_Init_Types(void)
1119
PyType_Ready( &IDGroup_Type );
1120
PyType_Ready( &IDGroup_Iter_Type );
1121
PyType_Ready( &IDArray_Type );