Python API: Add functions to ensure and clear IDProperties

This adds id_properties_clear() and id_properties_ensure() functions
to RNA structs. This is meant as an initial change based on discussion
in review of D9697. However, they may be useful in other situations.

The change requires refactoring the internal idproperties callback to
return a pointer to the IDProperty pointer, which actually turns out
to be quite a nice cleanup.

An id_properties attribute could be added in the future potentially.

Differential Revision: https://developer.blender.org/D11908
This commit is contained in:
Hans Goudey 2021-07-14 10:51:28 -04:00
parent 37a5ff4a84
commit c202d38659
19 changed files with 129 additions and 151 deletions

View File

@ -811,6 +811,7 @@ void RNA_struct_py_type_set(StructRNA *srna, void *py_type);
void *RNA_struct_blender_type_get(StructRNA *srna);
void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type);
struct IDProperty **RNA_struct_idprops_p(PointerRNA *ptr);
struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create);
bool RNA_struct_idprops_check(StructRNA *srna);
bool RNA_struct_idprops_register_check(const StructRNA *type);

View File

@ -493,9 +493,10 @@ StructRNA *rna_ID_refine(PointerRNA *ptr)
return ID_code_to_RNA_type(GS(id->name));
}
IDProperty *rna_ID_idprops(PointerRNA *ptr, bool create)
IDProperty **rna_ID_idprops(PointerRNA *ptr)
{
return IDP_GetProperties(ptr->data, create);
ID *id = (ID *)ptr->data;
return &id->properties;
}
void rna_ID_fake_user_set(PointerRNA *ptr, bool value)
@ -510,9 +511,9 @@ void rna_ID_fake_user_set(PointerRNA *ptr, bool value)
}
}
IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, bool UNUSED(create))
IDProperty **rna_PropertyGroup_idprops(PointerRNA *ptr)
{
return ptr->data;
return (IDProperty **)&ptr->data;
}
void rna_PropertyGroup_unregister(Main *UNUSED(bmain), StructRNA *type)
@ -1162,12 +1163,12 @@ static PointerRNA rna_IDPreview_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ImagePreview, prv_img);
}
static IDProperty *rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr, bool UNUSED(create))
static IDProperty **rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr)
{
if (ptr == NULL) {
return NULL;
}
return ptr->data;
return (IDProperty **)&ptr->data;
}
static void rna_Library_version_get(PointerRNA *ptr, int *value)

View File

@ -369,15 +369,32 @@ static bool rna_idproperty_ui_set_default(PointerRNA *ptr,
return true;
}
IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
IDProperty **RNA_struct_idprops_p(PointerRNA *ptr)
{
StructRNA *type = ptr->type;
if (type && type->idproperties) {
return type->idproperties(ptr, create);
if (type == NULL) {
return NULL;
}
if (type->idproperties == NULL) {
return NULL;
}
return NULL;
return type->idproperties(ptr);
}
IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
{
IDProperty **property_ptr = RNA_struct_idprops_p(ptr);
if (property_ptr == NULL) {
return NULL;
}
if (create && *property_ptr == NULL) {
IDPropertyTemplate val = {0};
*property_ptr = IDP_New(IDP_GROUP, &val, __func__);
}
return *property_ptr;
}
bool RNA_struct_idprops_check(StructRNA *srna)

View File

@ -260,28 +260,16 @@ static char *rna_Bone_path(PointerRNA *ptr)
return BLI_sprintfN("bones[\"%s\"]", name_esc);
}
static IDProperty *rna_Bone_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_Bone_idprops(PointerRNA *ptr)
{
Bone *bone = ptr->data;
if (create && !bone->prop) {
IDPropertyTemplate val = {0};
bone->prop = IDP_New(IDP_GROUP, &val, "RNA_Bone ID properties");
}
return bone->prop;
return &bone->prop;
}
static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_EditBone_idprops(PointerRNA *ptr)
{
EditBone *ebone = ptr->data;
if (create && !ebone->prop) {
IDPropertyTemplate val = {0};
ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
}
return ebone->prop;
return &ebone->prop;
}
static void rna_bone_layer_set(int *layer, const bool *values)

View File

