Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/makesdna/DNA_ID.h5
-rw-r--r--source/blender/makesrna/intern/rna_access.c97
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);
}
}