Blender  V2.59
bpy_rna_array.c
Go to the documentation of this file.
00001 /*
00002  * $Id: bpy_rna_array.c 39233 2011-08-09 20:00:53Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * Contributor(s): Arystanbek Dyussenov
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00029 #include <Python.h>
00030 
00031 #include "RNA_types.h"
00032 
00033 #include "bpy_rna.h"
00034 #include "BKE_global.h"
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "RNA_access.h"
00038 
00039 #define MAX_ARRAY_DIMENSION 10
00040 
00041 typedef void (*ItemConvertFunc)(PyObject *, char *);
00042 typedef int  (*ItemTypeCheckFunc)(PyObject *);
00043 typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *);
00044 typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *);
00045 
00046 /*
00047   arr[3][4][5]
00048           0  1  2  <- dimension index
00049 */
00050 
00051 /*
00052   arr[2]= x
00053 
00054   py_to_array_index(arraydim=0, arrayoffset=0, index=2)
00055         validate_array(lvalue_dim=0)
00056         ... make real index ...
00057 */
00058 
00059 /* arr[3]=x, self->arraydim is 0, lvalue_dim is 1 */
00060 /* Ensures that a python sequence has expected number of items/sub-items and items are of desired type. */
00061 static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[],
00062                                                            ItemTypeCheckFunc check_item_type, const char *item_type_str, const char *error_prefix)
00063 {
00064         int i;
00065 
00066         /* not the last dimension */
00067         if (dim + 1 < totdim) {
00068                 /* check that a sequence contains dimsize[dim] items */
00069                 const int seq_size= PySequence_Size(seq);
00070                 if(seq_size == -1) {
00071                         PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
00072                                      error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
00073                         return -1;
00074                 }
00075                 for (i= 0; i < seq_size; i++) {
00076                         PyObject *item;
00077                         int ok= 1;
00078                         item= PySequence_GetItem(seq, i);
00079 
00080                         if(item == NULL) {
00081                                 PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
00082                                              error_prefix, Py_TYPE(seq)->tp_name, i);
00083                                 ok= 0;
00084                         }
00085                         else if (!PySequence_Check(item)) {
00086                                 /* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */
00087                                 PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s",
00088                                              error_prefix, item_type_str, Py_TYPE(item)->tp_name);
00089                                 ok= 0;
00090                         }
00091                         /* arr[3][4][5]
00092                            dimsize[1]=4
00093                            dimsize[2]=5
00094                    
00095                            dim=0 */
00096                         else if (PySequence_Size(item) != dimsize[dim + 1]) {
00097                                 /* BLI_snprintf(error_str, error_str_size, "sequences of dimension %d should contain %d items", (int)dim + 1, (int)dimsize[dim + 1]); */
00098                                 PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items",
00099                                              error_prefix, (int)dim + 1, (int)dimsize[dim + 1]);
00100                                 ok= 0;
00101                         }
00102                         else if (validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1) {
00103                                 ok= 0;
00104                         }
00105 
00106                         Py_XDECREF(item);
00107 
00108                         if (!ok)
00109                                 return -1;
00110                 }
00111         }
00112         else {
00113                 /* check that items are of correct type */
00114                 const int seq_size= PySequence_Size(seq);
00115                 if(seq_size == -1) {
00116                         PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
00117                                      error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
00118                         return -1;
00119                 }
00120                 for (i= 0; i < seq_size; i++) {
00121                         PyObject *item= PySequence_GetItem(seq, i);
00122 
00123                         if(item == NULL) {
00124                                 PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
00125                                              error_prefix, Py_TYPE(seq)->tp_name, i);
00126                                 return -1;
00127                         }
00128                         else if (!check_item_type(item)) {
00129                                 Py_DECREF(item);
00130 
00131                                 /* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */
00132                                 PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s",
00133                                              error_prefix, item_type_str, Py_TYPE(item)->tp_name);
00134                                 return -1;
00135                         }
00136 
00137                         Py_DECREF(item);
00138                 }
00139         }
00140 
00141         return 0; /* ok */
00142 }
00143 
00144 /* Returns the number of items in a single- or multi-dimensional sequence. */
00145 static int count_items(PyObject *seq, int dim)
00146 {
00147         int totitem= 0;
00148 
00149         if(dim > 1) {
00150                 const int seq_size= PySequence_Size(seq);
00151                 int i;
00152                 for (i= 0; i < seq_size; i++) {
00153                         PyObject *item= PySequence_GetItem(seq, i);
00154                         if(item) {
00155                                 const int tot= count_items(item, dim - 1);
00156                                 Py_DECREF(item);
00157                                 if(tot != -1) {
00158                                         totitem += tot;
00159                                 }
00160                                 else {
00161                                         totitem= -1;
00162                                         break;
00163                                 }
00164                         }
00165                         else {
00166                                 totitem= -1;
00167                                 break;
00168                         }
00169                 }
00170         }
00171         else {
00172                 totitem= PySequence_Size(seq);
00173         }
00174 
00175         return totitem;
00176 }
00177 
00178 /* Modifies property array length if needed and PROP_DYNAMIC flag is set. */
00179 static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int *totitem, const char *error_prefix)
00180 {
00181         int dimsize[MAX_ARRAY_DIMENSION];
00182         int tot, totdim, len;
00183 
00184         totdim= RNA_property_array_dimension(ptr, prop, dimsize);
00185         tot= count_items(rvalue, totdim - lvalue_dim);
00186 
00187         if(tot == -1) {
00188                 PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, error validating the sequence length",
00189                              error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
00190                 return -1;
00191         }
00192         else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
00193                 if (RNA_property_array_length(ptr, prop) != tot) {
00194 #if 0
00195                         /* length is flexible */
00196                         if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) {
00197                                 /* BLI_snprintf(error_str, error_str_size, "%s.%s: array length cannot be changed to %d", RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */
00198                                 PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d",
00199                                              error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
00200                                 return -1;
00201                         }
00202 #else
00203                         *totitem= tot;
00204                         return 0;
00205 
00206 #endif
00207                 }
00208 
00209                 len= tot;
00210         }
00211         else {
00212                 /* length is a constraint */
00213                 if (!lvalue_dim) {
00214                         len= RNA_property_array_length(ptr, prop);
00215                 }
00216                 /* array item assignment */
00217                 else {
00218                         int i;
00219 
00220                         len= 1;
00221 
00222                         /* arr[3][4][5]
00223 
00224                            arr[2]= x
00225                            dimsize={4, 5}
00226                            dimsize[1]= 4
00227                            dimsize[2]= 5
00228                            lvalue_dim=0, totdim=3
00229 
00230                            arr[2][3]= x
00231                            lvalue_dim=1
00232 
00233                            arr[2][3][4]= x
00234                            lvalue_dim=2 */
00235                         for (i= lvalue_dim; i < totdim; i++)
00236                                 len *= dimsize[i];
00237                 }
00238 
00239                 if (tot != len) {
00240                         /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
00241                         PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d",
00242                                      error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
00243                         return -1;
00244                 }
00245         }
00246 
00247         *totitem= len;
00248 
00249         return 0;
00250 }
00251 
00252 static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, const char *error_prefix)
00253 {
00254         int dimsize[MAX_ARRAY_DIMENSION];
00255         int totdim= RNA_property_array_dimension(ptr, prop, dimsize);
00256 
00257         /* validate type first because length validation may modify property array length */
00258 
00259         if (validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1)
00260                 return -1;
00261 
00262         return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix);
00263 }
00264 
00265 static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index)
00266 {
00267         if (!data) {
00268                 char value[sizeof(int)];
00269 
00270                 convert_item(item, value);
00271                 rna_set_index(ptr, prop, *index, value);
00272                 *index= *index + 1;
00273         }
00274         else {
00275                 convert_item(item, data);
00276                 data += item_size;
00277         }
00278 
00279         return data;
00280 }
00281 
00282 static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int dim, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index)
00283 {
00284         unsigned int i;
00285         int totdim= RNA_property_array_dimension(ptr, prop, NULL);
00286         const int seq_size= PySequence_Size(seq);
00287 
00288         /* Regarding PySequence_GetItem() failing.
00289          *
00290          * This should never be NULL since we validated it, _but_ some triky python
00291          * developer could write their own sequence type which succeeds on
00292          * validating but fails later somehow, so include checks for safety.
00293          */
00294 
00295         /* Note that 'data can be NULL' */
00296 
00297         if(seq_size == -1) {
00298                 return NULL;
00299         }
00300 
00301         for (i= 0; i < seq_size; i++) {
00302                 PyObject *item= PySequence_GetItem(seq, i);
00303                 if(item) {
00304                         if (dim + 1 < totdim) {
00305                                 data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
00306                         }
00307                         else {
00308                                 data= copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
00309                         }
00310 
00311                         Py_DECREF(item);
00312 
00313                         /* data may be NULL, but the for loop checks */
00314                 }
00315                 else {
00316                         return NULL;
00317                 }
00318         }
00319 
00320         return data;
00321 }
00322 
00323 static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
00324 {
00325         /*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/
00326         int totitem;
00327         char *data= NULL;
00328 
00329         /*totdim= RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/
00330 
00331         if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
00332                 return -1;
00333         }
00334 
00335         if (totitem) {
00336                 /* note: this code is confusing */
00337                 if(param_data && RNA_property_flag(prop) & PROP_DYNAMIC) {
00338                         /* not freeing allocated mem, RNA_parameter_list_free() will do this */
00339                         ParameterDynAlloc *param_alloc= (ParameterDynAlloc *)param_data;
00340                         param_alloc->array_tot= (int)totitem;
00341                         param_alloc->array= MEM_callocN(item_size * totitem, "py_to_array dyn"); /* freeing param list will free */
00342 
00343                         data= param_alloc->array;
00344                 }
00345                 else if (param_data) {
00346                         data= param_data;
00347                 }
00348                 else {
00349                         data= PyMem_MALLOC(item_size * totitem);
00350                 }
00351 
00352                 /* will only fail in very rare cases since we already validated the
00353                  * python data, the check here is mainly for completeness. */
00354                 if(copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) {
00355                         if (param_data==NULL) {
00356                                 /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
00357                                 rna_set_array(ptr, prop, data);
00358                                 PyMem_FREE(data);
00359                         }
00360                 }
00361                 else {
00362                         if (param_data==NULL) {
00363                                 PyMem_FREE(data);
00364                         }
00365 
00366                         PyErr_Format(PyExc_TypeError, "%s internal error parsing sequence of type '%s' after successful validation",
00367                                      error_prefix, Py_TYPE(seq)->tp_name);
00368                         return -1;
00369                 }
00370         }
00371 
00372         return 0;
00373 }
00374 
00375 static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int arrayoffset, int index, ItemTypeCheckFunc check_item_type, const char *item_type_str, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
00376 {
00377         int totdim, dimsize[MAX_ARRAY_DIMENSION];
00378         int totitem, i;
00379 
00380         totdim= RNA_property_array_dimension(ptr, prop, dimsize);
00381 
00382         /* convert index */
00383 
00384         /* arr[3][4][5]
00385 
00386            arr[2]= x
00387            lvalue_dim=0, index= 0 + 2 * 4 * 5
00388 
00389            arr[2][3]= x
00390            lvalue_dim=1, index= 40 + 3 * 5 */
00391 
00392         lvalue_dim++;
00393 
00394         for (i= lvalue_dim; i < totdim; i++)
00395                 index *= dimsize[i];
00396 
00397         index += arrayoffset;
00398 
00399         if(lvalue_dim == totdim) { /* single item, assign directly */
00400                 if(!check_item_type(py)) {
00401                         PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s",
00402                                      error_prefix, RNA_struct_identifier(ptr->type),
00403                                      RNA_property_identifier(prop), item_type_str,
00404                                      Py_TYPE(py)->tp_name);
00405                         return -1;
00406                 }
00407                 copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
00408         }
00409         else {
00410                 if (validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
00411                         return -1;
00412                 }
00413 
00414                 if (totitem) {
00415                         copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index);
00416                 }
00417         }
00418         return 0;
00419 }
00420 
00421 static void py_to_float(PyObject *py, char *data)
00422 {
00423         *(float*)data= (float)PyFloat_AsDouble(py);
00424 }
00425 
00426 static void py_to_int(PyObject *py, char *data)
00427 {
00428         *(int*)data= (int)PyLong_AsSsize_t(py);
00429 }
00430 
00431 static void py_to_bool(PyObject *py, char *data)
00432 {
00433         *(int*)data= (int)PyObject_IsTrue(py);
00434 }
00435 
00436 static int py_float_check(PyObject *py)
00437 {
00438         /* accept both floats and integers */
00439         return PyNumber_Check(py);
00440 }
00441 
00442 static int py_int_check(PyObject *py)
00443 {
00444         /* accept only integers */
00445         return PyLong_Check(py);
00446 }
00447 
00448 static int py_bool_check(PyObject *py)
00449 {
00450         return PyBool_Check(py);
00451 }
00452 
00453 static void float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
00454 {
00455         RNA_property_float_set_index(ptr, prop, index, *(float*)value);
00456 }
00457 
00458 static void int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
00459 {
00460         RNA_property_int_set_index(ptr, prop, index, *(int*)value);
00461 }
00462 
00463 static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
00464 {
00465         RNA_property_boolean_set_index(ptr, prop, index, *(int*)value);
00466 }
00467 
00468 int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
00469 {
00470         int ret;
00471         switch (RNA_property_type(prop)) {
00472         case PROP_FLOAT:
00473                 ret= py_to_array(py, ptr, prop, param_data, py_float_check, "float", sizeof(float), py_to_float, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix);
00474                 break;
00475         case PROP_INT:
00476                 ret= py_to_array(py, ptr, prop, param_data, py_int_check, "int", sizeof(int), py_to_int, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix);
00477                 break;
00478         case PROP_BOOLEAN:
00479                 ret= py_to_array(py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(int), py_to_bool, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix);
00480                 break;
00481         default:
00482                 PyErr_SetString(PyExc_TypeError, "not an array type");
00483                 ret= -1;
00484         }
00485 
00486         return ret;
00487 }
00488 
00489 int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix)
00490 {
00491         int ret;
00492         switch (RNA_property_type(prop)) {
00493         case PROP_FLOAT:
00494                 ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_float_check, "float", py_to_float, float_set_index, error_prefix);
00495                 break;
00496         case PROP_INT:
00497                 ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_int_check, "int", py_to_int, int_set_index, error_prefix);
00498                 break;
00499         case PROP_BOOLEAN:
00500                 ret= py_to_array_index(py, ptr, prop, arraydim, arrayoffset, index, py_bool_check, "boolean", py_to_bool, bool_set_index, error_prefix);
00501                 break;
00502         default:
00503                 PyErr_SetString(PyExc_TypeError, "not an array type");
00504                 ret= -1;
00505         }
00506 
00507         return ret;
00508 }
00509 
00510 PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index)
00511 {
00512         PyObject *item;
00513 
00514         switch (RNA_property_type(prop)) {
00515         case PROP_FLOAT:
00516                 item= PyFloat_FromDouble(RNA_property_float_get_index(ptr, prop, index));
00517                 break;
00518         case PROP_BOOLEAN:
00519                 item= PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index));
00520                 break;
00521         case PROP_INT:
00522                 item= PyLong_FromSsize_t(RNA_property_int_get_index(ptr, prop, index));
00523                 break;
00524         default:
00525                 PyErr_SetString(PyExc_TypeError, "not an array type");
00526                 item= NULL;
00527         }
00528 
00529         return item;
00530 }
00531 
00532 #if 0
00533 /* XXX this is not used (and never will?) */
00534 /* Given an array property, creates an N-dimensional tuple of values. */
00535 static PyObject *pyrna_py_from_array_internal(PointerRNA *ptr, PropertyRNA *prop, int dim, int *index)
00536 {
00537         PyObject *tuple;
00538         int i, len;
00539         int totdim= RNA_property_array_dimension(ptr, prop, NULL);
00540 
00541         len= RNA_property_multi_array_length(ptr, prop, dim);
00542 
00543         tuple= PyTuple_New(len);
00544 
00545         for (i= 0; i < len; i++) {
00546                 PyObject *item;
00547 
00548                 if (dim + 1 < totdim)
00549                         item= pyrna_py_from_array_internal(ptr, prop, dim + 1, index);
00550                 else {
00551                         item= pyrna_array_index(ptr, prop, *index);
00552                         *index= *index + 1;
00553                 }
00554 
00555                 if (!item) {
00556                         Py_DECREF(tuple);
00557                         return NULL;
00558                 }
00559 
00560                 PyTuple_SET_ITEM(tuple, i, item);
00561         }
00562 
00563         return tuple;
00564 }
00565 #endif
00566 
00567 PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index)
00568 {
00569         int totdim, arraydim, arrayoffset, dimsize[MAX_ARRAY_DIMENSION], i, len;
00570         BPy_PropertyArrayRNA *ret= NULL;
00571 
00572         arraydim= self ? self->arraydim : 0;
00573         arrayoffset= self ? self->arrayoffset : 0;
00574 
00575         /* just in case check */
00576         len= RNA_property_multi_array_length(ptr, prop, arraydim);
00577         if (index >= len || index < 0) {
00578                 /* this shouldn't happen because higher level funcs must check for invalid index */
00579                 if (G.f & G_DEBUG) printf("pyrna_py_from_array_index: invalid index %d for array with length=%d\n", index, len);
00580 
00581                 PyErr_SetString(PyExc_IndexError, "out of range");
00582                 return NULL;
00583         }
00584 
00585         totdim= RNA_property_array_dimension(ptr, prop, dimsize);
00586 
00587         if (arraydim + 1 < totdim) {
00588                 ret= (BPy_PropertyArrayRNA*)pyrna_prop_CreatePyObject(ptr, prop);
00589                 ret->arraydim= arraydim + 1;
00590 
00591                 /* arr[3][4][5]
00592 
00593                    x= arr[2]
00594                    index= 0 + 2 * 4 * 5
00595 
00596                    x= arr[2][3]
00597                    index= offset + 3 * 5 */
00598 
00599                 for (i= arraydim + 1; i < totdim; i++)
00600                         index *= dimsize[i];
00601 
00602                 ret->arrayoffset= arrayoffset + index;
00603         }
00604         else {
00605                 index= arrayoffset + index;
00606                 ret= (BPy_PropertyArrayRNA *)pyrna_array_index(ptr, prop, index);
00607         }
00608 
00609         return (PyObject*)ret;
00610 }
00611 
00612 PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop)
00613 {
00614         PyObject *ret;
00615 
00616         ret= pyrna_math_object_from_array(ptr, prop);
00617 
00618         /* is this a maths object? */
00619         if (ret) return ret;
00620 
00621         return pyrna_prop_CreatePyObject(ptr, prop);
00622 }
00623 
00624 /* TODO, multi-dimensional arrays */
00625 int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
00626 {
00627         int len= RNA_property_array_length(ptr, prop);
00628         int type;
00629         int i;
00630 
00631         if(len==0) /* possible with dynamic arrays */
00632                 return 0;
00633 
00634         if (RNA_property_array_dimension(ptr, prop, NULL) > 1) {
00635                 PyErr_SetString(PyExc_TypeError, "PropertyRNA - multi dimensional arrays not supported yet");
00636                 return -1;
00637         }
00638 
00639         type= RNA_property_type(prop);
00640 
00641         switch (type) {
00642                 case PROP_FLOAT:
00643                 {
00644                         float value_f= PyFloat_AsDouble(value);
00645                         if(value_f==-1 && PyErr_Occurred()) {
00646                                 PyErr_Clear();
00647                                 return 0;
00648                         }
00649                         else {
00650                                 float tmp[32];
00651                                 float *tmp_arr;
00652 
00653                                 if(len * sizeof(float) > sizeof(tmp)) {
00654                                         tmp_arr= PyMem_MALLOC(len * sizeof(float));
00655                                 }
00656                                 else {
00657                                         tmp_arr= tmp;
00658                                 }
00659 
00660                                 RNA_property_float_get_array(ptr, prop, tmp_arr);
00661 
00662                                 for(i=0; i<len; i++)
00663                                         if(tmp_arr[i] == value_f)
00664                                                 break;
00665 
00666                                 if(tmp_arr != tmp)
00667                                         PyMem_FREE(tmp_arr);
00668 
00669                                 return i<len ? 1 : 0;
00670                         }
00671                         break;
00672                 }
00673                 case PROP_BOOLEAN:
00674                 case PROP_INT:
00675                 {
00676                         int value_i= PyLong_AsSsize_t(value);
00677                         if(value_i==-1 && PyErr_Occurred()) {
00678                                 PyErr_Clear();
00679                                 return 0;
00680                         }
00681                         else {
00682                                 int tmp[32];
00683                                 int *tmp_arr;
00684 
00685                                 if(len * sizeof(int) > sizeof(tmp)) {
00686                                         tmp_arr= PyMem_MALLOC(len * sizeof(int));
00687                                 }
00688                                 else {
00689                                         tmp_arr= tmp;
00690                                 }
00691 
00692                                 if(type==PROP_BOOLEAN)
00693                                         RNA_property_boolean_get_array(ptr, prop, tmp_arr);
00694                                 else
00695                                         RNA_property_int_get_array(ptr, prop, tmp_arr);
00696 
00697                                 for(i=0; i<len; i++)
00698                                         if(tmp_arr[i] == value_i)
00699                                                 break;
00700 
00701                                 if(tmp_arr != tmp)
00702                                         PyMem_FREE(tmp_arr);
00703 
00704                                 return i<len ? 1 : 0;
00705                         }
00706                         break;
00707                 }
00708         }
00709 
00710         /* should never reach this */
00711         PyErr_SetString(PyExc_TypeError, "PropertyRNA - type not in float/bool/int");
00712         return -1;
00713 }