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