@ -75,16 +75,10 @@ static void rna_AssetMetaData_tag_remove(AssetMetaData *asset_data,
RNA_POINTER_INVALIDATE(tag_ptr);
}
static IDProperty *rna_AssetMetaData_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_AssetMetaData_idprops(PointerRNA *ptr)
{
AssetMetaData *asset_data = ptr->data;
if (create && !asset_data->properties) {
IDPropertyTemplate val = {0};
asset_data->properties = IDP_New(IDP_GROUP, &val, "RNA_AssetMetaData group");
}
return asset_data->properties;
return &asset_data->properties;
}
static void rna_AssetMetaData_description_get(PointerRNA *ptr, char *value)

View File

@ -276,10 +276,10 @@ void rna_ID_name_get(struct PointerRNA *ptr, char *value);
int rna_ID_name_length(struct PointerRNA *ptr);
void rna_ID_name_set(struct PointerRNA *ptr, const char *value);
struct StructRNA *rna_ID_refine(struct PointerRNA *ptr);
struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, bool create);
struct IDProperty **rna_ID_idprops(struct PointerRNA *ptr);
void rna_ID_fake_user_set(struct PointerRNA *ptr, bool value);
void **rna_ID_instance(PointerRNA *ptr);
struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, bool create);
struct IDProperty **rna_PropertyGroup_idprops(struct PointerRNA *ptr);
void rna_PropertyGroup_unregister(struct Main *bmain, struct StructRNA *type);
struct StructRNA *rna_PropertyGroup_register(struct Main *bmain,
struct ReportList *reports,

View File

@ -54,7 +54,7 @@ typedef void (*ContextPropUpdateFunc)(struct bContext *C,
typedef void (*ContextUpdateFunc)(struct bContext *C, struct PointerRNA *ptr);
typedef int (*EditableFunc)(struct PointerRNA *ptr, const char **r_info);
typedef int (*ItemEditableFunc)(struct PointerRNA *ptr, int index);
typedef struct IDProperty *(*IDPropertiesFunc)(struct PointerRNA *ptr, bool create);
typedef struct IDProperty **(*IDPropertiesFunc)(struct PointerRNA *ptr);
typedef struct StructRNA *(*StructRefineFunc)(struct PointerRNA *ptr);
typedef char *(*StructPathFunc)(struct PointerRNA *ptr);
@ -559,7 +559,7 @@ struct StructRNA {
*/
StructInstanceFunc instance;
/* callback to get id properties */
/** Return the location of the struct's pointer to the root group IDProperty. */
IDPropertiesFunc idproperties;
/* functions of this struct */

View File

@ -119,16 +119,10 @@ static char *rna_ViewLayer_path(PointerRNA *ptr)
return BLI_sprintfN("view_layers[\"%s\"]", name_esc);
}
static IDProperty *rna_ViewLayer_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_ViewLayer_idprops(PointerRNA *ptr)
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
if (create && !view_layer->id_properties) {
IDPropertyTemplate val = {0};
view_layer->id_properties = IDP_New(IDP_GROUP, &val, "ViewLayer ID properties");
}
return view_layer->id_properties;
return &view_layer->id_properties;
}
static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, bContext *C)

View File

@ -1621,15 +1621,11 @@ static void rna_NodesModifier_node_group_update(Main *bmain, Scene *scene, Point
MOD_nodes_update_interface(object, nmd);
}
static IDProperty *rna_NodesModifier_properties(PointerRNA *ptr, bool create)
static IDProperty **rna_NodesModifier_properties(PointerRNA *ptr)
{
NodesModifierData *nmd = ptr->data;
NodesModifierSettings *settings = &nmd->settings;
if (create && settings->properties == NULL) {
IDPropertyTemplate val = {0};
settings->properties = IDP_New(IDP_GROUP, &val, "Nodes Modifier Settings");
}
return settings->properties;
return &settings->properties;
}
#else

View File

