diff options
author | Bastien Montagne <bastien@blender.org> | 2020-09-19 13:13:04 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-09-20 18:00:07 +0300 |
commit | 86c5d1f4aa07551b289619da501889a172a39e03 (patch) | |
tree | 1983e7dd4080e31089e3793b7eb5a631afb8d379 /source/blender | |
parent | 1c98bb83a4d401478188eaf1e8dd52c7c489c3a5 (diff) |
LibOverride: add checks to RNA collections editing utils.
Collections of liboverride data only support insertion of new items (and
deleting or moving those around). No operation on existing items from linked
data is allowed.
Reflect that in RNA functions used to edit py-defined RNA collections.
Note that this is not ideal currently, it does the job but feedback to
user is rather poor. Ideally add-ons should implement higher-level
checks for override cases in their operators.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/makesdna/DNA_ID.h | 5 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 97 |
2 files changed, 100 insertions, 2 deletions
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 1e24ec24dc2..ea1e1d7ee0e 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -130,6 +130,11 @@ enum { * Should only be used/be relevant for custom properties. */ IDP_FLAG_OVERRIDABLE_LIBRARY = 1 << 0, + /** This collection item IDProp has been inserted in a local override. + * This is used by internal code to distinguish between library-originated items and + * local-insterted ones, as many operations are not allowed on the former. */ + IDP_FLAG_OVERRIDELIBRARY_LOCAL = 1 << 1, + /** This means the property is set but RNA will return false when checking * 'RNA_property_is_set', currently this is a runtime flag */ IDP_FLAG_GHOST = 1 << 7, diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 45508aec67a..f6ccd4ac443 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3988,18 +3988,67 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop) } } +/* This helper checks whether given collection property itself is editable (we only currently + * support a limited set of operations, insertion of new items, and re-ordering of those new items + * exclusively). */ +static bool property_collection_liboverride_editable(PointerRNA *ptr, + PropertyRNA *prop, + bool *r_is_liboverride) +{ + ID *id = ptr->owner_id; + if (id == NULL) { + *r_is_liboverride = false; + return true; + } + + const bool is_liboverride = *r_is_liboverride = ID_IS_OVERRIDE_LIBRARY(id); + + if (!is_liboverride) { + /* We return True also for linked data, as it allows tricks like py scripts 'overriding' data + * of those.*/ + return true; + } + + if (!RNA_property_overridable_get(ptr, prop)) { + return false; + } + + if (prop->magic != RNA_MAGIC || (prop->flag & PROP_IDPROPERTY) == 0) { + /* Insertion and such not supported for pure IDProperties for now, nor for pure RNA/DNA ones. + */ + return false; + } + if ((prop->flag_override & PROPOVERRIDE_LIBRARY_INSERTION) == 0) { + return false; + } + + /* No more checks to do, this collections is overridable. */ + return true; +} + void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr) { IDProperty *idprop; - /* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */ + /* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */ BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); + bool is_liboverride; + if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) { + if (r_ptr) { + memset(r_ptr, 0, sizeof(*r_ptr)); + } + return; + } + if ((idprop = rna_idproperty_check(&prop, ptr))) { IDPropertyTemplate val = {0}; IDProperty *item; item = IDP_New(IDP_GROUP, &val, ""); + if (is_liboverride) { + item->flag |= IDP_FLAG_OVERRIDELIBRARY_LOCAL; + } IDP_AppendArray(idprop, item); /* IDP_AppendArray does a shallow copy (memcpy), only free memory */ /* IDP_FreePropertyContent(item); */ @@ -4016,6 +4065,9 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA IDP_AddToGroup(group, idprop); item = IDP_New(IDP_GROUP, &val, ""); + if (is_liboverride) { + item->flag |= IDP_FLAG_OVERRIDELIBRARY_LOCAL; + } IDP_AppendArray(idprop, item); /* IDP_AppendArray does a shallow copy (memcpy), only free memory */ /* IDP_FreePropertyContent(item); */ @@ -4064,6 +4116,11 @@ bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); + bool is_liboverride; + if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) { + return false; + } + if ((idprop = rna_idproperty_check(&prop, ptr))) { IDProperty tmp, *array; int len; @@ -4072,6 +4129,11 @@ bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) array = IDP_IDPArray(idprop); if (key >= 0 && key < len) { + if (is_liboverride && (array[key].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) == 0) { + /* We can only remove items that we actually inserted in the local override. */ + return false; + } + if (key + 1 < len) { /* move element to be removed to the back */ memcpy(&tmp, &array[key], sizeof(IDProperty)); @@ -4118,6 +4180,11 @@ bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, i BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); + bool is_liboverride; + if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) { + return false; + } + if ((idprop = rna_idproperty_check(&prop, ptr))) { IDProperty tmp, *array; int len; @@ -4126,6 +4193,11 @@ bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, i array = IDP_IDPArray(idprop); if (key >= 0 && key < len && pos >= 0 && pos < len && key != pos) { + if (is_liboverride && (array[key].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) == 0) { + /* We can only move items that we actually inserted in the local override. */ + return false; + } + memcpy(&tmp, &array[key], sizeof(IDProperty)); if (pos < key) { memmove(array + pos + 1, array + pos, sizeof(IDProperty) * (key - pos)); @@ -4151,8 +4223,29 @@ void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop) BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); + bool is_liboverride; + if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) { + return; + } + if ((idprop = rna_idproperty_check(&prop, ptr))) { - IDP_ResizeIDPArray(idprop, 0); + if (is_liboverride) { + /* We can only move items that we actually inserted in the local override. */ + int len = idprop->len; + IDProperty tmp, *array = IDP_IDPArray(idprop); + for (int i = 0; i < len; i++) { + if ((array[i].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) != 0) { + memcpy(&tmp, &array[i], sizeof(IDProperty)); + memmove(array + i, array + i + 1, sizeof(IDProperty) * (len - (i + 1))); + memcpy(&array[len - 1], &tmp, sizeof(IDProperty)); + IDP_ResizeIDPArray(idprop, --len); + i--; + } + } + } + else { + IDP_ResizeIDPArray(idprop, 0); + } rna_idproperty_touch(idprop); } } |