tornavis/source/blender/python/generic/idprop_py_ui_api.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

840 lines
27 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
/** \file
* \ingroup pygen
*/
#include <Python.h>
#include "MEM_guardedalloc.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "idprop_py_ui_api.h"
#include "BKE_idprop.h"
#include "DNA_ID.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
#define USE_STRING_COERCE
#ifdef USE_STRING_COERCE
# include "py_capi_utils.h"
#endif
#include "py_capi_rna.h"
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
#include "python_utildefines.h"
/* -------------------------------------------------------------------- */
/** \name UI Data Update
* \{ */
static bool args_contain_key(PyObject *kwargs, const char *name)
{
if (kwargs == NULL) {
/* When a function gets called without any kwargs, Python just passes NULL instead.
* PyDict_Contains() is not NULL-safe, though. */
return false;
}
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
PyObject *py_key = PyUnicode_FromString(name);
const bool result = PyDict_Contains(kwargs, py_key) == 1;
Py_DECREF(py_key);
return result;
}
/**
* \return False when parsing fails, in which case caller should return NULL.
*/
static bool idprop_ui_data_update_base(IDPropertyUIData *ui_data,
const char *rna_subtype,
const char *description)
{
if (rna_subtype != NULL) {
if (pyrna_enum_value_from_id(rna_enum_property_subtype_items,
rna_subtype,
&ui_data->rna_subtype,
"IDPropertyUIManager.update") == -1)
{
return false;
}
}
if (description != NULL) {
ui_data->description = BLI_strdup(description);
}
return true;
}
/**
* \note The default value needs special handling because for array IDProperties it can
* be a single value or an array, but for non-array properties it can only be a value.
*/
static bool idprop_ui_data_update_int_default(IDProperty *idprop,
IDPropertyUIDataInt *ui_data,
PyObject *default_value)
{
if (PySequence_Check(default_value)) {
if (idprop->type != IDP_ARRAY) {
PyErr_SetString(PyExc_TypeError, "Only array properties can have array default values");
return false;
}
Py_ssize_t len = PySequence_Size(default_value);
int *new_default_array = (int *)MEM_malloc_arrayN(len, sizeof(int), __func__);
if (PyC_AsArray(
new_default_array, sizeof(int), default_value, len, &PyLong_Type, "ui_data_update") ==
-1)
{
MEM_freeN(new_default_array);
return false;
}
ui_data->default_array_len = len;
ui_data->default_array = new_default_array;
}
else {
const int value = PyC_Long_AsI32(default_value);
if ((value == -1) && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "Error converting \"default\" argument to integer");
return false;
}
ui_data->default_value = value;
}
return true;
}
/**
* \return False when parsing fails, in which case caller should return NULL.
*/
static bool idprop_ui_data_update_int(IDProperty *idprop, PyObject *args, PyObject *kwargs)
{
const char *rna_subtype = NULL;
const char *description = NULL;
int min, max, soft_min, soft_max, step;
PyObject *default_value = NULL;
const char *kwlist[] = {
"min", "max", "soft_min", "soft_max", "step", "default", "subtype", "description", NULL};
if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
"|$iiiiiOzz:update",
(char **)kwlist,
&min,
&max,
&soft_min,
&soft_max,
&step,
&default_value,
&rna_subtype,
&description))
{
return false;
}
/* Write to a temporary copy of the UI data in case some part of the parsing fails. */
IDPropertyUIDataInt *ui_data_orig = (IDPropertyUIDataInt *)idprop->ui_data;
IDPropertyUIDataInt ui_data = *ui_data_orig;
if (!idprop_ui_data_update_base(&ui_data.base, rna_subtype, description)) {
IDP_ui_data_free_unique_contents(&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
if (args_contain_key(kwargs, "min")) {
ui_data.min = min;
ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min);
ui_data.max = MAX2(ui_data.min, ui_data.max);
}
if (args_contain_key(kwargs, "max")) {
ui_data.max = max;
ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max);
ui_data.min = MIN2(ui_data.min, ui_data.max);
}
if (args_contain_key(kwargs, "soft_min")) {
ui_data.soft_min = soft_min;
ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min);
ui_data.soft_max = MAX2(ui_data.soft_min, ui_data.soft_max);
}
if (args_contain_key(kwargs, "soft_max")) {
ui_data.soft_max = soft_max;
ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max);
ui_data.soft_min = MIN2(ui_data.soft_min, ui_data.soft_max);
}
if (args_contain_key(kwargs, "step")) {
ui_data.step = step;
}
if (!ELEM(default_value, NULL, Py_None)) {
if (!idprop_ui_data_update_int_default(idprop, &ui_data, default_value)) {
IDP_ui_data_free_unique_contents(
&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
}
2021-09-02 05:22:35 +02:00
/* Write back to the property's UI data. */
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
*ui_data_orig = ui_data;
return true;
}
/**
* \note The default value needs special handling because for array IDProperties it can
* be a single value or an array, but for non-array properties it can only be a value.
*/
static bool idprop_ui_data_update_bool_default(IDProperty *idprop,
IDPropertyUIDataBool *ui_data,
PyObject *default_value)
{
if (PySequence_Check(default_value)) {
if (idprop->type != IDP_ARRAY) {
PyErr_SetString(PyExc_TypeError, "Only array properties can have array default values");
return false;
}
Py_ssize_t len = PySequence_Size(default_value);
int8_t *new_default_array = (int8_t *)MEM_malloc_arrayN(len, sizeof(int8_t), __func__);
if (PyC_AsArray(new_default_array,
sizeof(int8_t),
default_value,
len,
&PyBool_Type,
"ui_data_update") == -1)
{
MEM_freeN(new_default_array);
return false;
}
ui_data->default_array_len = len;
ui_data->default_array = new_default_array;
}
else {
const int value = PyC_Long_AsBool(default_value);
if ((value == -1) && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "Error converting \"default\" argument to integer");
return false;
}
ui_data->default_value = (value != 0);
}
return true;
}
/**
* \return False when parsing fails, in which case caller should return NULL.
*/
static bool idprop_ui_data_update_bool(IDProperty *idprop, PyObject *args, PyObject *kwargs)
{
const char *rna_subtype = NULL;
const char *description = NULL;
PyObject *default_value = NULL;
const char *kwlist[] = {"default", "subtype", "description", NULL};
if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
"|$Ozz:update",
(char **)kwlist,
&default_value,
&rna_subtype,
&description))
{
return false;
}
/* Write to a temporary copy of the UI data in case some part of the parsing fails. */
IDPropertyUIDataBool *ui_data_orig = (IDPropertyUIDataBool *)idprop->ui_data;
IDPropertyUIDataBool ui_data = *ui_data_orig;
if (!idprop_ui_data_update_base(&ui_data.base, rna_subtype, description)) {
IDP_ui_data_free_unique_contents(&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
if (!ELEM(default_value, NULL, Py_None)) {
if (!idprop_ui_data_update_bool_default(idprop, &ui_data, default_value)) {
IDP_ui_data_free_unique_contents(
&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
}
/* Write back to the property's UI data. */
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
*ui_data_orig = ui_data;
return true;
}
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
/**
* \note The default value needs special handling because for array IDProperties it can
* be a single value or an array, but for non-array properties it can only be a value.
*/
static bool idprop_ui_data_update_float_default(IDProperty *idprop,
IDPropertyUIDataFloat *ui_data,
PyObject *default_value)
{
if (PySequence_Check(default_value)) {
if (idprop->type != IDP_ARRAY) {
PyErr_SetString(PyExc_TypeError, "Only array properties can have array default values");
return false;
}
Py_ssize_t len = PySequence_Size(default_value);
double *new_default_array = (double *)MEM_malloc_arrayN(len, sizeof(double), __func__);
if (PyC_AsArray(new_default_array,
sizeof(double),
default_value,
len,
&PyFloat_Type,
"ui_data_update") == -1)
{
MEM_freeN(new_default_array);
return false;
}
ui_data->default_array_len = len;
ui_data->default_array = new_default_array;
}
else {
const double value = PyFloat_AsDouble(default_value);
if ((value == -1.0) && PyErr_Occurred()) {
PyErr_SetString(PyExc_ValueError, "Error converting \"default\" argument to double");
return false;
}
ui_data->default_value = value;
}
return true;
}
/**
* \return False when parsing fails, in which case caller should return NULL.
*/
static bool idprop_ui_data_update_float(IDProperty *idprop, PyObject *args, PyObject *kwargs)
{
const char *rna_subtype = NULL;
const char *description = NULL;
int precision;
double min, max, soft_min, soft_max, step;
PyObject *default_value = NULL;
const char *kwlist[] = {"min",
"max",
"soft_min",
"soft_max",
"step",
"precision",
"default",
"subtype",
"description",
NULL};
if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
"|$dddddiOzz:update",
(char **)kwlist,
&min,
&max,
&soft_min,
&soft_max,
&step,
&precision,
&default_value,
&rna_subtype,
&description))
{
return false;
}
/* Write to a temporary copy of the UI data in case some part of the parsing fails. */
IDPropertyUIDataFloat *ui_data_orig = (IDPropertyUIDataFloat *)idprop->ui_data;
IDPropertyUIDataFloat ui_data = *ui_data_orig;
if (!idprop_ui_data_update_base(&ui_data.base, rna_subtype, description)) {
IDP_ui_data_free_unique_contents(&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
if (args_contain_key(kwargs, "min")) {
ui_data.min = min;
ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min);
ui_data.max = MAX2(ui_data.min, ui_data.max);
}
if (args_contain_key(kwargs, "max")) {
ui_data.max = max;
ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max);
ui_data.min = MIN2(ui_data.min, ui_data.max);
}
if (args_contain_key(kwargs, "soft_min")) {
ui_data.soft_min = soft_min;
ui_data.soft_min = MAX2(ui_data.soft_min, ui_data.min);
ui_data.soft_max = MAX2(ui_data.soft_min, ui_data.soft_max);
}
if (args_contain_key(kwargs, "soft_max")) {
ui_data.soft_max = soft_max;
ui_data.soft_max = MIN2(ui_data.soft_max, ui_data.max);
ui_data.soft_min = MIN2(ui_data.soft_min, ui_data.soft_max);
}
if (args_contain_key(kwargs, "step")) {
ui_data.step = (float)step;
}
if (args_contain_key(kwargs, "precision")) {
ui_data.precision = precision;
}
if (!ELEM(default_value, NULL, Py_None)) {
if (!idprop_ui_data_update_float_default(idprop, &ui_data, default_value)) {
IDP_ui_data_free_unique_contents(
&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
}
2021-09-02 05:22:35 +02:00
/* Write back to the property's UI data. */
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
*ui_data_orig = ui_data;
return true;
}
/**
* \return False when parsing fails, in which case caller should return NULL.
*/
static bool idprop_ui_data_update_string(IDProperty *idprop, PyObject *args, PyObject *kwargs)
{
const char *rna_subtype = NULL;
const char *description = NULL;
const char *default_value;
const char *kwlist[] = {"default", "subtype", "description", NULL};
if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
"|$zzz:update",
(char **)kwlist,
&default_value,
&rna_subtype,
&description))
{
return false;
}
/* Write to a temporary copy of the UI data in case some part of the parsing fails. */
IDPropertyUIDataString *ui_data_orig = (IDPropertyUIDataString *)idprop->ui_data;
IDPropertyUIDataString ui_data = *ui_data_orig;
if (!idprop_ui_data_update_base(&ui_data.base, rna_subtype, description)) {
IDP_ui_data_free_unique_contents(&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
if (default_value != NULL) {
ui_data.default_value = BLI_strdup(default_value);
}
2021-09-02 05:22:35 +02:00
/* Write back to the property's UI data. */
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
*ui_data_orig = ui_data;
return true;
}
/**
* \return False when parsing fails, in which case caller should return NULL.
*/
static bool idprop_ui_data_update_id(IDProperty *idprop, PyObject *args, PyObject *kwargs)
{
const char *rna_subtype = NULL;
const char *description = NULL;
const char *kwlist[] = {"subtype", "description", NULL};
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "|$zz:update", (char **)kwlist, &rna_subtype, &description))
{
return false;
}
/* Write to a temporary copy of the UI data in case some part of the parsing fails. */
IDPropertyUIDataID *ui_data_orig = (IDPropertyUIDataID *)idprop->ui_data;
IDPropertyUIDataID ui_data = *ui_data_orig;
if (!idprop_ui_data_update_base(&ui_data.base, rna_subtype, description)) {
IDP_ui_data_free_unique_contents(&ui_data.base, IDP_ui_data_type(idprop), &ui_data_orig->base);
return false;
}
2021-09-02 05:22:35 +02:00
/* Write back to the property's UI data. */
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
IDP_ui_data_free_unique_contents(&ui_data_orig->base, IDP_ui_data_type(idprop), &ui_data.base);
*ui_data_orig = ui_data;
return true;
}
PyDoc_STRVAR(BPy_IDPropertyUIManager_update_doc,
".. method:: update( "
"subtype=None, "
"min=None, "
"max=None, "
"soft_min=None, "
"soft_max=None, "
"precision=None, "
"step=None, "
"default=None, "
"description=None)\n"
"\n"
" Update the RNA information of the IDProperty used for interaction and\n"
" display in the user interface. The required types for many of the keyword\n"
" arguments depend on the type of the property.\n ");
static PyObject *BPy_IDPropertyUIManager_update(BPy_IDPropertyUIManager *self,
PyObject *args,
PyObject *kwargs)
{
IDProperty *property = self->property;
BLI_assert(IDP_ui_data_supported(property));
switch (IDP_ui_data_type(property)) {
case IDP_UI_DATA_TYPE_INT:
IDP_ui_data_ensure(property);
if (!idprop_ui_data_update_int(property, args, kwargs)) {
return NULL;
}
Py_RETURN_NONE;
case IDP_UI_DATA_TYPE_BOOLEAN:
IDP_ui_data_ensure(property);
if (!idprop_ui_data_update_bool(property, args, kwargs)) {
return NULL;
}
Py_RETURN_NONE;
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
case IDP_UI_DATA_TYPE_FLOAT:
IDP_ui_data_ensure(property);
if (!idprop_ui_data_update_float(property, args, kwargs)) {
return NULL;
}
Py_RETURN_NONE;
case IDP_UI_DATA_TYPE_STRING:
IDP_ui_data_ensure(property);
if (!idprop_ui_data_update_string(property, args, kwargs)) {
return NULL;
}
Py_RETURN_NONE;
case IDP_UI_DATA_TYPE_ID:
IDP_ui_data_ensure(property);
if (!idprop_ui_data_update_id(property, args, kwargs)) {
return NULL;
}
Py_RETURN_NONE;
case IDP_UI_DATA_TYPE_UNSUPPORTED:
PyErr_Format(PyExc_TypeError, "IDProperty \"%s\" does not support RNA data", property->name);
return NULL;
}
BLI_assert_unreachable();
Py_RETURN_NONE;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI Data As Dictionary
* \{ */
static void idprop_ui_data_to_dict_int(IDProperty *property, PyObject *dict)
{
IDPropertyUIDataInt *ui_data = (IDPropertyUIDataInt *)property->ui_data;
PyObject *item;
PyDict_SetItemString(dict, "min", item = PyLong_FromLong(ui_data->min));
Py_DECREF(item);
PyDict_SetItemString(dict, "max", item = PyLong_FromLong(ui_data->max));
Py_DECREF(item);
PyDict_SetItemString(dict, "soft_min", item = PyLong_FromLong(ui_data->soft_min));
Py_DECREF(item);
PyDict_SetItemString(dict, "soft_max", item = PyLong_FromLong(ui_data->soft_max));
Py_DECREF(item);
PyDict_SetItemString(dict, "step", item = PyLong_FromLong(ui_data->step));
Py_DECREF(item);
if (property->type == IDP_ARRAY) {
PyObject *list = PyList_New(ui_data->default_array_len);
for (int i = 0; i < ui_data->default_array_len; i++) {
PyList_SET_ITEM(list, i, PyLong_FromLong(ui_data->default_array[i]));
}
PyDict_SetItemString(dict, "default", list);
Py_DECREF(list);
}
else {
PyDict_SetItemString(dict, "default", item = PyLong_FromLong(ui_data->default_value));
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
Py_DECREF(item);
}
}
static void idprop_ui_data_to_dict_bool(IDProperty *property, PyObject *dict)
{
IDPropertyUIDataBool *ui_data = (IDPropertyUIDataBool *)property->ui_data;
PyObject *item;
if (property->type == IDP_ARRAY) {
PyObject *list = PyList_New(ui_data->default_array_len);
for (int i = 0; i < ui_data->default_array_len; i++) {
PyList_SET_ITEM(list, i, PyBool_FromLong(ui_data->default_array[i]));
}
PyDict_SetItemString(dict, "default", list);
Py_DECREF(list);
}
else {
PyDict_SetItemString(dict, "default", item = PyBool_FromLong(ui_data->default_value));
Py_DECREF(item);
}
}
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
static void idprop_ui_data_to_dict_float(IDProperty *property, PyObject *dict)
{
IDPropertyUIDataFloat *ui_data = (IDPropertyUIDataFloat *)property->ui_data;
PyObject *item;
PyDict_SetItemString(dict, "min", item = PyFloat_FromDouble(ui_data->min));
Py_DECREF(item);
PyDict_SetItemString(dict, "max", item = PyFloat_FromDouble(ui_data->max));
Py_DECREF(item);
PyDict_SetItemString(dict, "soft_min", item = PyFloat_FromDouble(ui_data->soft_min));
Py_DECREF(item);
PyDict_SetItemString(dict, "soft_max", item = PyFloat_FromDouble(ui_data->soft_max));
Py_DECREF(item);
PyDict_SetItemString(dict, "step", item = PyFloat_FromDouble((double)ui_data->step));
Py_DECREF(item);
PyDict_SetItemString(dict, "precision", item = PyLong_FromDouble((double)ui_data->precision));
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
Py_DECREF(item);
if (property->type == IDP_ARRAY) {
PyObject *list = PyList_New(ui_data->default_array_len);
for (int i = 0; i < ui_data->default_array_len; i++) {
PyList_SET_ITEM(list, i, PyFloat_FromDouble(ui_data->default_array[i]));
}
PyDict_SetItemString(dict, "default", list);
Py_DECREF(list);
}
else {
PyDict_SetItemString(dict, "default", item = PyFloat_FromDouble(ui_data->default_value));
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
Py_DECREF(item);
}
}
static void idprop_ui_data_to_dict_string(IDProperty *property, PyObject *dict)
{
IDPropertyUIDataString *ui_data = (IDPropertyUIDataString *)property->ui_data;
PyObject *item;
const char *default_value = (ui_data->default_value == NULL) ? "" : ui_data->default_value;
PyDict_SetItemString(dict, "default", item = PyUnicode_FromString(default_value));
Py_DECREF(item);
}
PyDoc_STRVAR(BPy_IDPropertyUIManager_as_dict_doc,
".. method:: as_dict()\n"
"\n"
" Return a dictionary of the property's RNA UI data. The fields in the\n"
" returned dictionary and their types will depend on the property's type.\n");
static PyObject *BPy_IDIDPropertyUIManager_as_dict(BPy_IDPropertyUIManager *self)
{
IDProperty *property = self->property;
BLI_assert(IDP_ui_data_supported(property));
IDPropertyUIData *ui_data = IDP_ui_data_ensure(property);
PyObject *dict = PyDict_New();
/* RNA subtype. */
{
const char *subtype_id = NULL;
RNA_enum_identifier(rna_enum_property_subtype_items, ui_data->rna_subtype, &subtype_id);
PyObject *item = PyUnicode_FromString(subtype_id);
PyDict_SetItemString(dict, "subtype", item);
Py_DECREF(item);
}
/* Description. */
if (ui_data->description != NULL) {
PyObject *item = PyUnicode_FromString(ui_data->description);
PyDict_SetItemString(dict, "description", item);
Py_DECREF(item);
}
/* Type specific data. */
switch (IDP_ui_data_type(property)) {
case IDP_UI_DATA_TYPE_STRING:
idprop_ui_data_to_dict_string(property, dict);
break;
case IDP_UI_DATA_TYPE_ID:
break;
case IDP_UI_DATA_TYPE_INT:
idprop_ui_data_to_dict_int(property, dict);
break;
case IDP_UI_DATA_TYPE_BOOLEAN:
idprop_ui_data_to_dict_bool(property, dict);
break;
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
case IDP_UI_DATA_TYPE_FLOAT:
idprop_ui_data_to_dict_float(property, dict);
break;
case IDP_UI_DATA_TYPE_UNSUPPORTED:
BLI_assert_unreachable();
break;
}
return dict;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI Data Clear
* \{ */
PyDoc_STRVAR(BPy_IDPropertyUIManager_clear_doc,
".. method:: clear()\n"
"\n"
" Remove the RNA UI data from this IDProperty.\n");
static PyObject *BPy_IDPropertyUIManager_clear(BPy_IDPropertyUIManager *self)
{
IDProperty *property = self->property;
BLI_assert(IDP_ui_data_supported(property));
if (property == NULL) {
PyErr_SetString(PyExc_RuntimeError, "IDPropertyUIManager missing property");
BLI_assert_unreachable();
return NULL;
}
if (property->ui_data != NULL) {
IDP_ui_data_free(property);
}
Py_RETURN_NONE;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI Data Copying
* \{ */
PyDoc_STRVAR(
BPy_IDPropertyUIManager_update_from_doc,
".. method:: update_from(ui_manager_source)\n"
"\n"
" Copy UI data from an IDProperty in the source group to a property in this group.\n "
" If the source property has no UI data, the target UI data will be reset if it exists.\n"
"\n"
" :raises TypeError: If the types of the two properties don't match.\n");
static PyObject *BPy_IDPropertyUIManager_update_from(BPy_IDPropertyUIManager *self, PyObject *args)
{
IDProperty *property = self->property;
BLI_assert(IDP_ui_data_supported(property));
BPy_IDPropertyUIManager *ui_manager_src;
if (!PyArg_ParseTuple(args, "O!:update_from", &BPy_IDPropertyUIManager_Type, &ui_manager_src)) {
return NULL;
}
if (property->ui_data != NULL) {
IDP_ui_data_free(property);
}
if (ui_manager_src->property && ui_manager_src->property->ui_data) {
property->ui_data = IDP_ui_data_copy(ui_manager_src->property);
}
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
Py_RETURN_NONE;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UI Data Manager Definition
* \{ */
static struct PyMethodDef BPy_IDPropertyUIManager_methods[] = {
{"update",
(PyCFunction)BPy_IDPropertyUIManager_update,
METH_VARARGS | METH_KEYWORDS,
BPy_IDPropertyUIManager_update_doc},
{"as_dict",
(PyCFunction)BPy_IDIDPropertyUIManager_as_dict,
METH_NOARGS,
BPy_IDPropertyUIManager_as_dict_doc},
{"clear",
(PyCFunction)BPy_IDPropertyUIManager_clear,
METH_NOARGS,
BPy_IDPropertyUIManager_clear_doc},
{"update_from",
(PyCFunction)BPy_IDPropertyUIManager_update_from,
METH_VARARGS,
BPy_IDPropertyUIManager_update_from_doc},
{NULL, NULL, 0, NULL},
};
static PyObject *BPy_IDPropertyUIManager_repr(BPy_IDPropertyUIManager *self)
{
return PyUnicode_FromFormat(
"<bpy id prop ui manager: name=\"%s\", address=%p>", self->property->name, self->property);
}
static Py_hash_t BPy_IDPropertyUIManager_hash(BPy_IDPropertyUIManager *self)
{
return _Py_HashPointer(self->property);
}
PyTypeObject BPy_IDPropertyUIManager_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format `<module>.<name>`. */
/*tp_name*/ "IDPropertyUIManager",
/*tp_basicsize*/ sizeof(BPy_IDPropertyUIManager),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ NULL,
/*tp_vectorcall_offset*/ 0,
/*tp_getattr*/ NULL,
/*tp_setattr*/ NULL,
/*tp_as_async*/ NULL,
/*tp_repr*/ (reprfunc)BPy_IDPropertyUIManager_repr,
/*tp_as_number*/ NULL,
/*tp_as_sequence*/ NULL,
/*tp_as_mapping*/ NULL,
/*tp_hash*/ (hashfunc)BPy_IDPropertyUIManager_hash,
/*tp_call*/ NULL,
/*tp_str*/ NULL,
/*tp_getattro*/ NULL,
/*tp_setattro*/ NULL,
/*tp_as_buffer*/ NULL,
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
/*tp_doc*/ NULL,
/*tp_traverse*/ NULL,
/*tp_clear*/ NULL,
/*tp_richcompare*/ NULL,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ NULL,
/*tp_iternext*/ NULL,
/*tp_methods*/ BPy_IDPropertyUIManager_methods,
/*tp_members*/ NULL,
/*tp_getset*/ NULL,
/*tp_base*/ NULL,
/*tp_dict*/ NULL,
/*tp_descr_get*/ NULL,
/*tp_descr_set*/ NULL,
/*tp_dictoffset*/ 0,
/*tp_init*/ NULL,
/*tp_alloc*/ NULL,
/*tp_new*/ NULL,
/*tp_free*/ NULL,
/*tp_is_gc*/ NULL,
/*tp_bases*/ NULL,
/*tp_mro*/ NULL,
/*tp_cache*/ NULL,
/*tp_subclasses*/ NULL,
/*tp_weaklist*/ NULL,
/*tp_del*/ NULL,
/*tp_version_tag*/ 0,
/*tp_finalize*/ NULL,
/*tp_vectorcall*/ NULL,
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
};
void IDPropertyUIData_Init_Types(void)
Refactor IDProperty UI data storage The storage of IDProperty UI data (min, max, default value, etc) is quite complicated. For every property, retrieving a single one of these values involves three string lookups. First for the "_RNA_UI" group property, then another for a group with the property's name, then for the data value name. Not only is this inefficient, it's hard to reason about, unintuitive, and not at all self-explanatory. This commit replaces that system with a UI data struct directly in the IDProperty. If it's not used, the only cost is of a NULL pointer. Beyond storing the description, name, and RNA subtype, derived structs are used to store type specific UI data like min and max. Note that this means that addons using (abusing) the `_RNA_UI` custom property will have to be changed. A few places in the addons repository will be changed after this commit with D9919. **Before** Before, first the _RNA_UI subgroup is retrieved the _RNA_UI group, then the subgroup for the original property, then specific UI data is accessed like any other IDProperty. ``` prop = rna_idprop_ui_prop_get(idproperties_owner, "prop_name", create=True) prop["min"] = 1.0 ``` **After** After, the `id_properties_ui` function for RNA structs returns a python object specifically for managing an IDProperty's UI data. ``` ui_data = idproperties_owner.id_properties_ui("prop_name") ui_data.update(min=1.0) ``` In addition to `update`, there are now other functions: - `as_dict`: Returns a dictionary of the property's UI data. - `clear`: Removes the property's UI data. - `update_from`: Copy UI data between properties, even if they have different owners. Differential Revision: https://developer.blender.org/D9697
2021-08-27 15:27:24 +02:00
{
PyType_Ready(&BPy_IDPropertyUIManager_Type);
}
/** \} */