From 337e2c902930d8a8980505d66234bc46c95b051c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 10 Jul 2020 15:19:40 +0200 Subject: RNA: refactor how we get 'ensured' RNA properties. Introduce new PropertyRNAOrID structure, storing most useful data about an 'opaque' PropertyRNA in relation with a given PointerRNA struct. It deals with all the three cases (pure static RNA, runtime RNA where data is actually stored in IDProperties, and pure IDProperties, aka custom data. --- source/blender/makesrna/intern/rna_access.c | 79 +++++++++++++++++----- .../blender/makesrna/intern/rna_access_internal.h | 4 ++ .../blender/makesrna/intern/rna_internal_types.h | 39 +++++++++++ 3 files changed, 104 insertions(+), 18 deletions(-) (limited to 'source/blender') diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 79cf993e0cc..c3b417ca79d 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -558,9 +558,12 @@ static PropertyRNA *arraytypemap[IDP_NUMTYPES] = { (PropertyRNA *)&rna_PropertyGroupItem_double_array, }; -static void *rna_idproperty_check_ex(PropertyRNA **prop, - PointerRNA *ptr, - const bool return_rnaprop) +/* This function initializes a PropertyRNAOrID with all required info, from a given PropertyRNA + * and PointerRNA data. It deals properly with the three cases (static RNA, runtime RNA, and + * IDProperty). */ +void rna_property_rna_or_id_get(PropertyRNA *prop, + PointerRNA *ptr, + PropertyRNAOrID *r_prop_rna_or_id) { /* This is quite a hack, but avoids some complexity in the API. we * pass IDProperty structs as PropertyRNA pointers to the outside. @@ -568,36 +571,64 @@ static void *rna_idproperty_check_ex(PropertyRNA **prop, * distinguish it from IDProperty structs. If it is an ID property, * we look up an IDP PropertyRNA based on the type, and set the data * pointer to the IDProperty. */ + memset(r_prop_rna_or_id, 0, sizeof(*r_prop_rna_or_id)); - if ((*prop)->magic == RNA_MAGIC) { - if ((*prop)->flag & PROP_IDPROPERTY) { - IDProperty *idprop = rna_idproperty_find(ptr, (*prop)->identifier); + r_prop_rna_or_id->ptr = *ptr; + r_prop_rna_or_id->rawprop = prop; - if (idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) { + if (prop->magic == RNA_MAGIC) { + r_prop_rna_or_id->rnaprop = prop; + r_prop_rna_or_id->identifier = prop->identifier; + + r_prop_rna_or_id->is_array = prop->getlength || prop->totarraylength; + if (r_prop_rna_or_id->is_array) { + int arraylen[RNA_MAX_ARRAY_DIMENSION]; + r_prop_rna_or_id->array_len = (prop->getlength && ptr->data) ? + (uint)prop->getlength(ptr, arraylen) : + prop->totarraylength; + } + + if (prop->flag & PROP_IDPROPERTY) { + IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier); + + if (idprop != NULL && !rna_idproperty_verify_valid(ptr, prop, idprop)) { IDProperty *group = RNA_struct_idprops(ptr, 0); IDP_FreeFromGroup(group, idprop); - return NULL; + idprop = NULL; } - return idprop; + r_prop_rna_or_id->idprop = idprop; + r_prop_rna_or_id->is_set = idprop != NULL && (idprop->flag & IDP_FLAG_GHOST) == 0; } else { - return return_rnaprop ? *prop : NULL; + /* Full static RNA properties are always set. */ + r_prop_rna_or_id->is_set = true; } } + else { + IDProperty *idprop = (IDProperty *)prop; + /* Given prop may come from the custom properties of another data, ensure we get the one from + * given data ptr. */ + IDProperty *idprop_evaluated = rna_idproperty_find(ptr, idprop->name); + if (idprop_evaluated != NULL && idprop->type != idprop_evaluated->type) { + idprop_evaluated = NULL; + } - { - IDProperty *idprop = (IDProperty *)(*prop); + r_prop_rna_or_id->idprop = idprop_evaluated; + r_prop_rna_or_id->is_idprop = true; + /* Full IDProperties are always set. */ + r_prop_rna_or_id->is_set = true; + r_prop_rna_or_id->identifier = idprop->name; if (idprop->type == IDP_ARRAY) { - *prop = arraytypemap[(int)(idprop->subtype)]; + r_prop_rna_or_id->rnaprop = arraytypemap[(int)(idprop->subtype)]; + r_prop_rna_or_id->is_array = true; + r_prop_rna_or_id->array_len = idprop_evaluated != NULL ? (uint)idprop_evaluated->len : 0; } else { - *prop = typemap[(int)(idprop->type)]; + r_prop_rna_or_id->rnaprop = typemap[(int)(idprop->type)]; } - - return idprop; } } @@ -605,14 +636,26 @@ static void *rna_idproperty_check_ex(PropertyRNA **prop, * or NULL (in case IDProp could not be found, or prop is a real RNA property). */ IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr) { - return rna_idproperty_check_ex(prop, ptr, false); + PropertyRNAOrID prop_rna_or_id; + + rna_property_rna_or_id_get(*prop, ptr, &prop_rna_or_id); + + *prop = prop_rna_or_id.rnaprop; + return prop_rna_or_id.idprop; } /* This function always return the valid, real data pointer, be it a regular RNA property one, * or an IDProperty one. */ PropertyRNA *rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr) { - return rna_idproperty_check_ex(prop, ptr, true); + PropertyRNAOrID prop_rna_or_id; + + rna_property_rna_or_id_get(*prop, ptr, &prop_rna_or_id); + + *prop = prop_rna_or_id.rnaprop; + return (prop_rna_or_id.is_idprop || prop_rna_or_id.idprop != NULL) ? + (PropertyRNA *)prop_rna_or_id.idprop : + prop_rna_or_id.rnaprop; } PropertyRNA *rna_ensure_property(PropertyRNA *prop) diff --git a/source/blender/makesrna/intern/rna_access_internal.h b/source/blender/makesrna/intern/rna_access_internal.h index c7995746d08..ecc9386ca77 100644 --- a/source/blender/makesrna/intern/rna_access_internal.h +++ b/source/blender/makesrna/intern/rna_access_internal.h @@ -26,8 +26,12 @@ #include "rna_internal_types.h" struct IDProperty; +struct PropertyRNAOrID; PropertyRNA *rna_ensure_property(PropertyRNA *prop); +void rna_property_rna_or_id_get(PropertyRNA *prop, + PointerRNA *ptr, + PropertyRNAOrID *r_prop_rna_or_id); void rna_idproperty_touch(struct IDProperty *idprop); struct IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name); diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 345d84fc5b1..6336be25ac3 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -41,6 +41,8 @@ struct Scene; struct StructRNA; struct bContext; +typedef struct IDProperty IDProperty; + /* store local properties here */ #define RNA_IDP_UI "_RNA_UI" @@ -155,6 +157,43 @@ typedef void (*PropEnumSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *pr /* Handling override operations, and also comparison. */ +/** Structure storing all needed data to process all three kinds of RNA properties. */ +typedef struct PropertyRNAOrID { + PointerRNA ptr; + + /** The PropertyRNA passed as parameter, used to generate that structure's content: + * - Static RNA: The RNA property (same as `rnaprop`), never NULL. + * - Runtime RNA: The RNA property (same as `rnaprop`), never NULL. + * - IDProperty: The IDProperty, never NULL. + */ + PropertyRNA *rawprop; + /** The real RNA property of this property, never NULL: + * - Static RNA: The rna property, also gives direct access to the data (from any matching + * PointerRNA). + * - Runtime RNA: The rna property, does not directly gives access to the data. + * - IDProperty: The generic PropertyRNA matching its type. + */ + PropertyRNA *rnaprop; + /** The IDProperty storing the data of this property, may be NULL: + * - Static RNA: Always NULL. + * - Runtime RNA: The IDProperty storing the data of that property, may be NULL if never set yet. + * - IDProperty: The IDProperty, never NULL. + */ + IDProperty *idprop; + /** The name of the property. */ + const char *identifier; + + /** Whether this property is a 'pure' IDProperty or not. */ + bool is_idprop; + /** For runtime RNA properties, whether it is set, defined, or not. + * WARNING: This DOES take into account the `IDP_FLAG_GHOST` flag, i.e. it matches result of + * `RNA_property_is_set`. */ + bool is_set; + + bool is_array; + uint array_len; +} PropertyRNAOrID; + /** * If \a override is NULL, merely do comparison between prop_a from ptr_a and prop_b from ptr_b, * following comparison mode given. -- cgit v1.2.3