Blender  V2.93
bpy_rna_array.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include <Python.h>
24 
25 #include "CLG_log.h"
26 
27 #include "BLI_utildefines.h"
28 
29 #include "RNA_types.h"
30 
31 #include "bpy_rna.h"
32 
33 #include "MEM_guardedalloc.h"
34 
35 #include "RNA_access.h"
36 
37 #include "BPY_extern_clog.h"
38 
39 #include "../generic/py_capi_utils.h"
40 
41 #define USE_MATHUTILS
42 
43 #ifdef USE_MATHUTILS
44 # include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */
45 #endif
46 
47 #define MAX_ARRAY_DIMENSION 10
48 
49 struct ItemConvertArgData;
50 
51 typedef void (*ItemConvertFunc)(const struct ItemConvertArgData *arg, PyObject *, char *);
52 typedef int (*ItemTypeCheckFunc)(PyObject *);
53 typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *);
54 typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *);
55 
57  union {
58  struct {
59  int range[2];
61  struct {
62  float range[2];
64  };
65 };
66 
70 typedef struct ItemConvert_FuncArg {
72  struct ItemConvertArgData arg;
74 
75 /*
76  * arr[3][4][5]
77  * 0 1 2 <- dimension index
78  */
79 
80 /*
81  * arr[2] = x
82  *
83  * py_to_array_index(arraydim=0, arrayoffset=0, index=2)
84  * validate_array(lvalue_dim=0)
85  * ... make real index ...
86  */
87 
88 /* arr[3] = x, self->arraydim is 0, lvalue_dim is 1 */
89 /* Ensures that a python sequence has expected number of
90  * items/sub-items and items are of desired type. */
91 static int validate_array_type(PyObject *seq,
92  int dim,
93  int totdim,
94  int dimsize[],
95  const bool is_dynamic,
96  ItemTypeCheckFunc check_item_type,
97  const char *item_type_str,
98  const char *error_prefix)
99 {
100  Py_ssize_t i;
101 
102  /* not the last dimension */
103  if (dim + 1 < totdim) {
104  /* check that a sequence contains dimsize[dim] items */
105  const int seq_size = PySequence_Size(seq);
106  if (seq_size == -1) {
107  PyErr_Format(PyExc_ValueError,
108  "%s sequence expected at dimension %d, not '%s'",
109  error_prefix,
110  dim + 1,
111  Py_TYPE(seq)->tp_name);
112  return -1;
113  }
114  for (i = 0; i < seq_size; i++) {
115  Py_ssize_t item_seq_size;
116  PyObject *item;
117  bool ok = true;
118  item = PySequence_GetItem(seq, i);
119 
120  if (item == NULL) {
121  PyErr_Format(PyExc_TypeError,
122  "%s sequence type '%s' failed to retrieve index %d",
123  error_prefix,
124  Py_TYPE(seq)->tp_name,
125  i);
126  ok = 0;
127  }
128  else if ((item_seq_size = PySequence_Size(item)) == -1) {
129  /* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */
130  PyErr_Format(PyExc_TypeError,
131  "%s expected a sequence of %s, not %s",
132  error_prefix,
133  item_type_str,
134  Py_TYPE(item)->tp_name);
135  ok = 0;
136  }
137  /* arr[3][4][5]
138  * dimsize[1] = 4
139  * dimsize[2] = 5
140  *
141  * dim = 0 */
142  else if (item_seq_size != dimsize[dim + 1]) {
143  /* BLI_snprintf(error_str, error_str_size,
144  * "sequences of dimension %d should contain %d items",
145  * dim + 1, dimsize[dim + 1]); */
146  PyErr_Format(PyExc_ValueError,
147  "%s sequences of dimension %d should contain %d items, not %d",
148  error_prefix,
149  dim + 1,
150  dimsize[dim + 1],
151  item_seq_size);
152  ok = 0;
153  }
154  else if (validate_array_type(item,
155  dim + 1,
156  totdim,
157  dimsize,
158  is_dynamic,
159  check_item_type,
160  item_type_str,
161  error_prefix) == -1) {
162  ok = 0;
163  }
164 
165  Py_XDECREF(item);
166 
167  if (!ok) {
168  return -1;
169  }
170  }
171  }
172  else {
173  /* check that items are of correct type */
174  const int seq_size = PySequence_Size(seq);
175  if (seq_size == -1) {
176  PyErr_Format(PyExc_ValueError,
177  "%s sequence expected at dimension %d, not '%s'",
178  error_prefix,
179  dim + 1,
180  Py_TYPE(seq)->tp_name);
181  return -1;
182  }
183  if ((seq_size != dimsize[dim]) && (is_dynamic == false)) {
184  PyErr_Format(PyExc_ValueError,
185  "%s sequences of dimension %d should contain %d items, not %d",
186  error_prefix,
187  dim,
188  dimsize[dim],
189  seq_size);
190  return -1;
191  }
192 
193  for (i = 0; i < seq_size; i++) {
194  PyObject *item = PySequence_GetItem(seq, i);
195 
196  if (item == NULL) {
197  PyErr_Format(PyExc_TypeError,
198  "%s sequence type '%s' failed to retrieve index %d",
199  error_prefix,
200  Py_TYPE(seq)->tp_name,
201  i);
202  return -1;
203  }
204  if (!check_item_type(item)) {
205  Py_DECREF(item);
206 
207 #if 0
208  BLI_snprintf(
209  error_str, error_str_size, "sequence items should be of type %s", item_type_str);
210 #endif
211  PyErr_Format(PyExc_TypeError,
212  "%s expected sequence items of type %s, not %s",
213  error_prefix,
214  item_type_str,
215  Py_TYPE(item)->tp_name);
216  return -1;
217  }
218 
219  Py_DECREF(item);
220  }
221  }
222 
223  return 0; /* ok */
224 }
225 
226 /* Returns the number of items in a single- or multi-dimensional sequence. */
227 static int count_items(PyObject *seq, int dim)
228 {
229  int totitem = 0;
230 
231  if (dim > 1) {
232  const Py_ssize_t seq_size = PySequence_Size(seq);
233  Py_ssize_t i;
234  for (i = 0; i < seq_size; i++) {
235  PyObject *item = PySequence_GetItem(seq, i);
236  if (item) {
237  const int tot = count_items(item, dim - 1);
238  Py_DECREF(item);
239  if (tot != -1) {
240  totitem += tot;
241  }
242  else {
243  totitem = -1;
244  break;
245  }
246  }
247  else {
248  totitem = -1;
249  break;
250  }
251  }
252  }
253  else {
254  totitem = PySequence_Size(seq);
255  }
256 
257  return totitem;
258 }
259 
260 /* Modifies property array length if needed and PROP_DYNAMIC flag is set. */
261 static int validate_array_length(PyObject *rvalue,
262  PointerRNA *ptr,
263  PropertyRNA *prop,
264  int lvalue_dim,
265  int *r_totitem,
266  const char *error_prefix)
267 {
268  int dimsize[MAX_ARRAY_DIMENSION];
269  int tot, totdim, len;
270 
271  totdim = RNA_property_array_dimension(ptr, prop, dimsize);
272  tot = count_items(rvalue, totdim - lvalue_dim);
273 
274  if (tot == -1) {
275  PyErr_Format(PyExc_ValueError,
276  "%s %.200s.%.200s, error validating the sequence length",
277  error_prefix,
280  return -1;
281  }
282  if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
283  if (RNA_property_array_length(ptr, prop) != tot) {
284 #if 0
285  /* length is flexible */
286  if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) {
287  /* BLI_snprintf(error_str, error_str_size,
288  * "%s.%s: array length cannot be changed to %d",
289  * RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */
290  PyErr_Format(PyExc_ValueError,
291  "%s %s.%s: array length cannot be changed to %d",
292  error_prefix,
295  tot);
296  return -1;
297  }
298 #else
299  *r_totitem = tot;
300  return 0;
301 
302 #endif
303  }
304 
305  len = tot;
306  }
307  else {
308  /* length is a constraint */
309  if (!lvalue_dim) {
311  }
312  /* array item assignment */
313  else {
314  int i;
315 
316  len = 1;
317 
318  /* arr[3][4][5]
319  *
320  * arr[2] = x
321  * dimsize = {4, 5}
322  * dimsize[1] = 4
323  * dimsize[2] = 5
324  * lvalue_dim = 0, totdim = 3
325  *
326  * arr[2][3] = x
327  * lvalue_dim = 1
328  *
329  * arr[2][3][4] = x
330  * lvalue_dim = 2 */
331  for (i = lvalue_dim; i < totdim; i++) {
332  len *= dimsize[i];
333  }
334  }
335 
336  if (tot != len) {
337  /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
338  PyErr_Format(PyExc_ValueError,
339  "%s %.200s.%.200s, sequence must have %d items total, not %d",
340  error_prefix,
343  len,
344  tot);
345  return -1;
346  }
347  }
348 
349  *r_totitem = len;
350 
351  return 0;
352 }
353 
354 static int validate_array(PyObject *rvalue,
355  PointerRNA *ptr,
356  PropertyRNA *prop,
357  int lvalue_dim,
358  ItemTypeCheckFunc check_item_type,
359  const char *item_type_str,
360  int *r_totitem,
361  const char *error_prefix)
362 {
363  int dimsize[MAX_ARRAY_DIMENSION];
364  const int totdim = RNA_property_array_dimension(ptr, prop, dimsize);
365 
366  /* validate type first because length validation may modify property array length */
367 
368 #ifdef USE_MATHUTILS
369  if (lvalue_dim == 0) { /* only valid for first level array */
370  if (MatrixObject_Check(rvalue)) {
371  MatrixObject *pymat = (MatrixObject *)rvalue;
372 
373  if (BaseMath_ReadCallback(pymat) == -1) {
374  return -1;
375  }
376 
377  if (RNA_property_type(prop) != PROP_FLOAT) {
378  PyErr_Format(PyExc_ValueError,
379  "%s %.200s.%.200s, matrix assign to non float array",
380  error_prefix,
383  return -1;
384  }
385  if (totdim != 2) {
386  PyErr_Format(PyExc_ValueError,
387  "%s %.200s.%.200s, matrix assign array with %d dimensions",
388  error_prefix,
391  totdim);
392  return -1;
393  }
394  if (pymat->num_col != dimsize[0] || pymat->num_row != dimsize[1]) {
395  PyErr_Format(PyExc_ValueError,
396  "%s %.200s.%.200s, matrix assign dimension size mismatch, "
397  "is %dx%d, expected be %dx%d",
398  error_prefix,
401  pymat->num_col,
402  pymat->num_row,
403  dimsize[0],
404  dimsize[1]);
405  return -1;
406  }
407 
408  *r_totitem = dimsize[0] * dimsize[1];
409  return 0;
410  }
411  }
412 #endif /* USE_MATHUTILS */
413 
414  {
415  const int prop_flag = RNA_property_flag(prop);
416  if (validate_array_type(rvalue,
417  lvalue_dim,
418  totdim,
419  dimsize,
420  (prop_flag & PROP_DYNAMIC) != 0,
421  check_item_type,
422  item_type_str,
423  error_prefix) == -1) {
424  return -1;
425  }
426 
427  return validate_array_length(rvalue, ptr, prop, lvalue_dim, r_totitem, error_prefix);
428  }
429 }
430 
431 static char *copy_value_single(PyObject *item,
432  PointerRNA *ptr,
433  PropertyRNA *prop,
434  char *data,
435  uint item_size,
436  int *index,
437  const ItemConvert_FuncArg *convert_item,
438  RNA_SetIndexFunc rna_set_index)
439 {
440  if (!data) {
441  union {
442  float fl;
443  int i;
444  } value_buf;
445  char *value = (void *)&value_buf;
446 
447  convert_item->func(&convert_item->arg, item, value);
448  rna_set_index(ptr, prop, *index, value);
449  (*index) += 1;
450  }
451  else {
452  convert_item->func(&convert_item->arg, item, data);
453  data += item_size;
454  }
455 
456  return data;
457 }
458 
459 static char *copy_values(PyObject *seq,
460  PointerRNA *ptr,
461  PropertyRNA *prop,
462  int dim,
463  char *data,
464  uint item_size,
465  int *index,
466  const ItemConvert_FuncArg *convert_item,
467  RNA_SetIndexFunc rna_set_index)
468 {
469  const int totdim = RNA_property_array_dimension(ptr, prop, NULL);
470  const Py_ssize_t seq_size = PySequence_Size(seq);
471  Py_ssize_t i;
472 
473  /* Regarding PySequence_GetItem() failing.
474  *
475  * This should never be NULL since we validated it, _but_ some tricky python
476  * developer could write their own sequence type which succeeds on
477  * validating but fails later somehow, so include checks for safety.
478  */
479 
480  /* Note that 'data can be NULL' */
481 
482  if (seq_size == -1) {
483  return NULL;
484  }
485 
486 #ifdef USE_MATHUTILS
487  if (dim == 0) {
488  if (MatrixObject_Check(seq)) {
489  MatrixObject *pymat = (MatrixObject *)seq;
490  const size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float);
491 
492  /* read callback already done by validate */
493  /* since this is the first iteration we can assume data is allocated */
494  memcpy(data, pymat->matrix, allocsize);
495 
496  /* not really needed but do for completeness */
497  data += allocsize;
498 
499  return data;
500  }
501  }
502 #endif /* USE_MATHUTILS */
503 
504  for (i = 0; i < seq_size; i++) {
505  PyObject *item = PySequence_GetItem(seq, i);
506  if (item) {
507  if (dim + 1 < totdim) {
508  data = copy_values(
509  item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
510  }
511  else {
513  item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
514  }
515 
516  Py_DECREF(item);
517 
518  /* data may be NULL, but the for loop checks */
519  }
520  else {
521  return NULL;
522  }
523  }
524 
525  return data;
526 }
527 
528 static int py_to_array(PyObject *seq,
529  PointerRNA *ptr,
530  PropertyRNA *prop,
531  char *param_data,
532  ItemTypeCheckFunc check_item_type,
533  const char *item_type_str,
534  int item_size,
535  const ItemConvert_FuncArg *convert_item,
536  RNA_SetArrayFunc rna_set_array,
537  const char *error_prefix)
538 {
539  /*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/
540  int totitem;
541  char *data = NULL;
542 
543  /*totdim = RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/
544 
545  if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) ==
546  -1) {
547  return -1;
548  }
549 
550  if (totitem) {
551  /* note: this code is confusing */
552  if (param_data && RNA_property_flag(prop) & PROP_DYNAMIC) {
553  /* not freeing allocated mem, RNA_parameter_list_free() will do this */
554  ParameterDynAlloc *param_alloc = (ParameterDynAlloc *)param_data;
555  param_alloc->array_tot = (int)totitem;
556 
557  /* freeing param list will free */
558  param_alloc->array = MEM_callocN(item_size * totitem, "py_to_array dyn");
559 
560  data = param_alloc->array;
561  }
562  else if (param_data) {
563  data = param_data;
564  }
565  else {
566  data = PyMem_MALLOC(item_size * totitem);
567  }
568 
569  /* will only fail in very rare cases since we already validated the
570  * python data, the check here is mainly for completeness. */
571  if (copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) {
572  if (param_data == NULL) {
573  /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
574  rna_set_array(ptr, prop, data);
575  PyMem_FREE(data);
576  }
577  }
578  else {
579  if (param_data == NULL) {
580  PyMem_FREE(data);
581  }
582 
583  PyErr_Format(PyExc_TypeError,
584  "%s internal error parsing sequence of type '%s' after successful validation",
585  error_prefix,
586  Py_TYPE(seq)->tp_name);
587  return -1;
588  }
589  }
590 
591  return 0;
592 }
593 
594 static int py_to_array_index(PyObject *py,
595  PointerRNA *ptr,
596  PropertyRNA *prop,
597  int lvalue_dim,
598  int arrayoffset,
599  int index,
600  ItemTypeCheckFunc check_item_type,
601  const char *item_type_str,
602  const ItemConvert_FuncArg *convert_item,
603  RNA_SetIndexFunc rna_set_index,
604  const char *error_prefix)
605 {
606  int totdim, dimsize[MAX_ARRAY_DIMENSION];
607  int totitem, i;
608 
609  totdim = RNA_property_array_dimension(ptr, prop, dimsize);
610 
611  /* convert index */
612 
613  /* arr[3][4][5]
614  *
615  * arr[2] = x
616  * lvalue_dim = 0, index = 0 + 2 * 4 * 5
617  *
618  * arr[2][3] = x
619  * lvalue_dim = 1, index = 40 + 3 * 5 */
620 
621  lvalue_dim++;
622 
623  for (i = lvalue_dim; i < totdim; i++) {
624  index *= dimsize[i];
625  }
626 
627  index += arrayoffset;
628 
629  if (lvalue_dim == totdim) { /* single item, assign directly */
630  if (!check_item_type(py)) {
631  PyErr_Format(PyExc_TypeError,
632  "%s %.200s.%.200s, expected a %s type, not %s",
633  error_prefix,
636  item_type_str,
637  Py_TYPE(py)->tp_name);
638  return -1;
639  }
640  copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
641  }
642  else {
643  if (validate_array(
644  py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) ==
645  -1) {
646  return -1;
647  }
648 
649  if (totitem) {
650  copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index);
651  }
652  }
653  return 0;
654 }
655 
656 static void py_to_float(const struct ItemConvertArgData *arg, PyObject *py, char *data)
657 {
658  const float *range = arg->float_data.range;
659  float value = (float)PyFloat_AsDouble(py);
660  CLAMP(value, range[0], range[1]);
661  *(float *)data = value;
662 }
663 
664 static void py_to_int(const struct ItemConvertArgData *arg, PyObject *py, char *data)
665 {
666  const int *range = arg->int_data.range;
667  int value = PyC_Long_AsI32(py);
668  CLAMP(value, range[0], range[1]);
669  *(int *)data = value;
670 }
671 
672 static void py_to_bool(const struct ItemConvertArgData *UNUSED(arg), PyObject *py, char *data)
673 {
674  *(bool *)data = (bool)PyObject_IsTrue(py);
675 }
676 
677 static int py_float_check(PyObject *py)
678 {
679  /* accept both floats and integers */
680  return PyNumber_Check(py);
681 }
682 
683 static int py_int_check(PyObject *py)
684 {
685  /* accept only integers */
686  return PyLong_Check(py);
687 }
688 
689 static int py_bool_check(PyObject *py)
690 {
691  return PyBool_Check(py);
692 }
693 
694 static void float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
695 {
696  RNA_property_float_set_index(ptr, prop, index, *(float *)value);
697 }
698 
699 static void int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
700 {
701  RNA_property_int_set_index(ptr, prop, index, *(int *)value);
702 }
703 
704 static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
705 {
706  RNA_property_boolean_set_index(ptr, prop, index, *(bool *)value);
707 }
708 
710  PropertyRNA *prop,
711  ItemConvert_FuncArg *convert_item)
712 {
713  float *range = convert_item->arg.float_data.range;
714  convert_item->func = py_to_float;
715  RNA_property_float_range(ptr, prop, &range[0], &range[1]);
716 }
717 
719  PropertyRNA *prop,
720  ItemConvert_FuncArg *convert_item)
721 {
722  int *range = convert_item->arg.int_data.range;
723  convert_item->func = py_to_int;
724  RNA_property_int_range(ptr, prop, &range[0], &range[1]);
725 }
726 
728  PropertyRNA *UNUSED(prop),
729  ItemConvert_FuncArg *convert_item)
730 {
731  convert_item->func = py_to_bool;
732 }
733 
735  PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
736 {
737  int ret;
738  switch (RNA_property_type(prop)) {
739  case PROP_FLOAT: {
740  ItemConvert_FuncArg convert_item;
741  convert_item_init_float(ptr, prop, &convert_item);
742 
743  ret = py_to_array(py,
744  ptr,
745  prop,
746  param_data,
748  "float",
749  sizeof(float),
750  &convert_item,
752  error_prefix);
753  break;
754  }
755  case PROP_INT: {
756  ItemConvert_FuncArg convert_item;
757  convert_item_init_int(ptr, prop, &convert_item);
758 
759  ret = py_to_array(py,
760  ptr,
761  prop,
762  param_data,
763  py_int_check,
764  "int",
765  sizeof(int),
766  &convert_item,
768  error_prefix);
769  break;
770  }
771  case PROP_BOOLEAN: {
772  ItemConvert_FuncArg convert_item;
773  convert_item_init_bool(ptr, prop, &convert_item);
774 
775  ret = py_to_array(py,
776  ptr,
777  prop,
778  param_data,
780  "boolean",
781  sizeof(bool),
782  &convert_item,
784  error_prefix);
785  break;
786  }
787  default: {
788  PyErr_SetString(PyExc_TypeError, "not an array type");
789  ret = -1;
790  break;
791  }
792  }
793 
794  return ret;
795 }
796 
798  PropertyRNA *prop,
799  int arraydim,
800  int arrayoffset,
801  int index,
802  PyObject *py,
803  const char *error_prefix)
804 {
805  int ret;
806  switch (RNA_property_type(prop)) {
807  case PROP_FLOAT: {
808  ItemConvert_FuncArg convert_item;
809  convert_item_init_float(ptr, prop, &convert_item);
810 
811  ret = py_to_array_index(py,
812  ptr,
813  prop,
814  arraydim,
815  arrayoffset,
816  index,
818  "float",
819  &convert_item,
821  error_prefix);
822  break;
823  }
824  case PROP_INT: {
825  ItemConvert_FuncArg convert_item;
826  convert_item_init_int(ptr, prop, &convert_item);
827 
828  ret = py_to_array_index(py,
829  ptr,
830  prop,
831  arraydim,
832  arrayoffset,
833  index,
834  py_int_check,
835  "int",
836  &convert_item,
838  error_prefix);
839  break;
840  }
841  case PROP_BOOLEAN: {
842  ItemConvert_FuncArg convert_item;
843  convert_item_init_bool(ptr, prop, &convert_item);
844 
845  ret = py_to_array_index(py,
846  ptr,
847  prop,
848  arraydim,
849  arrayoffset,
850  index,
852  "boolean",
853  &convert_item,
855  error_prefix);
856  break;
857  }
858  default: {
859  PyErr_SetString(PyExc_TypeError, "not an array type");
860  ret = -1;
861  break;
862  }
863  }
864 
865  return ret;
866 }
867 
868 PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index)
869 {
870  PyObject *item;
871 
872  switch (RNA_property_type(prop)) {
873  case PROP_FLOAT:
874  item = PyFloat_FromDouble(RNA_property_float_get_index(ptr, prop, index));
875  break;
876  case PROP_BOOLEAN:
877  item = PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index));
878  break;
879  case PROP_INT:
880  item = PyLong_FromLong(RNA_property_int_get_index(ptr, prop, index));
881  break;
882  default:
883  PyErr_SetString(PyExc_TypeError, "not an array type");
884  item = NULL;
885  break;
886  }
887 
888  return item;
889 }
890 
891 #if 0
892 /* XXX this is not used (and never will?) */
893 /* Given an array property, creates an N-dimensional tuple of values. */
894 static PyObject *pyrna_py_from_array_internal(PointerRNA *ptr,
895  PropertyRNA *prop,
896  int dim,
897  int *index)
898 {
899  PyObject *tuple;
900  int i, len;
901  int totdim = RNA_property_array_dimension(ptr, prop, NULL);
902 
904 
905  tuple = PyTuple_New(len);
906 
907  for (i = 0; i < len; i++) {
908  PyObject *item;
909 
910  if (dim + 1 < totdim) {
911  item = pyrna_py_from_array_internal(ptr, prop, dim + 1, index);
912  }
913  else {
914  item = pyrna_array_index(ptr, prop, *index);
915  *index = *index + 1;
916  }
917 
918  if (!item) {
919  Py_DECREF(tuple);
920  return NULL;
921  }
922 
923  PyTuple_SET_ITEM(tuple, i, item);
924  }
925 
926  return tuple;
927 }
928 #endif
929 
931  PointerRNA *ptr,
932  PropertyRNA *prop,
933  int index)
934 {
935  int totdim, arraydim, arrayoffset, dimsize[MAX_ARRAY_DIMENSION], i, len;
937 
938  arraydim = self ? self->arraydim : 0;
939  arrayoffset = self ? self->arrayoffset : 0;
940 
941  /* just in case check */
942  len = RNA_property_multi_array_length(ptr, prop, arraydim);
943  if (index >= len || index < 0) {
944  /* this shouldn't happen because higher level funcs must check for invalid index */
945  CLOG_WARN(BPY_LOG_RNA, "invalid index %d for array with length=%d", index, len);
946 
947  PyErr_SetString(PyExc_IndexError, "out of range");
948  return NULL;
949  }
950 
951  totdim = RNA_property_array_dimension(ptr, prop, dimsize);
952 
953  if (arraydim + 1 < totdim) {
955  ret->arraydim = arraydim + 1;
956 
957  /* arr[3][4][5]
958  *
959  * x = arr[2]
960  * index = 0 + 2 * 4 * 5
961  *
962  * x = arr[2][3]
963  * index = offset + 3 * 5 */
964 
965  for (i = arraydim + 1; i < totdim; i++) {
966  index *= dimsize[i];
967  }
968 
969  ret->arrayoffset = arrayoffset + index;
970  }
971  else {
972  index = arrayoffset + index;
973  ret = (BPy_PropertyArrayRNA *)pyrna_array_index(ptr, prop, index);
974  }
975 
976  return (PyObject *)ret;
977 }
978 
980 {
981  PyObject *ret;
982 
984 
985  /* is this a maths object? */
986  if (ret) {
987  return ret;
988  }
989 
990  return pyrna_prop_CreatePyObject(ptr, prop);
991 }
992 
993 /* TODO, multi-dimensional arrays */
994 int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
995 {
996  const int len = RNA_property_array_length(ptr, prop);
997  int type;
998  int i;
999 
1000  if (len == 0) {
1001  /* possible with dynamic arrays */
1002  return 0;
1003  }
1004 
1005  if (RNA_property_array_dimension(ptr, prop, NULL) > 1) {
1006  PyErr_SetString(PyExc_TypeError, "PropertyRNA - multi dimensional arrays not supported yet");
1007  return -1;
1008  }
1009 
1010  type = RNA_property_type(prop);
1011 
1012  switch (type) {
1013  case PROP_FLOAT: {
1014  const float value_f = PyFloat_AsDouble(value);
1015  if (value_f == -1 && PyErr_Occurred()) {
1016  PyErr_Clear();
1017  return 0;
1018  }
1019 
1020  float tmp[32];
1021  float *tmp_arr;
1022 
1023  if (len * sizeof(float) > sizeof(tmp)) {
1024  tmp_arr = PyMem_MALLOC(len * sizeof(float));
1025  }
1026  else {
1027  tmp_arr = tmp;
1028  }
1029 
1030  RNA_property_float_get_array(ptr, prop, tmp_arr);
1031 
1032  for (i = 0; i < len; i++) {
1033  if (tmp_arr[i] == value_f) {
1034  break;
1035  }
1036  }
1037 
1038  if (tmp_arr != tmp) {
1039  PyMem_FREE(tmp_arr);
1040  }
1041 
1042  return i < len ? 1 : 0;
1043 
1044  break;
1045  }
1046  case PROP_INT: {
1047  const int value_i = PyC_Long_AsI32(value);
1048  if (value_i == -1 && PyErr_Occurred()) {
1049  PyErr_Clear();
1050  return 0;
1051  }
1052 
1053  int tmp[32];
1054  int *tmp_arr;
1055 
1056  if (len * sizeof(int) > sizeof(tmp)) {
1057  tmp_arr = PyMem_MALLOC(len * sizeof(int));
1058  }
1059  else {
1060  tmp_arr = tmp;
1061  }
1062 
1063  RNA_property_int_get_array(ptr, prop, tmp_arr);
1064 
1065  for (i = 0; i < len; i++) {
1066  if (tmp_arr[i] == value_i) {
1067  break;
1068  }
1069  }
1070 
1071  if (tmp_arr != tmp) {
1072  PyMem_FREE(tmp_arr);
1073  }
1074 
1075  return i < len ? 1 : 0;
1076 
1077  break;
1078  }
1079  case PROP_BOOLEAN: {
1080  const int value_i = PyC_Long_AsBool(value);
1081  if (value_i == -1 && PyErr_Occurred()) {
1082  PyErr_Clear();
1083  return 0;
1084  }
1085 
1086  bool tmp[32];
1087  bool *tmp_arr;
1088 
1089  if (len * sizeof(bool) > sizeof(tmp)) {
1090  tmp_arr = PyMem_MALLOC(len * sizeof(bool));
1091  }
1092  else {
1093  tmp_arr = tmp;
1094  }
1095 
1096  RNA_property_boolean_get_array(ptr, prop, tmp_arr);
1097 
1098  for (i = 0; i < len; i++) {
1099  if (tmp_arr[i] == value_i) {
1100  break;
1101  }
1102  }
1103 
1104  if (tmp_arr != tmp) {
1105  PyMem_FREE(tmp_arr);
1106  }
1107 
1108  return i < len ? 1 : 0;
1109 
1110  break;
1111  }
1112  }
1113 
1114  /* should never reach this */
1115  PyErr_SetString(PyExc_TypeError, "PropertyRNA - type not in float/bool/int");
1116  return -1;
1117 }
typedef float(TangentPoint)[2]
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
struct CLG_LogRef * BPY_LOG_RNA
#define CLOG_WARN(clg_ref,...)
Definition: CLG_log.h:203
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
@ PROP_FLOAT
Definition: RNA_types.h:75
@ PROP_BOOLEAN
Definition: RNA_types.h:73
@ PROP_INT
Definition: RNA_types.h:74
@ PROP_DYNAMIC
Definition: RNA_types.h:275
PyObject * pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop)
Definition: bpy_rna.c:7560
PyObject * pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
Definition: bpy_rna.c:644
int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix)
static void py_to_int(const struct ItemConvertArgData *arg, PyObject *py, char *data)
static void int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
#define MAX_ARRAY_DIMENSION
Definition: bpy_rna_array.c:47
static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int *r_totitem, const char *error_prefix)
static void convert_item_init_int(PointerRNA *ptr, PropertyRNA *prop, ItemConvert_FuncArg *convert_item)
static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[], const bool is_dynamic, ItemTypeCheckFunc check_item_type, const char *item_type_str, const char *error_prefix)
Definition: bpy_rna_array.c:91
static int py_float_check(PyObject *py)
static void convert_item_init_bool(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), ItemConvert_FuncArg *convert_item)
static int py_int_check(PyObject *py)
int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value)
static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
void(* ItemConvertFunc)(const struct ItemConvertArgData *arg, PyObject *, char *)
Definition: bpy_rna_array.c:51
int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix)
static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *r_totitem, const char *error_prefix)
PyObject * pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index)
static char * copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int dim, char *data, uint item_size, int *index, const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index)
static void float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value)
static int count_items(PyObject *seq, int dim)
static void py_to_float(const struct ItemConvertArgData *arg, PyObject *py, char *data)
static void convert_item_init_float(PointerRNA *ptr, PropertyRNA *prop, ItemConvert_FuncArg *convert_item)
void(* RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *)
Definition: bpy_rna_array.c:54
PyObject * pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop)
static void py_to_bool(const struct ItemConvertArgData *UNUSED(arg), PyObject *py, char *data)
struct ItemConvert_FuncArg ItemConvert_FuncArg
PyObject * pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index)
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, const ItemConvert_FuncArg *convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
static char * copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, char *data, uint item_size, int *index, const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index)
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, const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
void(* RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *)
Definition: bpy_rna_array.c:53
int(* ItemTypeCheckFunc)(PyObject *)
Definition: bpy_rna_array.c:52
static int py_bool_check(PyObject *py)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
#define BaseMath_ReadCallback(_self)
Definition: mathutils.h:128
#define MatrixObject_Check(v)
int PyC_Long_AsBool(PyObject *value)
return ret
const char * RNA_struct_identifier(const StructRNA *type)
Definition: rna_access.c:723
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
Definition: rna_access.c:2530
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:3033
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2759
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1145
void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
Definition: rna_access.c:3190
int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
Definition: rna_access.c:1229
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:3108
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
Definition: rna_access.c:1426
void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
Definition: rna_access.c:2420
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1155
void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
Definition: rna_access.c:2830
int RNA_property_flag(PropertyRNA *prop)
Definition: rna_access.c:1192
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1218
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
Definition: rna_access.c:3132
void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
Definition: rna_access.c:2783
void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
Definition: rna_access.c:2690
void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
Definition: rna_access.c:1335
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_access.c:2453
int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
Definition: rna_access.c:1241
void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
Definition: rna_access.c:2482
struct ItemConvertArgData::@1127::@1129 int_data
struct ItemConvertArgData::@1127::@1130 float_data
struct ItemConvertArgData arg
Definition: bpy_rna_array.c:72
ItemConvertFunc func
Definition: bpy_rna_array.c:71
intptr_t array_tot
Definition: RNA_types.h:541
struct StructRNA * type
Definition: RNA_types.h:51
uint len
PointerRNA * ptr
Definition: wm_files.c:3157