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:
Diffstat (limited to 'source/blender/makesrna/intern/rna_access.c')
-rw-r--r--source/blender/makesrna/intern/rna_access.c1018
1 files changed, 796 insertions, 222 deletions
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index daa01f58e12..0532aac1bc3 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -34,6 +34,8 @@
#include "DNA_ID.h"
#include "DNA_scene_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
@@ -42,6 +44,10 @@
#include "BLI_ghash.h"
#include "BLI_math.h"
+#ifdef DEBUG_OVERRIDE_TIMEIT
+# include "PIL_time_utildefines.h"
+#endif
+
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -51,18 +57,21 @@
#include "BKE_idprop.h"
#include "BKE_fcurve.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
+#include "WM_message.h"
/* flush updates */
#include "DNA_object_types.h"
-#include "BKE_depsgraph.h"
#include "WM_types.h"
#include "rna_internal.h"
@@ -431,7 +440,7 @@ static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
(PropertyRNA *)&rna_PropertyGroupItem_double_array
};
-IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
+static void *rna_idproperty_check_ex(PropertyRNA **prop, PointerRNA *ptr, const bool return_rnaprop)
{
/* This is quite a hack, but avoids some complexity in the API. we
* pass IDProperty structs as PropertyRNA pointers to the outside.
@@ -453,8 +462,9 @@ IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
return idprop;
}
- else
- return NULL;
+ else {
+ return return_rnaprop ? *prop : NULL;
+ }
}
{
@@ -469,6 +479,19 @@ IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
}
}
+/* This function only returns an IDProperty,
+ * 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);
+}
+
+/* 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);
+}
+
static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
{
/* the quick version if we don't need the idproperty */
@@ -982,6 +1005,11 @@ int RNA_property_flag(PropertyRNA *prop)
return rna_ensure_property(prop)->flag;
}
+int RNA_property_override_flag(PropertyRNA *prop)
+{
+ return rna_ensure_property(prop)->flag_override;
+}
+
/**
* Get the tags set for \a prop as int bitfield.
* \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this
@@ -1819,7 +1847,8 @@ bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
return ((flag & PROP_EDITABLE) &&
(flag & PROP_REGISTER) == 0 &&
- (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)));
+ (!id || ((!ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)) &&
+ (!id->override_static || RNA_property_overridable_get(ptr, prop)))));
}
/**
@@ -1845,11 +1874,19 @@ bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char *
}
/* property from linked data-block */
- if (id && ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
- if (!(*r_info)[0]) {
- *r_info = N_("Can't edit this property from a linked data-block");
+ if (id) {
+ if (ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
+ if (!(*r_info)[0]) {
+ *r_info = N_("Can't edit this property from a linked data-block.");
+ }
+ return false;
+ }
+ if (id->override_static != NULL && !RNA_property_overridable_get(ptr, prop)) {
+ if (!(*r_info)[0]) {
+ *r_info = N_("Can't edit this property from an override data-block.");
+ }
+ return false;
}
- return false;
}
return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
@@ -1923,6 +1960,70 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
return false;
}
+/** \note Does not take into account editable status, this has to be checked separately
+ * (using RNA_property_edtiable_flag() usually). */
+bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop)
+{
+ if (prop->magic == RNA_MAGIC) {
+ /* Special handling for insertions of constraints or modifiers... */
+ /* TODO Note We may want to add a more generic system to RNA (like a special property in struct of items)
+ * if we get more overrideable collections, for now we can live with those special-cases handling I think. */
+ if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
+ bConstraint *con = ptr->data;
+ if (con->flag & CONSTRAINT_STATICOVERRIDE_LOCAL) {
+ return true;
+ }
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
+ ModifierData *mod = ptr->data;
+ if (mod->flag & eModifierFlag_StaticOverride_Local) {
+ return true;
+ }
+ }
+ /* If this is a RNA-defined property (real or 'virtual' IDProp), we want to use RNA prop flag. */
+ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && (prop->flag_override & PROPOVERRIDE_OVERRIDABLE_STATIC);
+ }
+ else {
+ /* If this is a real 'pure' IDProp (aka custom property), we want to use the IDProp flag. */
+ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) && (((IDProperty *)prop)->flag & IDP_FLAG_OVERRIDABLE_STATIC);
+ }
+}
+
+/* Should only be used for custom properties */
+bool RNA_property_overridable_static_set(PointerRNA *UNUSED(ptr), PropertyRNA *prop, const bool is_overridable)
+{
+ /* Only works for pure custom properties IDProps. */
+ if (prop->magic != RNA_MAGIC) {
+ IDProperty *idprop = (IDProperty *)prop;
+
+ idprop->flag = is_overridable ? (idprop->flag | IDP_FLAG_OVERRIDABLE_STATIC) :
+ (idprop->flag & ~IDP_FLAG_OVERRIDABLE_STATIC);
+ return true;
+ }
+
+ return false;
+}
+
+
+bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop)
+{
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ ID *id = ptr->id.data;
+
+ if (rna_path == NULL || id == NULL || id->override_static == NULL) {
+ return false;
+ }
+
+ return (BKE_override_static_property_find(id->override_static, rna_path) != NULL);
+}
+
+bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ prop = rna_ensure_property(prop);
+
+ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON);
+}
+
/* this function is to check if its possible to create a valid path from the ID
* its slow so don't call in a loop */
bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
@@ -1957,7 +2058,7 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR
* parts of the code that need it still, so we have this exception */
if (prop->flag & PROP_CONTEXT_UPDATE) {
if (C) {
- if (prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) {
+ if ((prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) == PROP_CONTEXT_PROPERTY_UPDATE) {
((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
}
else {
@@ -1968,14 +2069,35 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR
else
prop->update(bmain, scene, ptr);
}
- if (prop->noteflag)
+
+#if 1
+ /* TODO(campbell): Should eventually be replaced entirely by message bus (below)
+ * for now keep since COW, bugs are hard to track when we have other missing updates. */
+ if (prop->noteflag) {
WM_main_add_notifier(prop->noteflag, ptr->id.data);
+ }
+#endif
+
+ /* if C is NULL, we're updating from animation.
+ * avoid slow-down from f-curves by not publishing (for now). */
+ if (C != NULL) {
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ /* we could add NULL check, for now don't */
+ WM_msg_publish_rna(mbus, ptr, prop);
+ }
+ if (ptr->id.data != NULL) {
+ const short id_type = GS(((ID *)ptr->id.data)->name);
+ if (ID_TYPE_IS_COW(id_type)) {
+ DEG_id_tag_update(ptr->id.data, DEG_TAG_COPY_ON_WRITE);
+ }
+ }
+ /* End message bus. */
}
if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
/* WARNING! This is so property drivers update the display!
* not especially nice */
- DAG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_main_add_notifier(NC_WINDOW, NULL);
/* Not nice as well, but the only way to make sure material preview
* is updated with custom nodes.
@@ -6994,120 +7116,47 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
}
}
+static bool rna_property_override_operation_apply(
+ PointerRNA *ptr_local, PointerRNA *ptr_override, PointerRNA *ptr_storage,
+ PropertyRNA *prop_local, PropertyRNA *prop_override, PropertyRNA *prop_storage,
+ IDOverrideStaticPropertyOperation *opop);
+
bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
{
- int len, fromlen;
- PropertyRNA *fromprop = prop;
+ if (!RNA_property_editable(ptr, prop)) {
+ return false;
+ }
- if (prop->magic != RNA_MAGIC) {
- /* In case of IDProperty, we have to find the *real* idprop of ptr,
- * since prop in this case is just a fake wrapper around actual IDProp data, and not a 'real' PropertyRNA. */
- prop = (PropertyRNA *)rna_idproperty_find(ptr, ((IDProperty *)fromprop)->name);
+ PropertyRNA *prop_dst = prop;
+ PropertyRNA *prop_src = prop;
- /* its possible the custom-prop doesn't exist on this data-block */
- if (prop == NULL) {
- return false;
- }
+ /* Ensure we get real property data, be it an actual RNA property, or an IDProperty in disguise. */
+ prop_dst = rna_ensure_property_realdata(&prop_dst, ptr);
+ prop_src = rna_ensure_property_realdata(&prop_src, fromptr);
- /* Even though currently we now prop will always be the 'fromprop', this might not be the case in the future. */
- if (prop == fromprop) {
- fromprop = (PropertyRNA *)rna_idproperty_find(fromptr, ((IDProperty *)prop)->name);
- }
+ /* IDprops: destination may not exist, if source does and is set, try to create it. */
+ /* Note: this is sort of quick hack/bandage to fix the issue, we need to rethink how IDProps are handled
+ * in 'diff' RNA code completely, imho... */
+ if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) {
+ BLI_assert(prop_src->magic != RNA_MAGIC);
+ IDProperty *idp_dst = RNA_struct_idprops(ptr, true);
+ IDProperty *prop_idp_dst = IDP_CopyProperty((IDProperty *)prop_src);
+ IDP_AddToGroup(idp_dst, prop_idp_dst);
+ rna_idproperty_touch(prop_idp_dst);
+ /* Nothing else to do here... */
+ return true;
}
- /* get the length of the array to work with */
- len = RNA_property_array_length(ptr, prop);
- fromlen = RNA_property_array_length(fromptr, fromprop);
-
- if (len != fromlen)
+ if (ELEM(NULL, prop_dst, prop_src)) {
return false;
-
- /* get and set the default values as appropriate for the various types */
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- if (len) {
- if (index == -1) {
- int *tmparray = MEM_callocN(sizeof(int) * len, "copy - boolean");
-
- RNA_property_boolean_get_array(fromptr, fromprop, tmparray);
- RNA_property_boolean_set_array(ptr, prop, tmparray);
-
- MEM_freeN(tmparray);
- }
- else {
- int value = RNA_property_boolean_get_index(fromptr, fromprop, index);
- RNA_property_boolean_set_index(ptr, prop, index, value);
- }
- }
- else {
- int value = RNA_property_boolean_get(fromptr, fromprop);
- RNA_property_boolean_set(ptr, prop, value);
- }
- return true;
- case PROP_INT:
- if (len) {
- if (index == -1) {
- int *tmparray = MEM_callocN(sizeof(int) * len, "copy - int");
-
- RNA_property_int_get_array(fromptr, fromprop, tmparray);
- RNA_property_int_set_array(ptr, prop, tmparray);
-
- MEM_freeN(tmparray);
- }
- else {
- int value = RNA_property_int_get_index(fromptr, fromprop, index);
- RNA_property_int_set_index(ptr, prop, index, value);
- }
- }
- else {
- int value = RNA_property_int_get(fromptr, fromprop);
- RNA_property_int_set(ptr, prop, value);
- }
- return true;
- case PROP_FLOAT:
- if (len) {
- if (index == -1) {
- float *tmparray = MEM_callocN(sizeof(float) * len, "copy - float");
-
- RNA_property_float_get_array(fromptr, fromprop, tmparray);
- RNA_property_float_set_array(ptr, prop, tmparray);
-
- MEM_freeN(tmparray);
- }
- else {
- float value = RNA_property_float_get_index(fromptr, fromprop, index);
- RNA_property_float_set_index(ptr, prop, index, value);
- }
- }
- else {
- float value = RNA_property_float_get(fromptr, fromprop);
- RNA_property_float_set(ptr, prop, value);
- }
- return true;
- case PROP_ENUM:
- {
- int value = RNA_property_enum_get(fromptr, fromprop);
- RNA_property_enum_set(ptr, prop, value);
- return true;
- }
- case PROP_POINTER:
- {
- PointerRNA value = RNA_property_pointer_get(fromptr, fromprop);
- RNA_property_pointer_set(ptr, prop, value);
- return true;
- }
- case PROP_STRING:
- {
- char *value = RNA_property_string_get_alloc(fromptr, fromprop, NULL, 0, NULL);
- RNA_property_string_set(ptr, prop, value);
- MEM_freeN(value);
- return true;
- }
- default:
- return false;
}
- return false;
+ IDOverrideStaticPropertyOperation opop = {
+ .operation = IDOVERRIDESTATIC_OP_REPLACE,
+ .subitem_reference_index = index,
+ .subitem_local_index = index
+ };
+ return rna_property_override_operation_apply(ptr, fromptr, NULL, prop_dst, prop_src, NULL, &opop);
}
/* use RNA_warning macro which includes __func__ suffix */
@@ -7132,177 +7181,683 @@ void _RNA_warning(const char *format, ...)
#endif
}
-bool RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNAEqualsMode mode)
+static int rna_property_override_diff(
+ PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, PropertyRNA *prop_a, PropertyRNA *prop_b, const char *rna_path,
+ eRNACompareMode mode, IDOverrideStatic *override, const int flags, eRNAOverrideMatchResult *r_report_flags);
+
+bool RNA_property_equals(PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode)
+{
+ BLI_assert(ELEM(mode, RNA_EQ_STRICT, RNA_EQ_UNSET_MATCH_ANY, RNA_EQ_UNSET_MATCH_NONE));
+
+ return (rna_property_override_diff(ptr_a, ptr_b, prop, NULL, NULL, NULL, mode, NULL, 0, NULL) == 0);
+}
+
+bool RNA_struct_equals(PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
+ bool equals = true;
+
+ if (ptr_a == NULL && ptr_b == NULL)
+ return true;
+ else if (ptr_a == NULL || ptr_b == NULL)
+ return false;
+ else if (ptr_a->type != ptr_b->type)
+ return false;
+
+ iterprop = RNA_struct_iterator_property(ptr_a->type);
+
+ RNA_property_collection_begin(ptr_a, iterprop, &iter);
+ for (; iter.valid; RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop = iter.ptr.data;
+
+ if (!RNA_property_equals(ptr_a, ptr_b, prop, mode)) {
+ equals = false;
+ break;
+ }
+ }
+ RNA_property_collection_end(&iter);
+
+ return equals;
+}
+
+/* Low-level functions, also used by non-override RNA API like copy or equality check. */
+
+/** Generic RNA property diff function.
+ *
+ * \note about \a prop and \a prop_a/prop_b parameters: the former is exptected to be an 'un-resolved' one,
+ * while the two laters are expected to be fully resolved ones (i.e. to be the IDProps when they should be, etc.).
+ * When \a prop is given, \a prop_a and \a prop_b should always be NULL, and vice-versa.
+ * This is necessary, because we cannot perform 'set/unset' checks on resolved properties
+ * (unset IDProps would merely be NULL then).
+ *
+ * \note When there is no equality, but we cannot determine an order (greater than/lesser than), we return 1.
+ */
+static int rna_property_override_diff(
+ PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, PropertyRNA *prop_a, PropertyRNA *prop_b,
+ const char *rna_path, eRNACompareMode mode,
+ IDOverrideStatic *override, const int flags, eRNAOverrideMatchResult *r_report_flags)
{
- int len, fromlen;
+ if (prop != NULL) {
+ BLI_assert(prop_a == NULL && prop_b == NULL);
+ prop_a = prop;
+ prop_b = prop;
+ }
+
+ if (ELEM(NULL, prop_a, prop_b)) {
+ return (prop_a == prop_b) ? 0 : 1;
+ }
+
+ if (!RNA_property_comparable(ptr_a, prop_a) || !RNA_property_comparable(ptr_b, prop_b)) {
+ return 0;
+ }
if (mode == RNA_EQ_UNSET_MATCH_ANY) {
/* uninitialized properties are assumed to match anything */
- if (!RNA_property_is_set(a, prop) || !RNA_property_is_set(b, prop))
- return true;
+ if (!RNA_property_is_set(ptr_a, prop_a) || !RNA_property_is_set(ptr_b, prop_b)) {
+ return 0;
+ }
}
else if (mode == RNA_EQ_UNSET_MATCH_NONE) {
/* unset properties never match set properties */
- if (RNA_property_is_set(a, prop) != RNA_property_is_set(b, prop))
- return false;
+ if (RNA_property_is_set(ptr_a, prop_a) != RNA_property_is_set(ptr_b, prop_b)) {
+ return 1;
+ }
+ }
+
+ if (prop != NULL) {
+ /* Ensure we get real property data, be it an actual RNA property, or an IDProperty in disguise. */
+ prop_a = rna_ensure_property_realdata(&prop_a, ptr_a);
+ prop_b = rna_ensure_property_realdata(&prop_b, ptr_b);
+
+ if (ELEM(NULL, prop_a, prop_b)) {
+ return (prop_a == prop_b) ? 0 : 1;
+ }
+ }
+
+ /* Check if we are working with arrays. */
+ const bool is_array_a = RNA_property_array_check(prop_a);
+ const bool is_array_b = RNA_property_array_check(prop_b);
+
+ if (is_array_a != is_array_b) {
+ /* Should probably never happen actually... */
+ BLI_assert(0);
+ return is_array_a ? 1 : -1;
+ }
+
+ /* Get the length of the array to work with. */
+ const int len_a = RNA_property_array_length(ptr_a, prop_a);
+ const int len_b = RNA_property_array_length(ptr_b, prop_b);
+
+ if (len_a != len_b) {
+ /* Do not handle override in that case, we do not support insertion/deletion from arrays for now. */
+ return len_a > len_b ? 1 : -1;
+ }
+
+ if (is_array_a && len_a == 0) {
+ /* Empty arrays, will happen in some case with dynamic ones. */
+ return 0;
+ }
+
+ RNAPropOverrideDiff override_diff = NULL;
+ /* Special case for IDProps, we use default callback then. */
+ if (prop_a->magic != RNA_MAGIC) {
+ override_diff = rna_property_override_diff_default;
+ if (prop_b->magic == RNA_MAGIC && prop_b->override_diff != override_diff) {
+ override_diff = NULL;
+ }
+ }
+ else if (prop_b->magic != RNA_MAGIC) {
+ override_diff = rna_property_override_diff_default;
+ if (prop_a->override_diff != override_diff) {
+ override_diff = NULL;
+ }
+ }
+ else if (prop_a->override_diff == prop_b->override_diff) {
+ override_diff = prop_a->override_diff;
+ }
+
+ if (override_diff == NULL) {
+#ifndef NDEBUG
+ printf("'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%d vs. %d).\n",
+ rna_path ? rna_path : (prop_a->magic != RNA_MAGIC ? ((IDProperty *)prop_a)->name : prop_a->identifier),
+ prop_a->magic == RNA_MAGIC, prop_b->magic == RNA_MAGIC);
+#endif
+ BLI_assert(0);
+ return 1;
+ }
+
+ bool override_changed = false;
+ int diff_flags = flags;
+ if (!RNA_property_overridable_get(ptr_a, prop_a)) {
+ diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE;
+ }
+ const int diff = override_diff(
+ ptr_a, ptr_b, prop_a, prop_b, len_a, len_b,
+ mode, override, rna_path, diff_flags, &override_changed);
+ if (override_changed && r_report_flags) {
+ *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_CREATED;
+ }
+
+ return diff;
+}
+
+/* Modify local data-block to make it ready for override application (only needed for diff operations, where we use
+ * the local data-block's data as second operand). */
+static bool rna_property_override_operation_store(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage,
+ PropertyRNA *prop_local, PropertyRNA *prop_reference, PropertyRNA *prop_storage,
+ IDOverrideStaticProperty *op)
+{
+ int len_local, len_reference, len_storage = 0;
+ bool changed = false;
+
+ if (ptr_storage == NULL) {
+ return changed;
+ }
+
+ /* get the length of the array to work with */
+ len_local = RNA_property_array_length(ptr_local, prop_local);
+ len_reference = RNA_property_array_length(ptr_reference, prop_reference);
+ if (prop_storage) {
+ len_storage = RNA_property_array_length(ptr_storage, prop_storage);
+ }
+
+ if (len_local != len_reference || len_local != len_storage) {
+ /* Do not handle override in that case, we do not support insertion/deletion from arrays for now. */
+ return changed;
+ }
+
+ BLI_assert(prop_local->override_store == prop_reference->override_store &&
+ (!ptr_storage || prop_local->override_store == prop_storage->override_store) &&
+ prop_local->override_store != NULL);
+
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ /* Only needed for diff operations. */
+ if (!ELEM(opop->operation, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY)) {
+ continue;
+ }
+
+ if (prop_local->override_store(
+ ptr_local, ptr_reference, ptr_storage, prop_local, prop_reference, prop_storage,
+ len_local, len_reference, len_storage, opop))
+ {
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+static bool rna_property_override_operation_apply(
+ PointerRNA *ptr_local, PointerRNA *ptr_override, PointerRNA *ptr_storage,
+ PropertyRNA *prop_local, PropertyRNA *prop_override, PropertyRNA *prop_storage,
+ IDOverrideStaticPropertyOperation *opop)
+{
+ int len_local, len_reference, len_storage = 0;
+
+ const short override_op = opop->operation;
+
+ if (override_op == IDOVERRIDESTATIC_OP_NOOP) {
+ return true;
+ }
+
+ if (ELEM(override_op, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY) && !ptr_storage) {
+ /* We cannot apply 'diff' override operations without some refference storage.
+ * This should typically only happen at read time of .blend file... */
+ return false;
+ }
+
+ if (ELEM(override_op, IDOVERRIDESTATIC_OP_ADD, IDOVERRIDESTATIC_OP_SUBTRACT, IDOVERRIDESTATIC_OP_MULTIPLY) && !prop_storage) {
+ /* We cannot apply 'diff' override operations without some refference storage.
+ * This should typically only happen at read time of .blend file... */
+ return false;
+ }
+
+ RNAPropOverrideApply override_apply = NULL;
+ /* Special case for IDProps, we use default callback then. */
+ if (prop_local->magic != RNA_MAGIC) {
+ override_apply = rna_property_override_apply_default;
+ if (prop_override->magic == RNA_MAGIC && prop_override->override_apply != override_apply) {
+ override_apply = NULL;
+ }
+ }
+ else if (prop_override->magic != RNA_MAGIC) {
+ override_apply = rna_property_override_apply_default;
+ if (prop_local->override_apply != override_apply) {
+ override_apply = NULL;
+ }
+ }
+ else if (prop_local->override_apply == prop_override->override_apply) {
+ override_apply = prop_local->override_apply;
+ }
+
+ if (ptr_storage && prop_storage->magic == RNA_MAGIC && prop_storage->override_apply != override_apply) {
+ override_apply = NULL;
+ }
+
+ if (override_apply == NULL) {
+#ifndef NDEBUG
+ printf("'%s' gives unmatching or NULL RNA copy callbacks, should not happen (%d vs. %d).\n",
+ prop_local->magic != RNA_MAGIC ? ((IDProperty *)prop_local)->name : prop_local->identifier,
+ prop_local->magic == RNA_MAGIC, prop_override->magic == RNA_MAGIC);
+#endif
+ BLI_assert(0);
+ return false;
}
/* get the length of the array to work with */
- len = RNA_property_array_length(a, prop);
- fromlen = RNA_property_array_length(b, prop);
+ len_local = RNA_property_array_length(ptr_local, prop_local);
+ len_reference = RNA_property_array_length(ptr_override, prop_override);
+ if (ptr_storage) {
+ len_storage = RNA_property_array_length(ptr_storage, prop_storage);
+ }
- if (len != fromlen)
+ if (len_local != len_reference || (ptr_storage && len_local != len_storage)) {
+ /* Do not handle override in that case, we do not support insertion/deletion from arrays for now. */
return false;
+ }
/* get and set the default values as appropriate for the various types */
- switch (RNA_property_type(prop)) {
- case PROP_BOOLEAN:
- {
- if (len) {
- int fixed_a[16], fixed_b[16];
- int *array_a, *array_b;
- bool equals;
+ return override_apply(
+ ptr_local, ptr_override, ptr_storage,
+ prop_local, prop_override, prop_storage,
+ len_local, len_reference, len_storage,
+ opop);
+}
+
+/**
+ * Check whether reference and local overriden data match (are the same),
+ * with respect to given restrictive sets of properties.
+ * If requested, will generate needed new property overrides, and/or restore values from reference.
+ *
+ * \param r_report_flags If given, will be set with flags matching actions taken by the function on \a ptr_local.
+ *
+ * \return True if _resulting_ \a ptr_local does match \a ptr_reference.
+ */
+bool RNA_struct_override_matches(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, const char *root_path,
+ IDOverrideStatic *override, const eRNAOverrideMatch flags,
+ eRNAOverrideMatchResult *r_report_flags)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
+ bool matching = true;
+
+ BLI_assert(ptr_local->type == ptr_reference->type);
+ BLI_assert(ptr_local->id.data && ptr_reference->id.data);
+
+ const bool ignore_non_overridable = (flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE) != 0;
+ const bool ignore_overridden = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0;
+ const bool do_create = (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0;
+ const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_RESTORE) != 0;
+
+//#define DEBUG_OVERRIDE_TIMEIT
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ static float _sum_time_global = 0.0f;
+ static float _num_time_global = 0.0f;
+ double _timeit_time_global;
+ static float _sum_time_diffing = 0.0f;
+ static float _delta_time_diffing = 0.0f;
+ static int _num_delta_time_diffing = 0.0f;
+ static float _num_time_diffing = 0.0f;
+ double _timeit_time_diffing;
+
+ if (!root_path) {
+ _delta_time_diffing = 0.0f;
+ _num_delta_time_diffing = 0;
+ _timeit_time_global = PIL_check_seconds_timer();
+ }
+#endif
+
+ iterprop = RNA_struct_iterator_property(ptr_local->type);
+
+ for (RNA_property_collection_begin(ptr_local, iterprop, &iter); iter.valid; RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop_local = iter.ptr.data;
+ PropertyRNA *prop_reference = iter.ptr.data;
- array_a = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_b;
+ /* Ensure we get real property data, be it an actual RNA property, or an IDProperty in disguise. */
+ prop_local = rna_ensure_property_realdata(&prop_local, ptr_local);
+ prop_reference = rna_ensure_property_realdata(&prop_reference, ptr_reference);
- RNA_property_boolean_get_array(a, prop, array_a);
- RNA_property_boolean_get_array(b, prop, array_b);
+ if (ELEM(NULL, prop_local, prop_reference)) {
+ continue;
+ }
- equals = memcmp(array_a, array_b, sizeof(int) * len) == 0;
+ if (ignore_non_overridable && !RNA_property_overridable_get(ptr_local, prop_local)) {
+ continue;
+ }
- if (array_a != fixed_a) MEM_freeN(array_a);
- if (array_b != fixed_b) MEM_freeN(array_b);
+#if 0 /* This actually makes things slower, since it has to check for animation paths etc! */
+ if (RNA_property_animated(ptr_local, prop_local)) {
+ /* We cannot do anything here really, animation is some kind of dynamic overrides that has
+ * precedence over static one... */
+ continue;
+ }
+#endif
- return equals;
+#define RNA_PATH_BUFFSIZE 8192
+#define RNA_PATH_PRINTF(_str, ...) \
+ if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, \
+ (_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) \
+ { rna_path = BLI_sprintfN((_str), __VA_ARGS__); }(void)0
+#define RNA_PATH_FREE \
+ if (rna_path != rna_path_buffer) MEM_freeN(rna_path)
+
+ char rna_path_buffer[RNA_PATH_BUFFSIZE];
+ char *rna_path = rna_path_buffer;
+
+ /* XXX TODO this will have to be refined to handle collections insertions, and array items */
+ if (root_path) {
+ /* Inlined building, much much more efficient. */
+ if (prop_local->magic == RNA_MAGIC) {
+ RNA_PATH_PRINTF("%s.%s", root_path, RNA_property_identifier(prop_local));
}
else {
- int value = RNA_property_boolean_get(a, prop);
- return value == RNA_property_boolean_get(b, prop);
+ RNA_PATH_PRINTF("%s[\"%s\"]", root_path, RNA_property_identifier(prop_local));
}
}
+ else {
+ /* This is rather slow, but is not much called, so not really worth optimizing. */
+ rna_path = RNA_path_from_ID_to_property(ptr_local, prop_local);
+ }
+ if (rna_path == NULL) {
+ continue;
+ }
- case PROP_INT:
- {
- if (len) {
- int fixed_a[16], fixed_b[16];
- int *array_a, *array_b;
- bool equals;
+// printf("Override Checking %s\n", rna_path);
- array_a = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_mallocN(sizeof(int) * len, "RNA equals") : fixed_b;
+ if (ignore_overridden && BKE_override_static_property_find(override, rna_path) != NULL) {
+ RNA_PATH_FREE;
+ continue;
+ }
- RNA_property_int_get_array(a, prop, array_a);
- RNA_property_int_get_array(b, prop, array_b);
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ _timeit_time_diffing = PIL_check_seconds_timer();
+ }
+#endif
- equals = memcmp(array_a, array_b, sizeof(int) * len) == 0;
+ eRNAOverrideMatchResult report_flags = 0;
+ const int diff = rna_property_override_diff(
+ ptr_local, ptr_reference, NULL, prop_local, prop_reference, rna_path,
+ RNA_EQ_STRICT, override, flags, &report_flags);
- if (array_a != fixed_a) MEM_freeN(array_a);
- if (array_b != fixed_b) MEM_freeN(array_b);
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_diffing);
+ _delta_time_diffing += _delta_time;
+ _num_delta_time_diffing++;
+ }
+#endif
- return equals;
+ matching = matching && diff == 0;
+ if (r_report_flags) {
+ *r_report_flags |= report_flags;
+ }
+
+ if (diff != 0) {
+ /* XXX TODO: refine this for per-item overriding of arrays... */
+ IDOverrideStaticProperty *op = BKE_override_static_property_find(override, rna_path);
+ IDOverrideStaticPropertyOperation *opop = op ? op->operations.first : NULL;
+
+ if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) {
+ /* We are allowed to restore to reference's values. */
+ if (ELEM(NULL, op, opop) || opop->operation == IDOVERRIDESTATIC_OP_NOOP) {
+ /* We should restore that property to its reference value */
+ if (RNA_property_editable(ptr_local, prop_local)) {
+ IDOverrideStaticPropertyOperation opop_tmp = {
+ .operation = IDOVERRIDESTATIC_OP_REPLACE,
+ .subitem_reference_index = -1,
+ .subitem_local_index = -1
+ };
+ rna_property_override_operation_apply(ptr_local, ptr_reference, NULL,
+ prop_local, prop_reference, NULL, &opop_tmp);
+ if (r_report_flags) {
+ *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED;
+ }
+ }
+ else {
+ /* Too noisy for now, this triggers on runtime props like transform matrices etc. */
+ /* BLI_assert(!"We have differences between reference and overriding data on non-editable property."); */
+ matching = false;
+ }
+ }
}
- else {
- int value = RNA_property_int_get(a, prop);
- return value == RNA_property_int_get(b, prop);
+ else if ((report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0 && ELEM(NULL, op, opop)) {
+ /* This property is not overridden, and differs from reference, so we have no match. */
+ matching = false;
+ if (!(do_create || do_restore)) {
+ /* Since we have no 'changing' action allowed, we can break here. */
+ MEM_SAFE_FREE(rna_path);
+ break;
+ }
}
}
- case PROP_FLOAT:
- {
- if (len) {
- float fixed_a[16], fixed_b[16];
- float *array_a, *array_b;
- bool equals;
+ RNA_PATH_FREE;
- array_a = (len > 16) ? MEM_mallocN(sizeof(float) * len, "RNA equals") : fixed_a;
- array_b = (len > 16) ? MEM_mallocN(sizeof(float) * len, "RNA equals") : fixed_b;
+#undef RNA_PATH_BUFFSIZE
+#undef RNA_PATH_PRINTF
+#undef RNA_PATH_FREE
+ }
+ RNA_property_collection_end(&iter);
- RNA_property_float_get_array(a, prop, array_a);
- RNA_property_float_get_array(b, prop, array_b);
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_global);
+ _sum_time_global += _delta_time;
+ _num_time_global++;
+ _sum_time_diffing += _delta_time_diffing;
+ _num_time_diffing++;
+ printf("ID: %s\n", ((ID *)ptr_local->id.data)->name);
+ printf("time end (%s): %.6f\n", __func__, _delta_time);
+ printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n", __func__,
+ (_sum_time_global / _num_time_global), _sum_time_global, (int)_num_time_global);
+ printf("diffing time end (%s): %.6f (in %d runs)\n", __func__, _delta_time_diffing, _num_delta_time_diffing);
+ printf("diffing time averaged (%s): %.6f (total: %.6f, in %d runs)\n", __func__,
+ (_sum_time_diffing / _num_time_diffing), _sum_time_diffing, (int)_num_time_diffing);
+ }
+#endif
- equals = memcmp(array_a, array_b, sizeof(float) * len) == 0;
+ return matching;
+}
- if (array_a != fixed_a) MEM_freeN(array_a);
- if (array_b != fixed_b) MEM_freeN(array_b);
- return equals;
+/** Store needed second operands into \a storage data-block for differential override operations. */
+bool RNA_struct_override_store(
+ PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, IDOverrideStatic *override)
+{
+ bool changed = false;
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(RNA_struct_override_store);
+#endif
+ for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) {
+ /* Simplified for now! */
+ PointerRNA data_reference, data_local;
+ PropertyRNA *prop_reference, *prop_local;
+
+ if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) &&
+ RNA_path_resolve_property(ptr_reference, op->rna_path, &data_reference, &prop_reference))
+ {
+ PointerRNA data_storage;
+ PropertyRNA *prop_storage = NULL;
+
+ /* It is totally OK if this does not success, only a subset of override operations actually need storage. */
+ if (ptr_storage && (ptr_storage->id.data != NULL)) {
+ RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage);
}
- else {
- float value = RNA_property_float_get(a, prop);
- return value == RNA_property_float_get(b, prop);
+
+ if (rna_property_override_operation_store(&data_local, &data_reference, &data_storage,
+ prop_reference, prop_local, prop_storage, op))
+ {
+ changed = true;
}
}
+ }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(RNA_struct_override_store);
+#endif
- case PROP_ENUM:
- {
- int value = RNA_property_enum_get(a, prop);
- return value == RNA_property_enum_get(b, prop);
- }
+ return changed;
+}
- case PROP_STRING:
+static void rna_property_override_apply_ex(
+ PointerRNA *ptr_local, PointerRNA *ptr_override, PointerRNA *ptr_storage,
+ PropertyRNA *prop_local, PropertyRNA *prop_override, PropertyRNA *prop_storage,
+ IDOverrideStaticProperty *op, const bool do_insert)
+{
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ if (!do_insert != !ELEM(opop->operation, IDOVERRIDESTATIC_OP_INSERT_AFTER, IDOVERRIDESTATIC_OP_INSERT_BEFORE)) {
+ if (!do_insert) {
+ printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path);
+ }
+ continue;
+ }
+ if (!rna_property_override_operation_apply(ptr_local, ptr_override, ptr_storage,
+ prop_local, prop_override, prop_storage, opop))
{
- char fixed_a[128], fixed_b[128];
- int len_a, len_b;
- char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a);
- char *value_b = RNA_property_string_get_alloc(b, prop, fixed_b, sizeof(fixed_b), &len_b);
- bool equals = STREQ(value_a, value_b);
+ /* TODO No assert here, would be much much better to just report as warning,
+ * failing override applications will probably be fairly common! */
+ BLI_assert(0);
+ }
+ }
+}
- if (value_a != fixed_a) MEM_freeN(value_a);
- if (value_b != fixed_b) MEM_freeN(value_b);
+/** Apply given \a override operations on \a ptr_local, using \a ptr_override
+ * (and \a ptr_storage form differential ops) as source. */
+void RNA_struct_override_apply(
+ PointerRNA *ptr_local, PointerRNA *ptr_override, PointerRNA *ptr_storage, IDOverrideStatic *override)
+{
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(RNA_struct_override_apply);
+#endif
+ /* Note: Applying insert operations in a separate pass is mandatory.
+ * We could optimize this later, but for now, as inneficient as it is, don't think this is a critical point.
+ */
+ bool do_insert = false;
+ for (int i = 0; i < 2; i++, do_insert = true) {
+ for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) {
+ /* Simplified for now! */
+ PointerRNA data_override, data_local;
+ PropertyRNA *prop_override, *prop_local;
+
+ if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) &&
+ RNA_path_resolve_property(ptr_override, op->rna_path, &data_override, &prop_override))
+ {
+ PointerRNA data_storage;
+ PropertyRNA *prop_storage = NULL;
- return equals;
- }
+ /* It is totally OK if this does not success, only a subset of override operations actually need storage. */
+ if (ptr_storage && (ptr_storage->id.data != NULL)) {
+ RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage);
+ }
- case PROP_POINTER:
- {
- if (!STREQ(RNA_property_identifier(prop), "rna_type")) {
- PointerRNA propptr_a = RNA_property_pointer_get(a, prop);
- PointerRNA propptr_b = RNA_property_pointer_get(b, prop);
- return RNA_struct_equals(&propptr_a, &propptr_b, mode);
+ rna_property_override_apply_ex(
+ &data_local, &data_override, prop_storage ? &data_storage : NULL,
+ prop_local, prop_override, prop_storage, op, do_insert);
}
- break;
+#ifndef NDEBUG
+ else {
+ printf("Failed to apply static override operation to '%s.%s' (could not resolve some properties)\n",
+ ((ID *)ptr_override->id.data)->name, op->rna_path);
+ }
+#endif
}
+ }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(RNA_struct_override_apply);
+#endif
+}
- default:
- break;
+IDOverrideStaticProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop)
+{
+ ID *id = ptr->id.data;
+
+ if (!id || !id->override_static) {
+ return NULL;
}
- return true;
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (rna_path) {
+ IDOverrideStaticProperty *op = BKE_override_static_property_find(id->override_static, rna_path);
+ MEM_freeN(rna_path);
+ return op;
+ }
+ return NULL;
}
-bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNAEqualsMode mode)
+IDOverrideStaticProperty *RNA_property_override_property_get(PointerRNA *ptr, PropertyRNA *prop, bool *r_created)
{
- CollectionPropertyIterator iter;
-// CollectionPropertyRNA *citerprop; /* UNUSED */
- PropertyRNA *iterprop;
- bool equals = true;
+ ID *id = ptr->id.data;
- if (a == NULL && b == NULL)
- return true;
- else if (a == NULL || b == NULL)
- return false;
- else if (a->type != b->type)
- return false;
+ if (!id || !id->override_static) {
+ return NULL;
+ }
+
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (rna_path) {
+ IDOverrideStaticProperty *op = BKE_override_static_property_get(id->override_static, rna_path, r_created);
+ MEM_freeN(rna_path);
+ return op;
+ }
+ return NULL;
+}
- iterprop = RNA_struct_iterator_property(a->type);
-// citerprop = (CollectionPropertyRNA *)rna_ensure_property(iterprop); /* UNUSED */
+IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_find(
+ PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict)
+{
+ IDOverrideStaticProperty *op = RNA_property_override_property_find(ptr, prop);
- RNA_property_collection_begin(a, iterprop, &iter);
- for (; iter.valid; RNA_property_collection_next(&iter)) {
- PropertyRNA *prop = iter.ptr.data;
+ if (!op) {
+ return NULL;
+ }
- if (!RNA_property_equals(a, b, prop, mode)) {
- equals = false;
- break;
+ return BKE_override_static_property_operation_find(op, NULL, NULL, index, index, strict, r_strict);
+}
+
+IDOverrideStaticPropertyOperation *RNA_property_override_property_operation_get(
+ PointerRNA *ptr, PropertyRNA *prop, const short operation, const int index,
+ const bool strict, bool *r_strict, bool *r_created)
+{
+ IDOverrideStaticProperty *op = RNA_property_override_property_get(ptr, prop, NULL);
+
+ if (!op) {
+ return NULL;
+ }
+
+ return BKE_override_static_property_operation_get(op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
+}
+
+eRNAOverrideStatus RNA_property_static_override_status(PointerRNA *ptr, PropertyRNA *prop, const int index)
+{
+ int override_status = 0;
+
+ if (!ptr || !prop || !ptr->id.data || !((ID *)ptr->id.data)->override_static) {
+ return override_status;
+ }
+
+ if (RNA_property_overridable_get(ptr, prop) && RNA_property_editable_flag(ptr, prop)) {
+ override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE;
+ }
+
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_find(ptr, prop, index, false, NULL);
+ if (opop != NULL) {
+ override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN;
+ if (opop->flag & IDOVERRIDESTATIC_FLAG_MANDATORY) {
+ override_status |= RNA_OVERRIDE_STATUS_MANDATORY;
+ }
+ if (opop->flag & IDOVERRIDESTATIC_FLAG_LOCKED) {
+ override_status |= RNA_OVERRIDE_STATUS_LOCKED;
}
}
- RNA_property_collection_end(&iter);
- return equals;
+ return override_status;
}
+
bool RNA_path_resolved_create(
PointerRNA *ptr, struct PropertyRNA *prop,
const int prop_index,
@@ -7321,3 +7876,22 @@ bool RNA_path_resolved_create(
return false;
}
}
+
+static char rna_struct_state_owner[64];
+void RNA_struct_state_owner_set(const char *name)
+{
+ if (name) {
+ BLI_strncpy(rna_struct_state_owner, name, sizeof(rna_struct_state_owner));
+ }
+ else {
+ rna_struct_state_owner[0] = '\0';
+ }
+}
+
+const char *RNA_struct_state_owner_get(void)
+{
+ if (rna_struct_state_owner[0]) {
+ return rna_struct_state_owner;
+ }
+ return NULL;
+}