Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python/intern/bpy_props.c')
-rw-r--r--source/blender/python/intern/bpy_props.c2640
1 files changed, 1525 insertions, 1115 deletions
diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c
index 14e25e02d84..a84d920d47d 100644
--- a/source/blender/python/intern/bpy_props.c
+++ b/source/blender/python/intern/bpy_props.c
@@ -492,6 +492,145 @@ static void bpy_prop_assign_flag_override(PropertyRNA *prop, const int flag_over
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Multi-Dimensional Property Utilities
+ * \{ */
+
+struct BPyPropArrayLength {
+ int len_total;
+ /** Ignore `dims` when `dims_len == 0`. */
+ int dims[RNA_MAX_ARRAY_DIMENSION];
+ int dims_len;
+};
+
+/**
+ * Use with #PyArg_ParseTuple's `O&` formatting.
+ */
+static int bpy_prop_array_length_parse(PyObject *o, void *p)
+{
+ struct BPyPropArrayLength *array_len_info = p;
+
+ if (PyLong_CheckExact(o)) {
+ int size;
+ if (((size = PyLong_AsLong(o)) == -1)) {
+ PyErr_Format(
+ PyExc_ValueError, "expected number or sequence of numbers, got %s", Py_TYPE(o)->tp_name);
+ return 0;
+ }
+ if (size < 1 || size > PYRNA_STACK_ARRAY) {
+ PyErr_Format(
+ PyExc_TypeError, "(size=%d) must be between 1 and " STRINGIFY(PYRNA_STACK_ARRAY), size);
+ return 0;
+ }
+ array_len_info->len_total = size;
+
+ /* Don't use this value. */
+ array_len_info->dims_len = 0;
+ }
+ else {
+ PyObject *seq_fast;
+ if (!(seq_fast = PySequence_Fast(o, "size must be a number of a sequence of numbers"))) {
+ return 0;
+ }
+ const int seq_len = PySequence_Fast_GET_SIZE(seq_fast);
+ if (seq_len < 1 || seq_len > RNA_MAX_ARRAY_DIMENSION) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "(len(size)=%d) length must be between 1 and " STRINGIFY(RNA_MAX_ARRAY_DIMENSION),
+ seq_len);
+ Py_DECREF(seq_fast);
+ return 0;
+ }
+
+ PyObject **seq_items = PySequence_Fast_ITEMS(seq_fast);
+ for (int i = 0; i < seq_len; i++) {
+ int size;
+ if (((size = PyLong_AsLong(seq_items[i])) == -1)) {
+ Py_DECREF(seq_fast);
+ PyErr_Format(PyExc_ValueError,
+ "expected number in sequence, got %s at index %d",
+ Py_TYPE(o)->tp_name,
+ i);
+ return 0;
+ }
+ if (size < 1 || size > PYRNA_STACK_ARRAY) {
+ Py_DECREF(seq_fast);
+ PyErr_Format(PyExc_TypeError,
+ "(size[%d]=%d) must be between 1 and " STRINGIFY(PYRNA_STACK_ARRAY),
+ i,
+ size);
+ return 0;
+ }
+
+ array_len_info->dims[i] = size;
+ array_len_info->dims_len = seq_len;
+ }
+ }
+ return 1;
+}
+
+/**
+ * Return -1 on error.
+ */
+static int bpy_prop_array_from_py_with_dims(void *values,
+ size_t values_elem_size,
+ PyObject *py_values,
+ const struct BPyPropArrayLength *array_len_info,
+ const PyTypeObject *type,
+ const char *error_str)
+{
+ if (array_len_info->dims_len == 0) {
+ return PyC_AsArray(
+ values, values_elem_size, py_values, array_len_info->len_total, type, error_str);
+ }
+ const int *dims = array_len_info->dims;
+ const int dims_len = array_len_info->dims_len;
+ return PyC_AsArray_Multi(values, values_elem_size, py_values, dims, dims_len, type, error_str);
+}
+
+static bool bpy_prop_array_is_matrix_compatible_ex(int subtype,
+ const struct BPyPropArrayLength *array_len_info)
+{
+ return ((subtype == PROP_MATRIX) && (array_len_info->dims_len == 2) &&
+ ((array_len_info->dims[0] >= 2) && (array_len_info->dims[0] >= 4)) &&
+ ((array_len_info->dims[1] >= 2) && (array_len_info->dims[1] >= 4)));
+}
+
+static bool bpy_prop_array_is_matrix_compatible(PropertyRNA *prop,
+ const struct BPyPropArrayLength *array_len_info)
+{
+ BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
+ return bpy_prop_array_is_matrix_compatible_ex(RNA_property_subtype(prop), array_len_info);
+}
+
+/**
+ * Needed since the internal storage of matrices swaps row/column.
+ */
+static void bpy_prop_array_matrix_swap_row_column_vn_vn(
+ float *values_dst, const float *values_src, const struct BPyPropArrayLength *array_len_info)
+{
+ BLI_assert(values_dst != values_src);
+ const int dim0 = array_len_info->dims[0], dim1 = array_len_info->dims[1];
+ BLI_assert(dim0 <= 4 && dim1 <= 4);
+ for (int i = 0; i < dim0; i++) {
+ for (int j = 0; j < dim1; j++) {
+ values_dst[(j * dim0) + i] = values_src[(i * dim1) + j];
+ }
+ }
+}
+
+static void bpy_prop_array_matrix_swap_row_column_vn(
+ float *values, const struct BPyPropArrayLength *array_len_info)
+{
+ const int dim0 = array_len_info->dims[0], dim1 = array_len_info->dims[1];
+ BLI_assert(dim0 <= 4 && dim1 <= 4);
+ float values_orig[4 * 4];
+ memcpy(values_orig, values, sizeof(float) * (dim0 * dim1));
+ bpy_prop_array_matrix_swap_row_column_vn_vn(values, values_orig, array_len_info);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Shared Property Callbacks
*
* Unique data is accessed via #RNA_property_py_data_get
@@ -687,7 +826,10 @@ static void bpy_prop_boolean_array_get_fn(struct PointerRNA *ptr,
PyGILState_STATE gilstate;
bool use_gil;
const bool is_write_ok = pyrna_write_check();
+ bool is_values_set = false;
int i, len = RNA_property_array_length(ptr, prop);
+ struct BPyPropArrayLength array_len_info = {.len_total = len};
+ array_len_info.dims_len = RNA_property_array_dimension(ptr, prop, array_len_info.dims);
BLI_assert(prop_store != NULL);
@@ -711,25 +853,25 @@ static void bpy_prop_boolean_array_get_fn(struct PointerRNA *ptr,
Py_DECREF(args);
- if (ret == NULL) {
- PyC_Err_PrintWithFunc(py_func);
-
- for (i = 0; i < len; i++) {
- values[i] = false;
- }
- }
- else {
- if (PyC_AsArray(values, ret, len, &PyBool_Type, false, "BoolVectorProperty get") == -1) {
+ if (ret != NULL) {
+ if (bpy_prop_array_from_py_with_dims(values,
+ sizeof(*values),
+ ret,
+ &array_len_info,
+ &PyBool_Type,
+ "BoolVectorProperty get callback") == -1) {
PyC_Err_PrintWithFunc(py_func);
-
- for (i = 0; i < len; i++) {
- values[i] = false;
- }
-
- /* PyC_AsArray decrements refcount internally on error */
}
else {
- Py_DECREF(ret);
+ is_values_set = true;
+ }
+ Py_DECREF(ret);
+ }
+
+ if (is_values_set == false) {
+ /* This is the flattened length for multi-dimensional arrays. */
+ for (i = 0; i < len; i++) {
+ values[i] = false;
}
}
@@ -756,6 +898,8 @@ static void bpy_prop_boolean_array_set_fn(struct PointerRNA *ptr,
bool use_gil;
const bool is_write_ok = pyrna_write_check();
const int len = RNA_property_array_length(ptr, prop);
+ struct BPyPropArrayLength array_len_info = {.len_total = len};
+ array_len_info.dims_len = RNA_property_array_dimension(ptr, prop, array_len_info.dims);
BLI_assert(prop_store != NULL);
@@ -775,7 +919,13 @@ static void bpy_prop_boolean_array_set_fn(struct PointerRNA *ptr,
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
- py_values = PyC_Tuple_PackArray_Bool(values, len);
+ if (array_len_info.dims_len == 0) {
+ py_values = PyC_Tuple_PackArray_Bool(values, len);
+ }
+ else {
+ py_values = PyC_Tuple_PackArray_Multi_Bool(
+ values, array_len_info.dims, array_len_info.dims_len);
+ }
PyTuple_SET_ITEM(args, 1, py_values);
ret = PyObject_CallObject(py_func, args);
@@ -937,7 +1087,10 @@ static void bpy_prop_int_array_get_fn(struct PointerRNA *ptr,
PyGILState_STATE gilstate;
bool use_gil;
const bool is_write_ok = pyrna_write_check();
+ bool is_values_set = false;
int i, len = RNA_property_array_length(ptr, prop);
+ struct BPyPropArrayLength array_len_info = {.len_total = len};
+ array_len_info.dims_len = RNA_property_array_dimension(ptr, prop, array_len_info.dims);
BLI_assert(prop_store != NULL);
@@ -961,25 +1114,25 @@ static void bpy_prop_int_array_get_fn(struct PointerRNA *ptr,
Py_DECREF(args);
- if (ret == NULL) {
- PyC_Err_PrintWithFunc(py_func);
-
- for (i = 0; i < len; i++) {
- values[i] = 0;
- }
- }
- else {
- if (PyC_AsArray(values, ret, len, &PyLong_Type, false, "IntVectorProperty get") == -1) {
+ if (ret != NULL) {
+ if (bpy_prop_array_from_py_with_dims(values,
+ sizeof(*values),
+ ret,
+ &array_len_info,
+ &PyLong_Type,
+ "IntVectorProperty get callback") == -1) {
PyC_Err_PrintWithFunc(py_func);
-
- for (i = 0; i < len; i++) {
- values[i] = 0;
- }
-
- /* PyC_AsArray decrements refcount internally on error */
}
else {
- Py_DECREF(ret);
+ is_values_set = true;
+ }
+ Py_DECREF(ret);
+ }
+
+ if (is_values_set == false) {
+ /* This is the flattened length for multi-dimensional arrays. */
+ for (i = 0; i < len; i++) {
+ values[i] = 0;
}
}
@@ -1006,6 +1159,8 @@ static void bpy_prop_int_array_set_fn(struct PointerRNA *ptr,
bool use_gil;
const bool is_write_ok = pyrna_write_check();
const int len = RNA_property_array_length(ptr, prop);
+ struct BPyPropArrayLength array_len_info = {.len_total = len};
+ array_len_info.dims_len = RNA_property_array_dimension(ptr, prop, array_len_info.dims);
BLI_assert(prop_store != NULL);
@@ -1025,7 +1180,14 @@ static void bpy_prop_int_array_set_fn(struct PointerRNA *ptr,
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
- py_values = PyC_Tuple_PackArray_I32(values, len);
+ if (array_len_info.dims_len == 0) {
+ py_values = PyC_Tuple_PackArray_I32(values, len);
+ }
+ else {
+ py_values = PyC_Tuple_PackArray_Multi_I32(
+ values, array_len_info.dims, array_len_info.dims_len);
+ }
+
PyTuple_SET_ITEM(args, 1, py_values);
ret = PyObject_CallObject(py_func, args);
@@ -1187,7 +1349,10 @@ static void bpy_prop_float_array_get_fn(struct PointerRNA *ptr,
PyGILState_STATE gilstate;
bool use_gil;
const bool is_write_ok = pyrna_write_check();
+ bool is_values_set = false;
int i, len = RNA_property_array_length(ptr, prop);
+ struct BPyPropArrayLength array_len_info = {.len_total = len};
+ array_len_info.dims_len = RNA_property_array_dimension(ptr, prop, array_len_info.dims);
BLI_assert(prop_store != NULL);
@@ -1211,25 +1376,29 @@ static void bpy_prop_float_array_get_fn(struct PointerRNA *ptr,
Py_DECREF(args);
- if (ret == NULL) {
- PyC_Err_PrintWithFunc(py_func);
-
- for (i = 0; i < len; i++) {
- values[i] = 0.0f;
- }
- }
- else {
- if (PyC_AsArray(values, ret, len, &PyFloat_Type, false, "FloatVectorProperty get") == -1) {
+ if (ret != NULL) {
+ if (bpy_prop_array_from_py_with_dims(values,
+ sizeof(*values),
+ ret,
+ &array_len_info,
+ &PyFloat_Type,
+ "FloatVectorProperty get callback") == -1) {
PyC_Err_PrintWithFunc(py_func);
-
- for (i = 0; i < len; i++) {
- values[i] = 0.0f;
- }
-
- /* PyC_AsArray decrements refcount internally on error */
}
else {
- Py_DECREF(ret);
+ /* Only for float types. */
+ if (bpy_prop_array_is_matrix_compatible(prop, &array_len_info)) {
+ bpy_prop_array_matrix_swap_row_column_vn(values, &array_len_info);
+ }
+ is_values_set = true;
+ }
+ Py_DECREF(ret);
+ }
+
+ if (is_values_set == false) {
+ /* This is the flattened length for multi-dimensional arrays. */
+ for (i = 0; i < len; i++) {
+ values[i] = 0.0f;
}
}
@@ -1256,6 +1425,8 @@ static void bpy_prop_float_array_set_fn(struct PointerRNA *ptr,
bool use_gil;
const bool is_write_ok = pyrna_write_check();
const int len = RNA_property_array_length(ptr, prop);
+ struct BPyPropArrayLength array_len_info = {.len_total = len};
+ array_len_info.dims_len = RNA_property_array_dimension(ptr, prop, array_len_info.dims);
BLI_assert(prop_store != NULL);
@@ -1275,7 +1446,14 @@ static void bpy_prop_float_array_set_fn(struct PointerRNA *ptr,
self = pyrna_struct_as_instance(ptr);
PyTuple_SET_ITEM(args, 0, self);
- py_values = PyC_Tuple_PackArray_F32(values, len);
+ if (array_len_info.dims_len == 0) {
+ py_values = PyC_Tuple_PackArray_F32(values, len);
+ }
+ else {
+ /* No need for matrix column/row swapping here unless the matrix data is read directly. */
+ py_values = PyC_Tuple_PackArray_Multi_F32(
+ values, array_len_info.dims, array_len_info.dims_len);
+ }
PyTuple_SET_ITEM(args, 1, py_values);
ret = PyObject_CallObject(py_func, args);
@@ -1720,9 +1898,9 @@ static int icon_id_from_name(const char *name)
}
static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
- PyObject *def,
- int *defvalue,
- const bool is_enum_flag)
+ const bool is_enum_flag,
+ PyObject *default_py,
+ int *r_default_value)
{
EnumPropertyItem *items;
PyObject *item;
@@ -1730,9 +1908,9 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
Py_ssize_t totbuf = 0;
int i;
- short def_used = 0;
- const char *def_string_cmp = NULL;
- int def_int_cmp = 0;
+ short default_used = 0;
+ const char *default_str_cmp = NULL;
+ int default_int_cmp = 0;
if (is_enum_flag) {
if (seq_len > RNA_ENUM_BITFLAG_SIZE) {
@@ -1741,23 +1919,23 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
RNA_ENUM_BITFLAG_SIZE) " members for a ENUM_FLAG type property");
return NULL;
}
- if (def && !PySet_Check(def)) {
+ if (default_py && !PySet_Check(default_py)) {
PyErr_Format(PyExc_TypeError,
"EnumProperty(...): default option must be a 'set' "
"type when ENUM_FLAG is enabled, not a '%.200s'",
- Py_TYPE(def)->tp_name);
+ Py_TYPE(default_py)->tp_name);
return NULL;
}
}
else {
- if (def) {
- if (!py_long_as_int(def, &def_int_cmp)) {
- def_string_cmp = PyUnicode_AsUTF8(def);
- if (def_string_cmp == NULL) {
+ if (default_py) {
+ if (!py_long_as_int(default_py, &default_int_cmp)) {
+ default_str_cmp = PyUnicode_AsUTF8(default_py);
+ if (default_str_cmp == NULL) {
PyErr_Format(PyExc_TypeError,
"EnumProperty(...): default option must be a 'str' or 'int' "
"type when ENUM_FLAG is disabled, not a '%.200s'",
- Py_TYPE(def)->tp_name);
+ Py_TYPE(default_py)->tp_name);
return NULL;
}
}
@@ -1765,7 +1943,7 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
}
/* blank value */
- *defvalue = 0;
+ *r_default_value = 0;
items = MEM_callocN(sizeof(EnumPropertyItem) * (seq_len + 1), "enum_items_from_py1");
@@ -1779,7 +1957,7 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
item = seq_fast_items[i];
- if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) &&
+ if (PyTuple_CheckExact(item) && (item_size = PyTuple_GET_SIZE(item)) &&
(item_size >= 3 && item_size <= 5) &&
(tmp.identifier = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) &&
(tmp.name = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) &&
@@ -1794,9 +1972,9 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
tmp.value = 1 << i;
}
- if (def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) {
- *defvalue |= tmp.value;
- def_used++;
+ if (default_py && PySet_Contains(default_py, PyTuple_GET_ITEM(item, 0))) {
+ *r_default_value |= tmp.value;
+ default_used++;
}
}
else {
@@ -1804,11 +1982,11 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
tmp.value = i;
}
- if (def && def_used == 0) {
- if ((def_string_cmp != NULL && STREQ(def_string_cmp, tmp.identifier)) ||
- (def_string_cmp == NULL && def_int_cmp == tmp.value)) {
- *defvalue = tmp.value;
- def_used++; /* only ever 1 */
+ if (default_py && default_used == 0) {
+ if ((default_str_cmp != NULL && STREQ(default_str_cmp, tmp.identifier)) ||
+ (default_str_cmp == NULL && default_int_cmp == tmp.value)) {
+ *r_default_value = tmp.value;
+ default_used++; /* only ever 1 */
}
}
}
@@ -1838,28 +2016,28 @@ static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast,
if (is_enum_flag) {
/* strict check that all set members were used */
- if (def && def_used != PySet_GET_SIZE(def)) {
+ if (default_py && default_used != PySet_GET_SIZE(default_py)) {
MEM_freeN(items);
PyErr_Format(PyExc_TypeError,
"EnumProperty(..., default={...}): set has %d unused member(s)",
- PySet_GET_SIZE(def) - def_used);
+ PySet_GET_SIZE(default_py) - default_used);
return NULL;
}
}
else {
- if (def && def_used == 0) {
+ if (default_py && default_used == 0) {
MEM_freeN(items);
- if (def_string_cmp) {
+ if (default_str_cmp) {
PyErr_Format(PyExc_TypeError,
"EnumProperty(..., default=\'%s\'): not found in enum members",
- def_string_cmp);
+ default_str_cmp);
}
else {
PyErr_Format(PyExc_TypeError,
"EnumProperty(..., default=%d): not found in enum members",
- def_int_cmp);
+ default_int_cmp);
}
return NULL;
}
@@ -1938,7 +2116,7 @@ static const EnumPropertyItem *bpy_prop_enum_itemf_fn(struct bContext *C,
}
else {
PyObject *items_fast;
- int defvalue_dummy = 0;
+ int default_value_dummy = 0;
if (!(items_fast = PySequence_Fast(items,
"EnumProperty(...): "
@@ -1947,7 +2125,7 @@ static const EnumPropertyItem *bpy_prop_enum_itemf_fn(struct bContext *C,
}
else {
eitems = enum_items_from_py(
- items_fast, NULL, &defvalue_dummy, (RNA_property_flag(prop) & PROP_ENUM_FLAG) != 0);
+ items_fast, (RNA_property_flag(prop) & PROP_ENUM_FLAG) != 0, NULL, &default_value_dummy);
Py_DECREF(items_fast);
@@ -2240,84 +2418,141 @@ static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop,
/** \name Shared Method Utilities
* \{ */
-/* this define runs at the start of each function and deals with
- * returning a deferred property (to be registered later) */
-#define BPY_PROPDEF_HEAD(_func) \
- if (PyTuple_GET_SIZE(args) == 1) { \
- PyObject *ret; \
- self = PyTuple_GET_ITEM(args, 0); \
- args = PyTuple_New(0); \
- ret = BPy_##_func(self, args, kw); \
- Py_DECREF(args); \
- return ret; \
- } \
- if (PyTuple_GET_SIZE(args) > 1) { \
- PyErr_SetString(PyExc_ValueError, "all args must be keywords"); \
- return NULL; \
- } \
- srna = srna_from_self(self, #_func "(...):"); \
- if (srna == NULL) { \
- if (PyErr_Occurred()) { \
- return NULL; \
- } \
- return bpy_prop_deferred_data_CreatePyObject(pymeth_##_func, kw); \
- } \
- (void)0
-
-/* terse macros for error checks shared between all funcs can't use function
- * calls because of static strings passed to pyrna_set_to_enum_bitfield */
-#define BPY_PROPDEF_CHECK(_func, _property_flag_items, _property_flag_override_items) \
- if (UNLIKELY(id_len >= MAX_IDPROP_NAME)) { \
- PyErr_Format(PyExc_TypeError, \
- #_func "(): '%.200s' too long, max length is %d", \
- id, \
- MAX_IDPROP_NAME - 1); \
- return NULL; \
- } \
- if (UNLIKELY(RNA_def_property_free_identifier(srna, id) == -1)) { \
- PyErr_Format(PyExc_TypeError, #_func "(): '%s' is defined as a non-dynamic type", id); \
- return NULL; \
- } \
- if (UNLIKELY(pyopts && pyrna_set_to_enum_bitfield( \
- _property_flag_items, pyopts, &opts, #_func "(options={ ...}):"))) { \
- return NULL; \
- } \
- if (UNLIKELY(pyopts_override && pyrna_set_to_enum_bitfield(_property_flag_override_items, \
- pyopts_override, \
- &opts_override, \
- #_func "(override={ ...}):"))) { \
- return NULL; \
- } \
- { \
- const EnumPropertyItem *tag_defines = RNA_struct_property_tag_defines(srna); \
- if (py_tags && !tag_defines) { \
- PyErr_Format(PyExc_TypeError, \
- #_func "(): property-tags not available for '%s'", \
- RNA_struct_identifier(srna)); \
- return NULL; \
- } \
- if (UNLIKELY(py_tags && pyrna_set_to_enum_bitfield( \
- tag_defines, py_tags, &prop_tags, #_func "(tags={ ...}):"))) { \
- return NULL; \
- } \
- } \
- (void)0
-
-#define BPY_PROPDEF_SUBTYPE_CHECK( \
- _func, _property_flag_items, _property_flag_override_items, _subtype) \
- BPY_PROPDEF_CHECK(_func, _property_flag_items, _property_flag_override_items); \
- if (UNLIKELY(pysubtype && RNA_enum_value_from_id(_subtype, pysubtype, &subtype) == 0)) { \
- const char *enum_str = BPy_enum_as_string(_subtype); \
- PyErr_Format(PyExc_TypeError, \
- #_func \
- "(subtype='%s'): " \
- "subtype not found in (%s)", \
- pysubtype, \
- enum_str); \
- MEM_freeN((void *)enum_str); \
- return NULL; \
- } \
- (void)0
+/**
+ * This define runs at the start of each function and deals with
+ * returning a deferred property #BPy_PropDeferred (to be registered later).
+ *
+ * \param self: The self argument from the caller.
+ * \param args: The positional arguments of the caller.
+ * \param kw: The keyword arguments of the caller.
+ * \param method_object: The method of the caller (unfortunately this can't be deduced).
+ * \param r_deferred_result: The deferred result (or NULL in the case of an error).
+ * The caller must return this value unless a valid `srna` is returned.
+ *
+ * \returns When not null, the caller is expected to perform the registration.
+ */
+static StructRNA *bpy_prop_deferred_data_or_srna(PyObject *self,
+ PyObject *args,
+ PyObject *kw,
+ PyObject *method_object,
+ PyObject **r_deferred_result)
+{
+ /* This must be the methods of one of the main property types defined in this file. */
+ BLI_assert(PyCFunction_CheckExact(method_object));
+
+ const int args_len = PyTuple_GET_SIZE(args);
+ PyMethodDef *method_def = ((PyCFunctionObject *)method_object)->m_ml;
+
+ /* Call this function with the first argument set to `self`. */
+ if (args_len == 1) {
+ self = PyTuple_GET_ITEM(args, 0);
+ args = PyTuple_New(0);
+
+ /* This will be #BPy_BoolProperty` or one of the functions that define a type. */
+ PyCFunctionWithKeywords method_fn = (PyCFunctionWithKeywords)method_def->ml_meth;
+ *r_deferred_result = method_fn(self, args, kw);
+ Py_DECREF(args);
+ /* May be an error (depending on `r_deferred_result`). */
+ return NULL;
+ }
+
+ const char *error_prefix = method_def->ml_name;
+ if (args_len > 1) {
+ PyErr_Format(PyExc_ValueError, "%s: all args must be keywords", error_prefix);
+ *r_deferred_result = NULL;
+ /* An error. */
+ return NULL;
+ }
+
+ StructRNA *srna = srna_from_self(self, error_prefix);
+ if (srna == NULL) {
+ *r_deferred_result = PyErr_Occurred() ?
+ NULL :
+ bpy_prop_deferred_data_CreatePyObject(method_object, kw);
+ /* May be an error (depending on `r_deferred_result`). */
+ return NULL;
+ }
+
+ /* Crash if this is ever used by accident! */
+#ifndef NDEBUG
+ *r_deferred_result = (PyObject *)(intptr_t)1;
+#endif
+
+ /* No error or deferred result, perform registration immediately. */
+ return srna;
+}
+
+struct BPy_PropIDParse {
+ const char *value;
+ StructRNA *srna;
+ /**
+ * In the case registering this properly replaces an existing dynamic property.
+ * Store a handle to the property for removal.
+ * This is needed so the property removal is deferred until all other arguments
+ * have been validated, otherwise failure elsewhere could leave the property un-registered.
+ */
+ void *prop_free_handle;
+};
+
+/**
+ * Use with #PyArg_ParseTuple's `O&` formatting.
+ */
+static int bpy_prop_arg_parse_id(PyObject *o, void *p)
+{
+ struct BPy_PropIDParse *parse_data = p;
+ StructRNA *srna = parse_data->srna;
+
+ if (!PyUnicode_Check(o)) {
+ PyErr_Format(PyExc_TypeError, "expected a string (got %.200s)", Py_TYPE(o)->tp_name);
+ return 0;
+ }
+
+ Py_ssize_t id_len;
+ const char *id;
+
+ id = PyUnicode_AsUTF8AndSize(o, &id_len);
+ if (UNLIKELY(id_len >= MAX_IDPROP_NAME)) {
+ PyErr_Format(PyExc_TypeError, "'%.200s' too long, max length is %d", id, MAX_IDPROP_NAME - 1);
+ return 0;
+ }
+
+ parse_data->prop_free_handle = NULL;
+ if (UNLIKELY(RNA_def_property_free_identifier_deferred_prepare(
+ srna, id, &parse_data->prop_free_handle) == -1)) {
+ PyErr_Format(PyExc_TypeError,
+ "'%s' is defined as a non-dynamic type for '%s'",
+ id,
+ RNA_struct_identifier(srna));
+ return 0;
+ }
+ parse_data->value = id;
+ return 1;
+}
+
+/**
+ * Needed so #RNA_struct_property_tag_defines can be called on the `srna`.
+ */
+struct BPy_EnumProperty_Parse_WithSRNA {
+ struct BPy_EnumProperty_Parse base;
+ StructRNA *srna;
+};
+
+/**
+ * Wrapper for #pyrna_enum_bitfield_parse_set
+ * that looks up tags from the `srna`.
+ */
+static int bpy_prop_arg_parse_tag_defines(PyObject *o, void *p)
+{
+ struct BPy_EnumProperty_Parse_WithSRNA *parse_data = p;
+ parse_data->base.items = RNA_struct_property_tag_defines(parse_data->srna);
+ if (parse_data->base.items == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "property-tags not available for '%s'",
+ RNA_struct_identifier(parse_data->srna));
+ return 0;
+ }
+ return pyrna_enum_bitfield_parse_set(o, &parse_data->base);
+}
/** \} */
@@ -2355,8 +2590,9 @@ static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop,
"value in the UI.\n"
#define BPY_PROPDEF_VECSIZE_DOC \
- " :arg size: Vector dimensions in [1, " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" \
-" :type size: int\n"
+ " :arg size: Vector dimensions in [1, " STRINGIFY(PYRNA_STACK_ARRAY) "]. " \
+"An int sequence can be used to define multi-dimension arrays.\n" \
+" :type size: int or int sequence\n"
#define BPY_PROPDEF_INT_STEP_DOC \
" :arg step: Step of increment/decrement in UI, in [1, 100], defaults to 1 (WARNING: unused " \
@@ -2415,11 +2651,15 @@ static int bpy_struct_id_used(StructRNA *srna, char *identifier)
/* -------------------------------------------------------------------- */
/** \name Module Methods
+ *
+ * Functions that register RNA.
+ *
+ * \note The `self` argument is NULL when called from Python,
+ * but being abused from C so we can pass the `srna` along.
+ * This isn't incorrect since its a Python object - but be careful.
+ *
* \{ */
-/* Function that sets RNA, NOTE - self is NULL when called from python,
- * but being abused from C so we can pass the srna along.
- * This isn't incorrect since its a python object - but be careful */
PyDoc_STRVAR(BPy_BoolProperty_doc,
".. function:: BoolProperty(name=\"\", "
"description=\"\", "
@@ -2440,95 +2680,108 @@ PyDoc_STRVAR(BPy_BoolProperty_doc,
static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(BoolProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- bool def = false;
- PropertyRNA *prop;
- PyObject *pyopts = NULL;
- PyObject *pyopts_override = NULL;
- int opts = 0;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "name",
- "description",
- "default",
- "options",
- "override",
- "tags",
- "subtype",
- "update",
- "get",
- "set",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#|$ssO&O!O!O!sOOO:BoolProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- PyC_ParseBool,
- &def,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(self, args, kw, pymeth_BoolProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
+
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ bool default_value = false;
+ PropertyRNA *prop;
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_number_items,
+ .value = PROP_NONE,
+ };
- BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_number_items);
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
- }
+ static const char *_keywords[] = {
+ "attr",
+ "name",
+ "description",
+ "default",
+ "options",
+ "override",
+ "tags",
+ "subtype",
+ "update",
+ "get",
+ "set",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&|$ssO&O&O&O&O&OOO:BoolProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ PyC_ParseBool,
+ &default_value,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
+
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
- prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype);
- RNA_def_property_boolean_default(prop, def);
- RNA_def_property_ui_text(prop, name ? name : id, description);
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_BOOLEAN, subtype_enum.value);
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_boolean(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
+ RNA_def_property_boolean_default(prop, default_value);
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
}
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_boolean(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
Py_RETURN_NONE;
}
@@ -2556,120 +2809,136 @@ PyDoc_STRVAR(
static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(BoolVectorProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- bool def[PYRNA_STACK_ARRAY] = {0};
- int size = 3;
- PropertyRNA *prop;
- PyObject *pydef = NULL;
- PyObject *pyopts = NULL;
- PyObject *pyopts_override = NULL;
- int opts = 0;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "name",
- "description",
- "default",
- "options",
- "override",
- "tags",
- "subtype",
- "size",
- "update",
- "get",
- "set",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#|$ssOO!O!O!siOOO:BoolVectorProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- &pydef,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &size,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(
+ self, args, kw, pymeth_BoolVectorProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_SUBTYPE_CHECK(BoolVectorProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_array_items);
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ bool default_value[RNA_MAX_ARRAY_DIMENSION][PYRNA_STACK_ARRAY] = {{false}};
+ struct BPyPropArrayLength array_len_info = {.len_total = 3};
+ PropertyRNA *prop;
+ PyObject *default_py = NULL;
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_array_items,
+ .value = PROP_NONE,
+ };
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- if (size < 1 || size > PYRNA_STACK_ARRAY) {
- PyErr_Format(
- PyExc_TypeError,
- "BoolVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY),
- size);
- return NULL;
- }
+ static const char *_keywords[] = {
+ "attr",
+ "name",
+ "description",
+ "default",
+ "options",
+ "override",
+ "tags",
+ "subtype",
+ "size",
+ "update",
+ "get",
+ "set",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&|$ssOO&O&O&O&O&OOO:BoolVectorProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ &default_py,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ bpy_prop_array_length_parse,
+ &array_len_info,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
- if (pydef &&
- PyC_AsArray(
- def, pydef, size, &PyBool_Type, false, "BoolVectorProperty(default=sequence)") == -1) {
+ if (default_py != NULL) {
+ if (bpy_prop_array_from_py_with_dims(default_value[0],
+ sizeof(*default_value[0]),
+ default_py,
+ &array_len_info,
+ &PyBool_Type,
+ "BoolVectorProperty(default=sequence)") == -1) {
return NULL;
}
+ }
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
- }
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
-#if 0
- prop = RNA_def_boolean_array(
- srna, id, size, pydef ? def : NULL, name ? name : id, description);
-#endif
- prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype);
- RNA_def_property_array(prop, size);
- if (pydef) {
- RNA_def_property_boolean_array_default(prop, def);
- }
- RNA_def_property_ui_text(prop, name ? name : id, description);
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_BOOLEAN, subtype_enum.value);
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
+ if (array_len_info.dims_len == 0) {
+ RNA_def_property_array(prop, array_len_info.len_total);
+ if (default_py != NULL) {
+ RNA_def_property_boolean_array_default(prop, default_value[0]);
}
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
+ }
+ else {
+ RNA_def_property_multi_array(prop, array_len_info.dims_len, array_len_info.dims);
+ if (default_py != NULL) {
+ RNA_def_property_boolean_array_default(prop, &default_value[0][0]);
}
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_boolean_array(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
}
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_boolean_array(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -2699,106 +2968,122 @@ PyDoc_STRVAR(
static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(IntProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0;
- PropertyRNA *prop;
- PyObject *pyopts = NULL;
- int opts = 0;
- PyObject *pyopts_override = NULL;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "name",
- "description",
- "default",
- "min",
- "max",
- "soft_min",
- "soft_max",
- "step",
- "options",
- "override",
- "tags",
- "subtype",
- "update",
- "get",
- "set",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#|$ssiiiiiiO!O!O!sOOO:IntProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- &def,
- &min,
- &max,
- &soft_min,
- &soft_max,
- &step,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(self, args, kw, pymeth_IntProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_SUBTYPE_CHECK(IntProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_number_items);
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX;
+ int step = 1;
+ int default_value = 0;
+ PropertyRNA *prop;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_number_items,
+ .value = PROP_NONE,
+ };
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
- }
+ static const char *_keywords[] = {
+ "attr",
+ "name",
+ "description",
+ "default",
+ "min",
+ "max",
+ "soft_min",
+ "soft_max",
+ "step",
+ "options",
+ "override",
+ "tags",
+ "subtype",
+ "update",
+ "get",
+ "set",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&|$ssiiiiiiO&O&O&O&OOO:IntProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ &default_value,
+ &min,
+ &max,
+ &soft_min,
+ &soft_max,
+ &step,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
+
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
- prop = RNA_def_property(srna, id, PROP_INT, subtype);
- RNA_def_property_int_default(prop, def);
- RNA_def_property_ui_text(prop, name ? name : id, description);
- RNA_def_property_range(prop, min, max);
- RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3);
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_INT, subtype_enum.value);
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_int(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
+ RNA_def_property_int_default(prop, default_value);
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+ RNA_def_property_range(prop, min, max);
+ RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
}
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_int(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -2832,128 +3117,151 @@ PyDoc_STRVAR(BPy_IntVectorProperty_doc,
static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(IntVectorProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1;
- int def[PYRNA_STACK_ARRAY] = {0};
- int size = 3;
- PropertyRNA *prop;
- PyObject *pydef = NULL;
- PyObject *pyopts = NULL;
- int opts = 0;
- PyObject *pyopts_override = NULL;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "name",
- "description",
- "default",
- "min",
- "max",
- "soft_min",
- "soft_max",
- "step",
- "options",
- "override",
- "tags",
- "subtype",
- "size",
- "update",
- "get",
- "set",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#|$ssOiiiiiO!O!O!siOOO:IntVectorProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- &pydef,
- &min,
- &max,
- &soft_min,
- &soft_max,
- &step,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &size,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(
+ self, args, kw, pymeth_IntVectorProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
+
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX;
+ int step = 1;
+ int default_value[RNA_MAX_ARRAY_DIMENSION][PYRNA_STACK_ARRAY] = {0};
+ struct BPyPropArrayLength array_len_info = {.len_total = 3};
+ PropertyRNA *prop;
+ PyObject *default_py = NULL;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_array_items,
+ .value = PROP_NONE,
+ };
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- BPY_PROPDEF_SUBTYPE_CHECK(IntVectorProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_array_items);
+ static const char *_keywords[] = {
+ "attr",
+ "name",
+ "description",
+ "default",
+ "min",
+ "max",
+ "soft_min",
+ "soft_max",
+ "step",
+ "options",
+ "override",
+ "tags",
+ "subtype",
+ "size",
+ "update",
+ "get",
+ "set",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&|$ssOiiiiiO&O&O&O&O&OOO:IntVectorProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ &default_py,
+ &min,
+ &max,
+ &soft_min,
+ &soft_max,
+ &step,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ bpy_prop_array_length_parse,
+ &array_len_info,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
- if (size < 1 || size > PYRNA_STACK_ARRAY) {
- PyErr_Format(
- PyExc_TypeError,
- "IntVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY),
- size);
+ if (default_py != NULL) {
+ if (bpy_prop_array_from_py_with_dims(default_value[0],
+ sizeof(*default_value[0]),
+ default_py,
+ &array_len_info,
+ &PyLong_Type,
+ "IntVectorProperty(default=sequence)") == -1) {
return NULL;
}
+ }
- if (pydef &&
- PyC_AsArray(
- def, pydef, size, &PyLong_Type, false, "IntVectorProperty(default=sequence)") == -1) {
- return NULL;
- }
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_INT, subtype_enum.value);
+
+ if (array_len_info.dims_len == 0) {
+ RNA_def_property_array(prop, array_len_info.len_total);
+ if (default_py != NULL) {
+ RNA_def_property_int_array_default(prop, default_value[0]);
}
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
+ }
+ else {
+ RNA_def_property_multi_array(prop, array_len_info.dims_len, array_len_info.dims);
+ if (default_py != NULL) {
+ RNA_def_property_int_array_default(prop, &default_value[0][0]);
}
+ }
- prop = RNA_def_property(srna, id, PROP_INT, subtype);
- RNA_def_property_array(prop, size);
- if (pydef) {
- RNA_def_property_int_array_default(prop, def);
- }
- RNA_def_property_range(prop, min, max);
- RNA_def_property_ui_text(prop, name ? name : id, description);
- RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3);
+ RNA_def_property_range(prop, min, max);
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+ RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3);
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_int_array(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
}
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_int_array(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -2986,103 +3294,117 @@ PyDoc_STRVAR(BPy_FloatProperty_doc,
static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(FloatProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3,
- def = 0.0f;
- int precision = 2;
- PropertyRNA *prop;
- PyObject *pyopts = NULL;
- int opts = 0;
- PyObject *pyopts_override = NULL;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- const char *pyunit = NULL;
- int unit = PROP_UNIT_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr", "name", "description", "default", "min", "max", "soft_min",
- "soft_max", "step", "precision", "options", "override", "tags", "subtype",
- "unit", "update", "get", "set", NULL,
- };
- static _PyArg_Parser _parser = {"s#|$ssffffffiO!O!O!ssOOO:FloatProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- &def,
- &min,
- &max,
- &soft_min,
- &soft_max,
- &step,
- &precision,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &pyunit,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(self, args, kw, pymeth_FloatProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_number_items);
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX;
+ float step = 3;
+ float default_value = 0.0f;
+ int precision = 2;
+ PropertyRNA *prop;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_number_items,
+ .value = PROP_NONE,
+ };
+ struct BPy_EnumProperty_Parse unit_enum = {
+ .items = rna_enum_property_unit_items,
+ .value = PROP_UNIT_NONE,
+ };
- if (pyunit && RNA_enum_value_from_id(rna_enum_property_unit_items, pyunit, &unit) == 0) {
- PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit", pyunit);
- return NULL;
- }
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
- }
+ static const char *_keywords[] = {
+ "attr", "name", "description", "default", "min", "max", "soft_min",
+ "soft_max", "step", "precision", "options", "override", "tags", "subtype",
+ "unit", "update", "get", "set", NULL,
+ };
+ static _PyArg_Parser _parser = {"O&|$ssffffffiO&O&O&O&O&OOO:FloatProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ &default_value,
+ &min,
+ &max,
+ &soft_min,
+ &soft_max,
+ &step,
+ &precision,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ pyrna_enum_value_parse_string,
+ &unit_enum,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
- prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit);
- RNA_def_property_float_default(prop, def);
- RNA_def_property_range(prop, min, max);
- RNA_def_property_ui_text(prop, name ? name : id, description);
- RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision);
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_float(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_FLOAT, subtype_enum.value | unit_enum.value);
+
+ RNA_def_property_float_default(prop, default_value);
+ RNA_def_property_range(prop, min, max);
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+ RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
}
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_float(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -3118,123 +3440,149 @@ PyDoc_STRVAR(BPy_FloatVectorProperty_doc,
static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(FloatVectorProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3;
- float def[PYRNA_STACK_ARRAY] = {0.0f};
- int precision = 2, size = 3;
- PropertyRNA *prop;
- PyObject *pydef = NULL;
- PyObject *pyopts = NULL;
- int opts = 0;
- PyObject *pyopts_override = NULL;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- const char *pyunit = NULL;
- int unit = PROP_UNIT_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr", "name", "description", "default", "min", "max", "soft_min",
- "soft_max", "step", "precision", "options", "override", "tags", "subtype",
- "unit", "size", "update", "get", "set", NULL,
- };
- static _PyArg_Parser _parser = {"s#|$ssOfffffiO!O!O!ssiOOO:FloatVectorProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- &pydef,
- &min,
- &max,
- &soft_min,
- &soft_max,
- &step,
- &precision,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &pyunit,
- &size,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(
+ self, args, kw, pymeth_FloatVectorProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_SUBTYPE_CHECK(FloatVectorProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_array_items);
-
- if (pyunit && RNA_enum_value_from_id(rna_enum_property_unit_items, pyunit, &unit) == 0) {
- PyErr_Format(PyExc_TypeError, "FloatVectorProperty(unit='%s'): invalid unit", pyunit);
- return NULL;
- }
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX;
+ float step = 3;
+ float default_value[RNA_MAX_ARRAY_DIMENSION][PYRNA_STACK_ARRAY] = {{0.0f}};
+ int precision = 2;
+ struct BPyPropArrayLength array_len_info = {.len_total = 3};
+ PropertyRNA *prop;
+ PyObject *default_py = NULL;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_array_items,
+ .value = PROP_NONE,
+ };
+ struct BPy_EnumProperty_Parse unit_enum = {
+ .items = rna_enum_property_unit_items,
+ .value = PROP_UNIT_NONE,
+ };
- if (size < 1 || size > PYRNA_STACK_ARRAY) {
- PyErr_Format(
- PyExc_TypeError,
- "FloatVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY),
- size);
- return NULL;
- }
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- if (pydef &&
- PyC_AsArray(
- def, pydef, size, &PyFloat_Type, false, "FloatVectorProperty(default=sequence)") ==
- -1) {
- return NULL;
- }
+ static const char *_keywords[] = {
+ "attr", "name", "description", "default", "min", "max", "soft_min",
+ "soft_max", "step", "precision", "options", "override", "tags", "subtype",
+ "unit", "size", "update", "get", "set", NULL,
+ };
+ static _PyArg_Parser _parser = {
+ "O&|$ssOfffffiO&O&O&O&O&O&OOO:FloatVectorProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ &default_py,
+ &min,
+ &max,
+ &soft_min,
+ &soft_max,
+ &step,
+ &precision,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ pyrna_enum_value_parse_string,
+ &unit_enum,
+ bpy_prop_array_length_parse,
+ &array_len_info,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ if (default_py != NULL) {
+ if (bpy_prop_array_from_py_with_dims(default_value[0],
+ sizeof(*default_value[0]),
+ default_py,
+ &array_len_info,
+ &PyFloat_Type,
+ "FloatVectorProperty(default=sequence)") == -1) {
return NULL;
}
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
+ if (bpy_prop_array_is_matrix_compatible_ex(subtype_enum.value, &array_len_info)) {
+ bpy_prop_array_matrix_swap_row_column_vn(&default_value[0][0], &array_len_info);
}
+ }
- prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit);
- RNA_def_property_array(prop, size);
- if (pydef) {
- RNA_def_property_float_array_default(prop, def);
- }
- RNA_def_property_range(prop, min, max);
- RNA_def_property_ui_text(prop, name ? name : id, description);
- RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision);
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_FLOAT, subtype_enum.value | unit_enum.value);
+
+ if (array_len_info.dims_len == 0) {
+ RNA_def_property_array(prop, array_len_info.len_total);
+ if (default_py != NULL) {
+ RNA_def_property_float_array_default(prop, default_value[0]);
}
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
+ }
+ else {
+ RNA_def_property_multi_array(prop, array_len_info.dims_len, array_len_info.dims);
+ if (default_py != NULL) {
+ RNA_def_property_float_array_default(prop, &default_value[0][0]);
}
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_float_array(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
}
+
+ RNA_def_property_range(prop, min, max);
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+ RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_float_array(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -3262,102 +3610,116 @@ PyDoc_STRVAR(BPy_StringProperty_doc,
static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(StringProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "", *def = "";
- Py_ssize_t id_len;
- int maxlen = 0;
- PropertyRNA *prop;
- PyObject *pyopts = NULL;
- int opts = 0;
- PyObject *pyopts_override = NULL;
- int opts_override = 0;
- int prop_tags = 0;
- const char *pysubtype = NULL;
- int subtype = PROP_NONE;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "name",
- "description",
- "default",
- "maxlen",
- "options",
- "override",
- "tags",
- "subtype",
- "update",
- "get",
- "set",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#|$sssiO!O!O!sOOO:StringProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &name,
- &description,
- &def,
- &maxlen,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &pysubtype,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(self, args, kw, pymeth_StringProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_SUBTYPE_CHECK(StringProperty,
- property_flag_items,
- property_flag_override_items,
- property_subtype_string_items);
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "", *default_value = "";
+ int maxlen = 0;
+ PropertyRNA *prop;
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
- }
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ struct BPy_EnumProperty_Parse subtype_enum = {
+ .items = property_subtype_string_items,
+ .value = PROP_NONE,
+ };
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- prop = RNA_def_property(srna, id, PROP_STRING, subtype);
- if (maxlen != 0) {
- /* +1 since it includes null terminator. */
- RNA_def_property_string_maxlength(prop, maxlen + 1);
- }
- if (def && def[0]) {
- RNA_def_property_string_default(prop, def);
- }
- RNA_def_property_ui_text(prop, name ? name : id, description);
+ static const char *_keywords[] = {
+ "attr",
+ "name",
+ "description",
+ "default",
+ "maxlen",
+ "options",
+ "override",
+ "tags",
+ "subtype",
+ "update",
+ "get",
+ "set",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&|$sssiO&O&O&O&OOO:StringProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &name,
+ &description,
+ &default_value,
+ &maxlen,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ pyrna_enum_value_parse_string,
+ &subtype_enum,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_string(prop, get_fn, set_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
}
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
+
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_property(srna, id_data.value, PROP_STRING, subtype_enum.value);
+
+ if (maxlen != 0) {
+ /* +1 since it includes null terminator. */
+ RNA_def_property_string_maxlength(prop, maxlen + 1);
+ }
+ if (default_value && default_value[0]) {
+ RNA_def_property_string_default(prop, default_value);
+ }
+ RNA_def_property_ui_text(prop, name ? name : id_data.value, description);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_string(prop, get_fn, set_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -3419,151 +3781,167 @@ PyDoc_STRVAR(
static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(EnumProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- PyObject *def = NULL;
- Py_ssize_t id_len;
- int defvalue = 0;
- PyObject *items, *items_fast;
- const EnumPropertyItem *eitems;
- PropertyRNA *prop;
- PyObject *pyopts = NULL;
- int opts = 0;
- PyObject *pyopts_override = NULL;
- int opts_override = 0;
- int prop_tags = 0;
- bool is_itemf = false;
- PyObject *update_fn = NULL;
- PyObject *get_fn = NULL;
- PyObject *set_fn = NULL;
- PyObject *py_tags = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "items",
- "name",
- "description",
- "default",
- "options",
- "override",
- "tags",
- "update",
- "get",
- "set",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#O|$ssOO!O!O!OOO:EnumProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &items,
- &name,
- &description,
- &def,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &update_fn,
- &get_fn,
- &set_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(self, args, kw, pymeth_EnumProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_CHECK(EnumProperty, property_flag_enum_items, property_flag_override_items);
-
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
- return NULL;
- }
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ PyObject *default_py = NULL;
+ int default_value = 0;
+ PyObject *items, *items_fast;
+ const EnumPropertyItem *eitems;
+ PropertyRNA *prop;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_enum_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ bool is_itemf = false;
+ PyObject *update_fn = NULL;
+ PyObject *get_fn = NULL;
+ PyObject *set_fn = NULL;
- if (def == Py_None) {
- /* This allows to get same behavior when explicitly passing None as default value,
- * and not defining a default value at all! */
- def = NULL;
- }
+ static const char *_keywords[] = {
+ "attr",
+ "items",
+ "name",
+ "description",
+ "default",
+ "options",
+ "override",
+ "tags",
+ "update",
+ "get",
+ "set",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&O|$ssOO&O&O&OOO:EnumProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &items,
+ &name,
+ &description,
+ &default_py,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ &update_fn,
+ &get_fn,
+ &set_fn)) {
+ return NULL;
+ }
- /* items can be a list or a callable */
- if (PyFunction_Check(
- items)) { /* don't use PyCallable_Check because we need the function code for errors */
- PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(items);
- if (f_code->co_argcount != 2) {
- PyErr_Format(PyExc_ValueError,
- "EnumProperty(...): expected 'items' function to take 2 arguments, not %d",
- f_code->co_argcount);
- return NULL;
- }
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(get_fn, "get", 1) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(set_fn, "set", 2) == -1) {
+ return NULL;
+ }
- if (def) {
- /* Only support getting integer default values here. */
- if (!py_long_as_int(def, &defvalue)) {
- /* NOTE: using type error here is odd but python does this for invalid arguments. */
- PyErr_SetString(
- PyExc_TypeError,
- "EnumProperty(...): 'default' can only be an integer when 'items' is a function");
- return NULL;
- }
- }
+ if (default_py == Py_None) {
+ /* This allows to get same behavior when explicitly passing None as default value,
+ * and not defining a default value at all! */
+ default_py = NULL;
+ }
- is_itemf = true;
- eitems = DummyRNA_NULL_items;
+ /* items can be a list or a callable */
+ if (PyFunction_Check(
+ items)) { /* don't use PyCallable_Check because we need the function code for errors */
+ PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(items);
+ if (f_code->co_argcount != 2) {
+ PyErr_Format(PyExc_ValueError,
+ "EnumProperty(...): expected 'items' function to take 2 arguments, not %d",
+ f_code->co_argcount);
+ return NULL;
}
- else {
- if (!(items_fast = PySequence_Fast(
- items,
- "EnumProperty(...): "
- "expected a sequence of tuples for the enum items or a function"))) {
- return NULL;
- }
-
- eitems = enum_items_from_py(items_fast, def, &defvalue, (opts & PROP_ENUM_FLAG) != 0);
- if (!eitems) {
- Py_DECREF(items_fast);
+ if (default_py) {
+ /* Only support getting integer default values here. */
+ if (!py_long_as_int(default_py, &default_value)) {
+ /* NOTE: using type error here is odd but python does this for invalid arguments. */
+ PyErr_SetString(
+ PyExc_TypeError,
+ "EnumProperty(...): 'default' can only be an integer when 'items' is a function");
return NULL;
}
}
- if (opts & PROP_ENUM_FLAG) {
- prop = RNA_def_enum_flag(srna, id, eitems, defvalue, name ? name : id, description);
- }
- else {
- prop = RNA_def_enum(srna, id, eitems, defvalue, name ? name : id, description);
+ is_itemf = true;
+ eitems = DummyRNA_NULL_items;
+ }
+ else {
+ if (!(items_fast = PySequence_Fast(
+ items,
+ "EnumProperty(...): "
+ "expected a sequence of tuples for the enum items or a function"))) {
+ return NULL;
}
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_enum(prop, get_fn, set_fn, (is_itemf ? items : NULL));
- RNA_def_property_duplicate_pointers(srna, prop);
+ eitems = enum_items_from_py(
+ items_fast, (options_enum.value & PROP_ENUM_FLAG) != 0, default_py, &default_value);
- if (is_itemf == false) {
- /* NOTE: this must be postponed until after #RNA_def_property_duplicate_pointers
- * otherwise if this is a generator it may free the strings before we copy them */
+ if (!eitems) {
Py_DECREF(items_fast);
-
- MEM_freeN((void *)eitems);
+ return NULL;
}
}
+
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ if (options_enum.value & PROP_ENUM_FLAG) {
+ prop = RNA_def_enum_flag(
+ srna, id_data.value, eitems, default_value, name ? name : id_data.value, description);
+ }
+ else {
+ prop = RNA_def_enum(
+ srna, id_data.value, eitems, default_value, name ? name : id_data.value, description);
+ }
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_enum(prop, get_fn, set_fn, (is_itemf ? items : NULL));
+ RNA_def_property_duplicate_pointers(srna, prop);
+
+ if (is_itemf == false) {
+ /* NOTE: this must be postponed until after #RNA_def_property_duplicate_pointers
+ * otherwise if this is a generator it may free the strings before we copy them */
+ Py_DECREF(items_fast);
+
+ MEM_freeN((void *)eitems);
+ }
+
Py_RETURN_NONE;
}
@@ -3609,94 +3987,111 @@ PyDoc_STRVAR(BPy_PointerProperty_doc,
PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(PointerProperty);
-
- if (srna) {
- const char *id = NULL, *name = NULL, *description = "";
- Py_ssize_t id_len;
- PropertyRNA *prop;
- StructRNA *ptype;
- PyObject *type = Py_None;
- PyObject *pyopts = NULL;
- PyObject *pyopts_override = NULL;
- PyObject *py_tags = NULL;
- int opts = 0;
- int opts_override = 0;
- int prop_tags = 0;
- PyObject *update_fn = NULL, *poll_fn = NULL;
-
- static const char *_keywords[] = {
- "attr",
- "type",
- "name",
- "description",
- "options",
- "override",
- "tags",
- "poll",
- "update",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#O|$ssO!O!O!OO:PointerProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &type,
- &name,
- &description,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags,
- &poll_fn,
- &update_fn)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(
+ self, args, kw, pymeth_PointerProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_CHECK(PointerProperty, property_flag_items, property_flag_override_items);
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ PropertyRNA *prop;
+ StructRNA *ptype;
+ PyObject *type = Py_None;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
+ PyObject *update_fn = NULL, *poll_fn = NULL;
- ptype = pointer_type_from_py(type, "PointerProperty(...)");
- if (!ptype) {
- return NULL;
- }
- if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup) && !RNA_struct_is_ID(ptype)) {
- PyErr_Format(PyExc_TypeError,
- "PointerProperty(...) expected an RNA type derived from %.200s or %.200s",
- RNA_struct_ui_name(&RNA_ID),
- RNA_struct_ui_name(&RNA_PropertyGroup));
- return NULL;
- }
- if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
- return NULL;
- }
- if (bpy_prop_callback_check(poll_fn, "poll", 2) == -1) {
- return NULL;
- }
- prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description);
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
+ static const char *_keywords[] = {
+ "attr",
+ "type",
+ "name",
+ "description",
+ "options",
+ "override",
+ "tags",
+ "poll",
+ "update",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&O|$ssO&O&O&OO:PointerProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &type,
+ &name,
+ &description,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum,
+ &poll_fn,
+ &update_fn)) {
+ return NULL;
+ }
- if (RNA_struct_idprops_contains_datablock(ptype)) {
- if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
- RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES);
- }
+ ptype = pointer_type_from_py(type, "PointerProperty(...)");
+ if (!ptype) {
+ return NULL;
+ }
+ if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup) && !RNA_struct_is_ID(ptype)) {
+ PyErr_Format(PyExc_TypeError,
+ "PointerProperty(...) expected an RNA type derived from %.200s or %.200s",
+ RNA_struct_ui_name(&RNA_ID),
+ RNA_struct_ui_name(&RNA_PropertyGroup));
+ return NULL;
+ }
+ if (bpy_prop_callback_check(update_fn, "update", 2) == -1) {
+ return NULL;
+ }
+ if (bpy_prop_callback_check(poll_fn, "poll", 2) == -1) {
+ return NULL;
+ }
+
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_pointer_runtime(
+ srna, id_data.value, ptype, name ? name : id_data.value, description);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+
+ if (RNA_struct_idprops_contains_datablock(ptype)) {
+ if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
+ RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES);
}
- bpy_prop_callback_assign_update(prop, update_fn);
- bpy_prop_callback_assign_pointer(prop, poll_fn);
- RNA_def_property_duplicate_pointers(srna, prop);
}
+ bpy_prop_callback_assign_update(prop, update_fn);
+ bpy_prop_callback_assign_pointer(prop, poll_fn);
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}
@@ -3715,83 +4110,98 @@ PyDoc_STRVAR(BPy_CollectionProperty_doc,
PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw)
{
StructRNA *srna;
-
- BPY_PROPDEF_HEAD(CollectionProperty);
-
- if (srna) {
- Py_ssize_t id_len;
- const char *id = NULL, *name = NULL, *description = "";
- PropertyRNA *prop;
- StructRNA *ptype;
- PyObject *type = Py_None;
- PyObject *pyopts = NULL;
- PyObject *pyopts_override = NULL;
- PyObject *py_tags = NULL;
- int opts = 0;
- int opts_override = 0;
- int prop_tags = 0;
-
- static const char *_keywords[] = {
- "attr",
- "type",
- "name",
- "description",
- "options",
- "override",
- "tags",
- NULL,
- };
- static _PyArg_Parser _parser = {"s#O|$ssO!O!O!:CollectionProperty", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(args,
- kw,
- &_parser,
- &id,
- &id_len,
- &type,
- &name,
- &description,
- &PySet_Type,
- &pyopts,
- &PySet_Type,
- &pyopts_override,
- &PySet_Type,
- &py_tags)) {
- return NULL;
+ { /* Keep this block first. */
+ PyObject *deferred_result;
+ srna = bpy_prop_deferred_data_or_srna(
+ self, args, kw, pymeth_CollectionProperty, &deferred_result);
+ if (srna == NULL) {
+ return deferred_result;
}
+ }
- BPY_PROPDEF_CHECK(
- CollectionProperty, property_flag_items, property_flag_override_collection_items);
+ struct BPy_PropIDParse id_data = {
+ .srna = srna,
+ };
+ const char *name = NULL, *description = "";
+ PropertyRNA *prop;
+ StructRNA *ptype;
+ PyObject *type = Py_None;
+
+ struct BPy_EnumProperty_Parse options_enum = {
+ .items = property_flag_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse override_enum = {
+ .items = property_flag_override_collection_items,
+ .value = 0,
+ };
+ struct BPy_EnumProperty_Parse_WithSRNA tags_enum = {
+ .srna = srna,
+ };
- ptype = pointer_type_from_py(type, "CollectionProperty(...):");
- if (!ptype) {
- return NULL;
- }
+ static const char *_keywords[] = {
+ "attr",
+ "type",
+ "name",
+ "description",
+ "options",
+ "override",
+ "tags",
+ NULL,
+ };
+ static _PyArg_Parser _parser = {"O&O|$ssO&O&O&:CollectionProperty", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args,
+ kw,
+ &_parser,
+ bpy_prop_arg_parse_id,
+ &id_data,
+ &type,
+ &name,
+ &description,
+ pyrna_enum_bitfield_parse_set,
+ &options_enum,
+ pyrna_enum_bitfield_parse_set,
+ &override_enum,
+ bpy_prop_arg_parse_tag_defines,
+ &tags_enum)) {
+ return NULL;
+ }
- if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) {
- PyErr_Format(PyExc_TypeError,
- "CollectionProperty(...) expected an RNA type derived from %.200s",
- RNA_struct_ui_name(&RNA_PropertyGroup));
- return NULL;
- }
+ ptype = pointer_type_from_py(type, "CollectionProperty(...):");
+ if (!ptype) {
+ return NULL;
+ }
- prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description);
- if (py_tags) {
- RNA_def_property_tags(prop, prop_tags);
- }
- if (pyopts) {
- bpy_prop_assign_flag(prop, opts);
- }
- if (pyopts_override) {
- bpy_prop_assign_flag_override(prop, opts_override);
- }
+ if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) {
+ PyErr_Format(PyExc_TypeError,
+ "CollectionProperty(...) expected an RNA type derived from %.200s",
+ RNA_struct_ui_name(&RNA_PropertyGroup));
+ return NULL;
+ }
- if (RNA_struct_idprops_contains_datablock(ptype)) {
- if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
- RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES);
- }
+ if (id_data.prop_free_handle != NULL) {
+ RNA_def_property_free_identifier_deferred_finish(srna, id_data.prop_free_handle);
+ }
+ prop = RNA_def_collection_runtime(
+ srna, id_data.value, ptype, name ? name : id_data.value, description);
+
+ if (tags_enum.base.is_set) {
+ RNA_def_property_tags(prop, tags_enum.base.value);
+ }
+ if (options_enum.is_set) {
+ bpy_prop_assign_flag(prop, options_enum.value);
+ }
+ if (override_enum.is_set) {
+ bpy_prop_assign_flag_override(prop, override_enum.value);
+ }
+
+ if (RNA_struct_idprops_contains_datablock(ptype)) {
+ if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) {
+ RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES);
}
- RNA_def_property_duplicate_pointers(srna, prop);
}
+ RNA_def_property_duplicate_pointers(srna, prop);
+
Py_RETURN_NONE;
}