diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2019-08-22 16:31:07 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2019-08-22 16:33:44 +0300 |
commit | 8965a81271661d017c8dea93446c75677ba2f7eb (patch) | |
tree | 1d5e0c58967ee0efe9e9a3a199fbadb6974846b0 /source/blender/makesrna/intern/rna_access.c | |
parent | 662d94e020f36e75b9c6b4a258f31c1625573ee8 (diff) |
Cleanup: Split some code out of rna_access.c
That file was getting out of control, now comparison/override RNA code is
in `rna_access_compare_override.c`. 1K lines of code for now, but that
area is likely to grow more in the future...
Note that we can probably split more out of `rna_access.c`, but for now
that will do.
Diffstat (limited to 'source/blender/makesrna/intern/rna_access.c')
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 1067 |
1 files changed, 3 insertions, 1064 deletions
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 7b7af5c12db..c4b0e43fd70 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -37,10 +37,6 @@ #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" @@ -49,7 +45,6 @@ #include "BKE_idcode.h" #include "BKE_idprop.h" #include "BKE_fcurve.h" -#include "BKE_library_override.h" #include "BKE_main.h" #include "BKE_report.h" @@ -67,6 +62,7 @@ #include "WM_types.h" #include "rna_internal.h" +#include "rna_access_internal.h" const PointerRNA PointerRNA_NULL = {{NULL}}; @@ -249,7 +245,7 @@ void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr) /* ID Properties */ -static void rna_idproperty_touch(IDProperty *idprop) +void rna_idproperty_touch(IDProperty *idprop) { /* so the property is seen as 'set' by rna */ idprop->flag &= ~IDP_FLAG_GHOST; @@ -619,7 +615,7 @@ PropertyRNA *rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr) return rna_idproperty_check_ex(prop, ptr, true); } -static PropertyRNA *rna_ensure_property(PropertyRNA *prop) +PropertyRNA *rna_ensure_property(PropertyRNA *prop) { /* the quick version if we don't need the idproperty */ @@ -1171,11 +1167,6 @@ 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 @@ -2194,77 +2185,6 @@ 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_editable_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_OVERRIDE_LIBRARY_LOCAL) { - return true; - } - } - else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) { - ModifierData *mod = ptr->data; - if (mod->flag & eModifierFlag_OverrideLibrary_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_LIBRARY); - } - 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_LIBRARY); - } -} - -/* Should only be used for custom properties */ -bool RNA_property_overridable_library_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_LIBRARY) : - (idprop->flag & ~IDP_FLAG_OVERRIDABLE_LIBRARY); - 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_library == NULL) { - return false; - } - - return (BKE_override_library_property_find(id->override_library, 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) @@ -8115,59 +8035,6 @@ bool RNA_property_assign_default(PointerRNA *ptr, PropertyRNA *prop) } } -static bool rna_property_override_operation_apply(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_override, - PointerRNA *ptr_storage, - PropertyRNA *prop_local, - PropertyRNA *prop_override, - PropertyRNA *prop_storage, - PointerRNA *ptr_item_local, - PointerRNA *ptr_item_override, - PointerRNA *ptr_item_storage, - IDOverrideLibraryPropertyOperation *opop); - -bool RNA_property_copy( - Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index) -{ - if (!RNA_property_editable(ptr, prop)) { - return false; - } - - PropertyRNA *prop_dst = prop; - PropertyRNA *prop_src = prop; - - /* 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); - - /* 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; - } - - if (ELEM(NULL, prop_dst, prop_src)) { - return false; - } - - IDOverrideLibraryPropertyOperation opop = { - .operation = IDOVERRIDE_LIBRARY_OP_REPLACE, - .subitem_reference_index = index, - .subitem_local_index = index, - }; - return rna_property_override_operation_apply( - bmain, ptr, fromptr, NULL, prop_dst, prop_src, NULL, NULL, NULL, NULL, &opop); -} - /* use RNA_warning macro which includes __func__ suffix */ void _RNA_warning(const char *format, ...) { @@ -8190,934 +8057,6 @@ void _RNA_warning(const char *format, ...) #endif } -static int rna_property_override_diff(Main *bmain, - PointerRNA *ptr_a, - PointerRNA *ptr_b, - PropertyRNA *prop, - PropertyRNA *prop_a, - PropertyRNA *prop_b, - const char *rna_path, - eRNACompareMode mode, - IDOverrideLibrary *override, - const int flags, - eRNAOverrideMatchResult *r_report_flags); - -bool RNA_property_equals( - Main *bmain, 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( - bmain, ptr_a, ptr_b, prop, NULL, NULL, NULL, mode, NULL, 0, NULL) == 0); -} - -bool RNA_struct_equals(Main *bmain, 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(bmain, 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 expected to be an 'un-resolved' one, - * while the two later 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(Main *bmain, - PointerRNA *ptr_a, - PointerRNA *ptr_b, - PropertyRNA *prop, - PropertyRNA *prop_a, - PropertyRNA *prop_b, - const char *rna_path, - eRNACompareMode mode, - IDOverrideLibrary *override, - const int flags, - eRNAOverrideMatchResult *r_report_flags) -{ - 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(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(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(bmain, - 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(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_reference, - PointerRNA *ptr_storage, - PropertyRNA *prop_local, - PropertyRNA *prop_reference, - PropertyRNA *prop_storage, - IDOverrideLibraryProperty *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 (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { - /* Only needed for diff operations. */ - if (!ELEM(opop->operation, - IDOVERRIDE_LIBRARY_OP_ADD, - IDOVERRIDE_LIBRARY_OP_SUBTRACT, - IDOVERRIDE_LIBRARY_OP_MULTIPLY)) { - continue; - } - - if (prop_local->override_store(bmain, - 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(Main *bmain, - PointerRNA *ptr_dst, - PointerRNA *ptr_src, - PointerRNA *ptr_storage, - PropertyRNA *prop_dst, - PropertyRNA *prop_src, - PropertyRNA *prop_storage, - PointerRNA *ptr_item_dst, - PointerRNA *ptr_item_src, - PointerRNA *ptr_item_storage, - IDOverrideLibraryPropertyOperation *opop) -{ - int len_dst, len_src, len_storage = 0; - - const short override_op = opop->operation; - - if (override_op == IDOVERRIDE_LIBRARY_OP_NOOP) { - return true; - } - - if (ELEM(override_op, - IDOVERRIDE_LIBRARY_OP_ADD, - IDOVERRIDE_LIBRARY_OP_SUBTRACT, - IDOVERRIDE_LIBRARY_OP_MULTIPLY) && - !ptr_storage) { - /* We cannot apply 'diff' override operations without some reference storage. - * This should typically only happen at read time of .blend file... */ - return false; - } - - if (ELEM(override_op, - IDOVERRIDE_LIBRARY_OP_ADD, - IDOVERRIDE_LIBRARY_OP_SUBTRACT, - IDOVERRIDE_LIBRARY_OP_MULTIPLY) && - !prop_storage) { - /* We cannot apply 'diff' override operations without some reference 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_dst->magic != RNA_MAGIC) { - override_apply = rna_property_override_apply_default; - if (prop_src->magic == RNA_MAGIC && prop_src->override_apply != override_apply) { - override_apply = NULL; - } - } - else if (prop_src->magic != RNA_MAGIC) { - override_apply = rna_property_override_apply_default; - if (prop_dst->override_apply != override_apply) { - override_apply = NULL; - } - } - else if (prop_dst->override_apply == prop_src->override_apply) { - override_apply = prop_dst->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_dst->magic != RNA_MAGIC ? ((IDProperty *)prop_dst)->name : prop_dst->identifier, - prop_dst->magic == RNA_MAGIC, - prop_src->magic == RNA_MAGIC); -#endif - BLI_assert(0); - return false; - } - - /* get the length of the array to work with */ - len_dst = RNA_property_array_length(ptr_dst, prop_dst); - len_src = RNA_property_array_length(ptr_src, prop_src); - if (ptr_storage) { - len_storage = RNA_property_array_length(ptr_storage, prop_storage); - } - - if (len_dst != len_src || (ptr_storage && len_dst != 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 */ - return override_apply(bmain, - ptr_dst, - ptr_src, - ptr_storage, - prop_dst, - prop_src, - prop_storage, - len_dst, - len_src, - len_storage, - ptr_item_dst, - ptr_item_src, - ptr_item_storage, - opop); -} - -/** - * Check whether reference and local overridden 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(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_reference, - const char *root_path, - IDOverrideLibrary *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; - - /* 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); - - if (ELEM(NULL, prop_local, prop_reference)) { - continue; - } - - if (ignore_non_overridable && !RNA_property_overridable_get(ptr_local, prop_local)) { - continue; - } - -#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 - -#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 { - 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; - } - - // printf("Override Checking %s\n", rna_path); - - if (ignore_overridden && BKE_override_library_property_find(override, rna_path) != NULL) { - RNA_PATH_FREE; - continue; - } - -#ifdef DEBUG_OVERRIDE_TIMEIT - if (!root_path) { - _timeit_time_diffing = PIL_check_seconds_timer(); - } -#endif - - eRNAOverrideMatchResult report_flags = 0; - const int diff = rna_property_override_diff(bmain, - ptr_local, - ptr_reference, - NULL, - prop_local, - prop_reference, - rna_path, - RNA_EQ_STRICT, - override, - flags, - &report_flags); - -#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 - - 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... */ - IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path); - IDOverrideLibraryPropertyOperation *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 == IDOVERRIDE_LIBRARY_OP_NOOP) { - /* We should restore that property to its reference value */ - if (RNA_property_editable(ptr_local, prop_local)) { - IDOverrideLibraryPropertyOperation opop_tmp = { - .operation = IDOVERRIDE_LIBRARY_OP_REPLACE, - .subitem_reference_index = -1, - .subitem_local_index = -1, - }; - rna_property_override_operation_apply(bmain, - ptr_local, - ptr_reference, - NULL, - prop_local, - prop_reference, - NULL, - NULL, - NULL, - 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. */ -#if 0 - BLI_assert(!"We have differences between reference and " - "overriding data on non-editable property."); -#endif - matching = false; - } - } - } - 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; - } - } - } - - RNA_PATH_FREE; - -#undef RNA_PATH_BUFFSIZE -#undef RNA_PATH_PRINTF -#undef RNA_PATH_FREE - } - RNA_property_collection_end(&iter); - -#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 - - return matching; -} - -/** Store needed second operands into \a storage data-block - * for differential override operations. */ -bool RNA_struct_override_store(Main *bmain, - PointerRNA *ptr_local, - PointerRNA *ptr_reference, - PointerRNA *ptr_storage, - IDOverrideLibrary *override) -{ - bool changed = false; - -#ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_START_AVERAGED(RNA_struct_override_store); -#endif - for (IDOverrideLibraryProperty *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); - } - - if (rna_property_override_operation_store(bmain, - &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 - - return changed; -} - -static void rna_property_override_apply_ex(Main *bmain, - PointerRNA *ptr_dst, - PointerRNA *ptr_src, - PointerRNA *ptr_storage, - PropertyRNA *prop_dst, - PropertyRNA *prop_src, - PropertyRNA *prop_storage, - PointerRNA *ptr_item_dst, - PointerRNA *ptr_item_src, - PointerRNA *ptr_item_storage, - IDOverrideLibraryProperty *op, - const bool do_insert) -{ - for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { - if (!do_insert != !ELEM(opop->operation, - IDOVERRIDE_LIBRARY_OP_INSERT_AFTER, - IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) { - if (!do_insert) { - printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path); - } - continue; - } - - /* Note: will have to think about putting that logic into its own function maybe? - * Would be nice to have it in a single place... - * Note that here, src is the local saved ID, and dst is a copy of the linked ID (since we use - * local ID as storage to apply local changes on top of a clean copy of the linked data). */ - PointerRNA private_ptr_item_dst, private_ptr_item_src, private_ptr_item_storage; - if (opop->subitem_local_name != NULL || opop->subitem_reference_name != NULL || - opop->subitem_local_index != -1 || opop->subitem_reference_index != -1) { - RNA_POINTER_INVALIDATE(&private_ptr_item_dst); - RNA_POINTER_INVALIDATE(&private_ptr_item_src); - RNA_POINTER_INVALIDATE(&private_ptr_item_storage); - if (opop->subitem_local_name != NULL) { - RNA_property_collection_lookup_string( - ptr_src, prop_src, opop->subitem_local_name, &private_ptr_item_src); - if (opop->subitem_reference_name != NULL) { - RNA_property_collection_lookup_string( - ptr_dst, prop_dst, opop->subitem_reference_name, &private_ptr_item_dst); - } - else { - RNA_property_collection_lookup_string( - ptr_dst, prop_dst, opop->subitem_local_name, &private_ptr_item_dst); - } - } - else if (opop->subitem_reference_name != NULL) { - RNA_property_collection_lookup_string( - ptr_src, prop_src, opop->subitem_reference_name, &private_ptr_item_src); - RNA_property_collection_lookup_string( - ptr_dst, prop_dst, opop->subitem_reference_name, &private_ptr_item_dst); - } - else if (opop->subitem_local_index != -1) { - RNA_property_collection_lookup_int( - ptr_src, prop_src, opop->subitem_local_index, &private_ptr_item_src); - if (opop->subitem_reference_index != -1) { - RNA_property_collection_lookup_int( - ptr_dst, prop_dst, opop->subitem_reference_index, &private_ptr_item_dst); - } - else { - RNA_property_collection_lookup_int( - ptr_dst, prop_dst, opop->subitem_local_index, &private_ptr_item_dst); - } - } - else if (opop->subitem_reference_index != -1) { - RNA_property_collection_lookup_int( - ptr_src, prop_src, opop->subitem_reference_index, &private_ptr_item_src); - RNA_property_collection_lookup_int( - ptr_dst, prop_dst, opop->subitem_reference_index, &private_ptr_item_dst); - } - if (prop_storage != NULL) { - if (opop->subitem_local_name != NULL) { - RNA_property_collection_lookup_string( - ptr_storage, prop_storage, opop->subitem_local_name, &private_ptr_item_storage); - } - else if (opop->subitem_reference_name != NULL) { - RNA_property_collection_lookup_string( - ptr_storage, prop_storage, opop->subitem_reference_name, &private_ptr_item_storage); - } - else if (opop->subitem_local_index != -1) { - RNA_property_collection_lookup_int( - ptr_storage, prop_storage, opop->subitem_local_index, &private_ptr_item_storage); - } - else if (opop->subitem_reference_index != -1) { - RNA_property_collection_lookup_int( - ptr_storage, prop_storage, opop->subitem_reference_index, &private_ptr_item_storage); - } - } - ptr_item_dst = &private_ptr_item_dst; - ptr_item_src = &private_ptr_item_src; - ptr_item_storage = &private_ptr_item_storage; - } - - if (!rna_property_override_operation_apply(bmain, - ptr_dst, - ptr_src, - ptr_storage, - prop_dst, - prop_src, - prop_storage, - ptr_item_dst, - ptr_item_src, - ptr_item_storage, - opop)) { - /* 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); - } - } -} - -/** Apply given \a override operations on \a ptr_dst, using \a ptr_src - * (and \a ptr_storage for differential ops) as source. */ -void RNA_struct_override_apply(Main *bmain, - PointerRNA *ptr_dst, - PointerRNA *ptr_src, - PointerRNA *ptr_storage, - IDOverrideLibrary *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 inefficient 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 (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) { - /* Simplified for now! */ - PointerRNA data_src, data_dst; - PointerRNA data_item_src, data_item_dst; - PropertyRNA *prop_src, *prop_dst; - - if (RNA_path_resolve_property_and_item_pointer( - ptr_dst, op->rna_path, &data_dst, &prop_dst, &data_item_dst) && - RNA_path_resolve_property_and_item_pointer( - ptr_src, op->rna_path, &data_src, &prop_src, &data_item_src)) { - PointerRNA data_storage, data_item_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_and_item_pointer( - ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage); - } - - rna_property_override_apply_ex(bmain, - &data_dst, - &data_src, - prop_storage ? &data_storage : NULL, - prop_dst, - prop_src, - prop_storage, - &data_item_dst, - &data_item_src, - prop_storage ? &data_item_storage : NULL, - op, - do_insert); - } -#ifndef NDEBUG - else { - printf( - "Failed to apply library override operation to '%s.%s' " - "(could not resolve some properties, local: %d, override: %d)\n", - ((ID *)ptr_src->id.data)->name, - op->rna_path, - RNA_path_resolve_property(ptr_dst, op->rna_path, &data_dst, &prop_dst), - RNA_path_resolve_property(ptr_src, op->rna_path, &data_src, &prop_src)); - } -#endif - } - } -#ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_END_AVERAGED(RNA_struct_override_apply); -#endif -} - -IDOverrideLibraryProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop) -{ - ID *id = ptr->id.data; - - if (!id || !id->override_library) { - return NULL; - } - - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - if (rna_path) { - IDOverrideLibraryProperty *op = BKE_override_library_property_find(id->override_library, - rna_path); - MEM_freeN(rna_path); - return op; - } - return NULL; -} - -IDOverrideLibraryProperty *RNA_property_override_property_get(PointerRNA *ptr, - PropertyRNA *prop, - bool *r_created) -{ - ID *id = ptr->id.data; - - if (!id || !id->override_library) { - return NULL; - } - - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - if (rna_path) { - IDOverrideLibraryProperty *op = BKE_override_library_property_get( - id->override_library, rna_path, r_created); - MEM_freeN(rna_path); - return op; - } - return NULL; -} - -IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_find( - PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict) -{ - IDOverrideLibraryProperty *op = RNA_property_override_property_find(ptr, prop); - - if (!op) { - return NULL; - } - - return BKE_override_library_property_operation_find( - op, NULL, NULL, index, index, strict, r_strict); -} - -IDOverrideLibraryPropertyOperation *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) -{ - IDOverrideLibraryProperty *op = RNA_property_override_property_get(ptr, prop, NULL); - - if (!op) { - return NULL; - } - - return BKE_override_library_property_operation_get( - op, operation, NULL, NULL, index, index, strict, r_strict, r_created); -} - -eRNAOverrideStatus RNA_property_override_library_status(PointerRNA *ptr, - PropertyRNA *prop, - const int index) -{ - int override_status = 0; - - if (!BKE_override_library_is_enabled()) { - return override_status; - } - - if (!ptr || !prop || !ptr->id.data || !((ID *)ptr->id.data)->override_library) { - return override_status; - } - - if (RNA_property_overridable_get(ptr, prop) && RNA_property_editable_flag(ptr, prop)) { - override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE; - } - - IDOverrideLibraryPropertyOperation *opop = RNA_property_override_property_operation_find( - ptr, prop, index, false, NULL); - if (opop != NULL) { - override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN; - if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_MANDATORY) { - override_status |= RNA_OVERRIDE_STATUS_MANDATORY; - } - if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_LOCKED) { - override_status |= RNA_OVERRIDE_STATUS_LOCKED; - } - } - - return override_status; -} - bool RNA_path_resolved_create(PointerRNA *ptr, struct PropertyRNA *prop, const int prop_index, |