Use struct identifiers in comments before the value. This has some advantages: - The struct identifiers didn't mix well with other code-comments, where other comments were wrapped onto the next line. - Minor changes could re-align all other comments in the struct. - PyVarObject_HEAD_INIT & tp_name are no longer placed on the same line. Remove overly verbose comments copied from PyTypeObject (Python v2.x), these aren't especially helpful and get outdated. Also corrected some outdated names: - PyTypeObject.tp_print -> tp_vectorcall_offset - PyTypeObject.tp_reserved -> tp_as_async
720 lines
23 KiB
C
720 lines
23 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \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"
|
|
|
|
#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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/**
|
|
* \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;
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/**
|
|
* \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);
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/**
|
|
* \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;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
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_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));
|
|
Py_DECREF(item);
|
|
}
|
|
}
|
|
|
|
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));
|
|
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));
|
|
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_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);
|
|
}
|
|
|
|
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,
|
|
};
|
|
|
|
void IDPropertyUIData_Init_Types()
|
|
{
|
|
PyType_Ready(&BPy_IDPropertyUIManager_Type);
|
|
}
|
|
|
|
/** \} */
|