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