@ -2366,16 +2366,10 @@ static StructRNA *rna_FunctionNode_register(Main *bmain,
return nt->rna_ext.srna;
}
static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_Node_idprops(PointerRNA *ptr)
{
bNode *node = ptr->data;
if (create && !node->prop) {
IDPropertyTemplate val = {0};
node->prop = IDP_New(IDP_GROUP, &val, "RNA_Node ID properties");
}
return node->prop;
return &node->prop;
}
static void rna_Node_parent_set(PointerRNA *ptr,
@ -2834,16 +2828,10 @@ static char *rna_NodeSocket_path(PointerRNA *ptr)
}
}
static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_NodeSocket_idprops(PointerRNA *ptr)
{
bNodeSocket *sock = ptr->data;
if (create && !sock->prop) {
IDPropertyTemplate val = {0};
sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocket ID properties");
}
return sock->prop;
return &sock->prop;
}
static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
@ -3150,16 +3138,10 @@ static char *rna_NodeSocketInterface_path(PointerRNA *ptr)
return NULL;
}
static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_NodeSocketInterface_idprops(PointerRNA *ptr)
{
bNodeSocket *sock = ptr->data;
if (create && !sock->prop) {
IDPropertyTemplate val = {0};
sock->prop = IDP_New(IDP_GROUP, &val, "RNA_NodeSocketInterface ID properties");
}
return sock->prop;
return &sock->prop;
}
static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@ -9950,7 +9932,7 @@ static void def_geo_switch(StructRNA *srna)
static void def_geo_curve_primitive_quadrilateral(StructRNA *srna)
{
PropertyRNA *prop;
static EnumPropertyItem mode_items[] = {
{GEO_NODE_CURVE_PRIMITIVE_QUAD_MODE_RECTANGLE,
"RECTANGLE",

View File

@ -224,16 +224,10 @@ static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
sizeof(agrp->name));
}
static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_PoseBone_idprops(PointerRNA *ptr)
{
bPoseChannel *pchan = ptr->data;
if (create && !pchan->prop) {
IDPropertyTemplate val = {0};
pchan->prop = IDP_New(IDP_GROUP, &val, "RNA_PoseBone group");
}
return pchan->prop;
return &pchan->prop;
}
static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value)

View File

@ -734,16 +734,10 @@ static char *rna_Sequence_path(PointerRNA *ptr)
}
}
static IDProperty *rna_Sequence_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_Sequence_idprops(PointerRNA *ptr)
{
Sequence *seq = ptr->data;
if (create && !seq->prop) {
IDPropertyTemplate val = {0};
seq->prop = IDP_New(IDP_GROUP, &val, "Sequence ID properties");
}
return seq->prop;
return &seq->prop;
}
static bool rna_MovieSequence_reload_if_needed(ID *scene_id, Sequence *seq, Main *bmain)

View File

@ -1041,16 +1041,10 @@ static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr)
return RV3D_VIEW_IS_AXIS(rv3d->view);
}
static IDProperty *rna_View3DShading_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_View3DShading_idprops(PointerRNA *ptr)
{
View3DShading *shading = ptr->data;
if (create && !shading->prop) {
IDPropertyTemplate val = {0};
shading->prop = IDP_New(IDP_GROUP, &val, "View3DShading ID properties");
}
return shading->prop;
return &shading->prop;
}
static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr)

View File

@ -33,16 +33,10 @@
# include "BKE_idprop.h"
# include "WM_api.h"
static IDProperty *rna_TimelineMarker_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_TimelineMarker_idprops(PointerRNA *ptr)
{
TimeMarker *marker = ptr->data;
if (create && marker->prop == NULL) {
IDPropertyTemplate val = {0};
marker->prop = IDP_New(IDP_GROUP, &val, "Marker ID properties");
}
return marker->prop;
return &marker->prop;
}
static void rna_TimelineMarker_update(Main *UNUSED(bmain),

View File

@ -452,15 +452,10 @@ static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *UNUSED(p
return UILST_FLT_ITEM;
}
static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_UIList_idprops(PointerRNA *ptr)
{
uiList *ui_list = (uiList *)ptr->data;
if (create && !ui_list->properties) {
IDPropertyTemplate val = {0};
ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group");
}
return ui_list->properties;
return &ui_list->properties;
}
static void uilist_draw_item(uiList *ui_list,

View File

@ -809,14 +809,9 @@ static const EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C
}
# endif
static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_AddonPref_idprops(PointerRNA *ptr)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
ptr->data = IDP_New(IDP_GROUP, &val, "RNA_AddonPreferences group");
}
return ptr->data;
return (IDProperty **)&ptr->data;
}
static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr)

View File

