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.
This commit is contained in:
Bastien Montagne 2020-07-10 15:19:40 +02:00
parent 6c1157201a
commit 337e2c9029
Notes: blender-bot 2024-02-19 11:28:23 +01:00
Referenced by issue #79633, "Copy to selected" on cycles properties (e.g. "shadow terminator offset") asserts / is broken
Referenced by pull request #118453, Fix: `is_overridable` crash with certain ShapeKey functions parameters
3 changed files with 104 additions and 18 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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.