@ -568,14 +568,9 @@ static StructRNA *rna_OperatorProperties_refine(PointerRNA *ptr)
}
}
static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_OperatorProperties_idprops(PointerRNA *ptr)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
ptr->data = IDP_New(IDP_GROUP, &val, "RNA_OperatorProperties group");
}
return ptr->data;
return (IDProperty **)&ptr->data;
}
static void rna_Operator_name_get(PointerRNA *ptr, char *value)
@ -1120,13 +1115,9 @@ static PointerRNA rna_wmKeyConfig_preferences_get(PointerRNA *ptr)
}
}
static IDProperty *rna_wmKeyConfigPref_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_wmKeyConfigPref_idprops(PointerRNA *ptr)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
ptr->data = IDP_New(IDP_GROUP, &val, "RNA_KeyConfigPreferences group");
}
return ptr->data;
return (IDProperty **)&ptr->data;
}
static void rna_wmKeyConfigPref_unregister(Main *UNUSED(bmain), StructRNA *type)

View File

@ -293,14 +293,9 @@ static StructRNA *rna_GizmoProperties_refine(PointerRNA *ptr)
}
}
static IDProperty *rna_GizmoProperties_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_GizmoProperties_idprops(PointerRNA *ptr)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
ptr->data = IDP_New(IDP_GROUP, &val, "RNA_GizmoProperties group");
}
return ptr->data;
return (IDProperty **)&ptr->data;
}
static PointerRNA rna_Gizmo_properties_get(PointerRNA *ptr)
@ -585,14 +580,9 @@ static StructRNA *rna_GizmoGroupProperties_refine(PointerRNA *ptr)
}
}
static IDProperty *rna_GizmoGroupProperties_idprops(PointerRNA *ptr, bool create)
static IDProperty **rna_GizmoGroupProperties_idprops(PointerRNA *ptr)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
ptr->data = IDP_New(IDP_GROUP, &val, "RNA_GizmoGroupProperties group");
}
return ptr->data;
return (IDProperty **)&ptr->data;
}
static wmGizmo *rna_GizmoGroup_gizmo_new(wmGizmoGroup *gzgroup,

View File

@ -4253,6 +4253,56 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self)
return ret;
}
PyDoc_STRVAR(pyrna_struct_id_properties_ensure_doc,
".. method:: id_properties_ensure()\n"
" :return: the parent group for an RNA struct's custom IDProperties.\n"
" :rtype: :class:`bpy.types.IDPropertyGroup`\n");
static PyObject *pyrna_struct_id_properties_ensure(BPy_StructRNA *self)
{
PYRNA_STRUCT_CHECK_OBJ(self);
if (RNA_struct_idprops_check(self->ptr.type) == 0) {
PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
return NULL;
}
IDProperty *idprops = RNA_struct_idprops(&self->ptr, true);
/* This is a paranoid check that theoretically might not be necessary.
* It allows the possibility that some structs can't ensure IDProperties. */
if (idprops == NULL) {
return Py_None;
}
BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type);
group->owner_id = self->ptr.owner_id;
group->prop = idprops;
group->parent = NULL;
return (PyObject *)group;
}
PyDoc_STRVAR(pyrna_struct_id_properties_clear_doc,
".. method:: id_properties_clear()\n"
" :return: Remove the parent group for an RNA struct's custom IDProperties.\n");
static PyObject *pyrna_struct_id_properties_clear(BPy_StructRNA *self)
{
PYRNA_STRUCT_CHECK_OBJ(self);
if (RNA_struct_idprops_check(self->ptr.type) == 0) {
PyErr_SetString(PyExc_TypeError, "This type doesn't support IDProperties");
return NULL;
}
IDProperty **idprops = RNA_struct_idprops_p(&self->ptr);
if (*idprops) {
IDP_FreeProperty(*idprops);
*idprops = NULL;
}
Py_RETURN_NONE;
}
/* ---------------getattr-------------------------------------------- */
static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname)
{
@ -5743,6 +5793,14 @@ static struct PyMethodDef pyrna_struct_methods[] = {
METH_VARARGS | METH_CLASS,
pyrna_struct_bl_rna_get_subclass_doc},
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
{"id_properties_ensure",
(PyCFunction)pyrna_struct_id_properties_ensure,
METH_NOARGS,
pyrna_struct_id_properties_ensure_doc},
{"id_properties_clear",
(PyCFunction)pyrna_struct_id_properties_clear,
METH_NOARGS,
pyrna_struct_id_properties_clear_doc},
/* experimental */
/* unused for now */