diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2017-12-18 12:13:43 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2017-12-18 12:13:43 +0300 |
commit | 7ab8c906865dddf2ef6164b6271e4469a3a95319 (patch) | |
tree | 7604626d0d6c56f6fcf5ca3233ec29bec4c623be | |
parent | 994648a6741087ae40227037ee87395aa18f5b18 (diff) |
Serious cleanup/refactor/fixing of new RNA comparison code.
Code also handling auto-generation of static overrides.
Aside from some naming consistency cleanup, this commit:
* Is the first step addressing the 'operator' issue with static
overrides, by implementing a first version of the 'restore from
reference' behavior.
* Fixes several issues that were discovered on the way in enhanced
RNA comparision code, like the 'zero-length dynamic array' case, or some
infinite looping caused by some non-ID pointers (that for some
mysterious reasons did not show up previously...).
* Factorizes a bit said RNA comparison code (auto-static override
generation and comparison/check were essentially doing the same thing).
-rw-r--r-- | source/blender/blenkernel/intern/library_override.c | 21 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 33 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 327 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_internal_types.h | 6 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_rna.c | 96 |
5 files changed, 289 insertions, 194 deletions
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c index 26aeca0564d..a65aea4c292 100644 --- a/source/blender/blenkernel/intern/library_override.c +++ b/source/blender/blenkernel/intern/library_override.c @@ -394,7 +394,10 @@ bool BKE_override_static_status_check_local(ID *local) RNA_id_pointer_create(local, &rnaptr_local); RNA_id_pointer_create(reference, &rnaptr_reference); - if (!RNA_struct_override_matches(&rnaptr_local, &rnaptr_reference, local->override_static, true, true)) { + if (!RNA_struct_override_matches( + &rnaptr_local, &rnaptr_reference, NULL, local->override_static, + RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE | RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN, NULL)) + { local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; return false; } @@ -438,7 +441,10 @@ bool BKE_override_static_status_check_reference(ID *local) RNA_id_pointer_create(local, &rnaptr_local); RNA_id_pointer_create(reference, &rnaptr_reference); - if (!RNA_struct_override_matches(&rnaptr_local, &rnaptr_reference, local->override_static, false, true)) { + if (!RNA_struct_override_matches( + &rnaptr_local, &rnaptr_reference, NULL, local->override_static, + RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN, NULL)) + { local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; return false; } @@ -469,8 +475,17 @@ bool BKE_override_static_operations_create(ID *local) RNA_id_pointer_create(local, &rnaptr_local); RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference); - ret = RNA_struct_auto_override(&rnaptr_local, &rnaptr_reference, local->override_static, NULL); + eRNAOverrideMatchResult report_flags = 0; + RNA_struct_override_matches( + &rnaptr_local, &rnaptr_reference, NULL, local->override_static, + RNA_OVERRIDE_COMPARE_CREATE | RNA_OVERRIDE_COMPARE_RESTORE, &report_flags); + if (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) { + ret = true; + } #ifndef NDEBUG + if (report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORED) { + printf("We did restore some properties of %s from its reference.\n", local->name); + } if (ret) { printf("We did generate static override rules for %s\n", local->name); } diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8d66f59dde5..415e018a3c1 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -1251,14 +1251,35 @@ typedef enum eRNACompareMode { RNA_EQ_COMPARE, } eRNACompareMode; -bool RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop, eRNACompareMode mode); -bool RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b, eRNACompareMode mode); +bool RNA_property_equals(struct PointerRNA *ptr_a, struct PointerRNA *ptr_b, struct PropertyRNA *prop, eRNACompareMode mode); +bool RNA_struct_equals(struct PointerRNA *ptr_a, struct PointerRNA *ptr_b, eRNACompareMode mode); /* Override. */ +/* flags for RNA_struct_override_matches. */ +typedef enum eRNAOverrideMatch { + /* Do not compare properties that are not overridable. */ + RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE = 1 << 0, + /* Do not compare properties that are already overridden. */ + RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN = 1 << 1, + + /* Create new property override if needed and possible. */ + RNA_OVERRIDE_COMPARE_CREATE = 1 << 16, + /* Restore property's value(s) to reference ones if needed and possible. */ + RNA_OVERRIDE_COMPARE_RESTORE = 1 << 17, +} eRNAOverrideMatch; + +typedef enum eRNAOverrideMatchResult { + /* Some new property overrides were created to take into account differences between local and reference. */ + RNA_OVERRIDE_MATCH_RESULT_CREATED = 1 << 0, + /* Some properties were reset to reference values. */ + RNA_OVERRIDE_MATCH_RESULT_RESTORED = 1 << 1, +} eRNAOverrideMatchResult; + bool RNA_struct_override_matches( - struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, - struct IDOverrideStatic *override, const bool ignore_non_overridable, const bool ignore_overridden); + struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, const char *root_path, + struct IDOverrideStatic *override, const eRNAOverrideMatch flags, + eRNAOverrideMatchResult *r_report_flags); bool RNA_struct_override_store( struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, PointerRNA *ptr_storage, @@ -1268,10 +1289,6 @@ void RNA_struct_override_apply( struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, struct PointerRNA *ptr_storage, struct IDOverrideStatic *override); -bool RNA_struct_auto_override( - struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, - struct IDOverrideStatic *override, const char *root_path); - struct IDOverrideStaticProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop); struct IDOverrideStaticProperty *RNA_property_override_property_get(PointerRNA *ptr, PropertyRNA *prop, bool *r_created); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 2be26ccf3ee..da84f51cea2 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -7037,36 +7037,46 @@ void _RNA_warning(const char *format, ...) } static int rna_property_override_diff( - PointerRNA *a, PointerRNA *b, PropertyRNA *prop, eRNACompareMode mode, - IDOverrideStatic *override, const char *rna_path, bool *r_override_changed, const int flags); + PointerRNA *ptr_a, PointerRNA *ptr_b, 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 *a, PointerRNA *b, PropertyRNA *prop, eRNACompareMode mode) +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(a, b, prop, mode, NULL, NULL, NULL, 0) != 0); + PropertyRNA *prop_a = prop; + PropertyRNA *prop_b = prop; + + if (prop_a->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_a = (PropertyRNA *)rna_idproperty_find(ptr_a, ((IDProperty *)prop_a)->name); + prop_b = (PropertyRNA *)rna_idproperty_find(ptr_b, ((IDProperty *)prop_b)->name); + } + + return (rna_property_override_diff(ptr_a, ptr_b, prop_a, prop_b, NULL, mode, NULL, 0, NULL) != 0); } -bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNACompareMode mode) +bool RNA_struct_equals(PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode) { CollectionPropertyIterator iter; PropertyRNA *iterprop; bool equals = true; - if (a == NULL && b == NULL) + if (ptr_a == NULL && ptr_b == NULL) return true; - else if (a == NULL || b == NULL) + else if (ptr_a == NULL || ptr_b == NULL) return false; - else if (a->type != b->type) + else if (ptr_a->type != ptr_b->type) return false; - iterprop = RNA_struct_iterator_property(a->type); + iterprop = RNA_struct_iterator_property(ptr_a->type); - RNA_property_collection_begin(a, iterprop, &iter); + 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(a, b, prop, mode)) { + if (!RNA_property_equals(ptr_a, ptr_b, prop, mode)) { equals = false; break; } @@ -7079,27 +7089,13 @@ bool RNA_struct_equals(PointerRNA *a, PointerRNA *b, eRNACompareMode mode) /* Low-level functions, also used by non-override RNA API like copy or equality check. */ #include "PIL_time_utildefines.h" static int rna_property_override_diff( - PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop_a, eRNACompareMode mode, - IDOverrideStatic *override, const char *rna_path, bool *r_override_changed, const int flags) + PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop_a, PropertyRNA *prop_b, const char *rna_path, + eRNACompareMode mode, IDOverrideStatic *override, const int flags, eRNAOverrideMatchResult *r_report_flags) { - int len_a, len_b; - - PropertyRNA *prop_b = prop_a; - - if (prop_a->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. */ - /* Note: so far callers never resolve IDProps, so we can keep it here for now... */ - prop_a = (PropertyRNA *)rna_idproperty_find(ptr_a, ((IDProperty *)prop_a)->name); - prop_b = (PropertyRNA *)rna_idproperty_find(ptr_b, ((IDProperty *)prop_b)->name); - - if (ELEM(NULL, prop_a, prop_b)) { - return 1; - } + if (ELEM(NULL, prop_a, prop_b)) { + return 1; } - BLI_assert(prop_a->override_diff == prop_b->override_diff && prop_a->override_diff != NULL); - 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)) @@ -7112,16 +7108,58 @@ static int rna_property_override_diff( } /* get the length of the array to work with */ - len_a = RNA_property_array_length(ptr_a, prop_a); - len_b = RNA_property_array_length(ptr_b, prop_b); + const int len_a = RNA_property_array_length(ptr_a, prop_a); + const int len_b = RNA_property_array_length(ptr_b, prop_b); + + 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; + } 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; } - return prop_a->override_diff( - ptr_a, ptr_b, prop_a, prop_b, len_a, len_b, mode, override, rna_path, flags, r_override_changed); + if (is_array_a && len_a == 0) { + /* Empty array, will happen in some case with dynamic ones. */ + return 0; + } + + /* XXX TODO: support IDProps. + * Currently those fail in several cases, due among other things to the lack of proper callbacks... */ + if (prop_a->magic != RNA_MAGIC || prop_b->magic != RNA_MAGIC) { + return 0; + } + + if (prop_a->override_diff != prop_b->override_diff || prop_a->override_diff == NULL) { + if (prop_a->override_diff != prop_b->override_diff) { + printf("'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%p vs. %p, %d vs. %d).\n", + rna_path, prop_a->override_diff, prop_b->override_diff, prop_a->magic, prop_b->magic); + BLI_assert(0); + } + /* Other case (both diff callbacks being NULL) is annoying, but happens with addons-defined ID properties, + * for some reasons :/ */ + return 0; + } + + bool override_changed; + int diff_flags = flags; + if ((RNA_property_flag(prop_a) & PROP_OVERRIDABLE_STATIC) == 0) { + diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE; + } + const int diff = prop_a->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 @@ -7220,57 +7258,158 @@ static bool rna_property_override_operation_apply( opop); } - /** * Check whether reference and local overriden data match (are the same), - * with respect to given restrictive sets of properties. */ + * 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, - IDOverrideStatic *override, const bool ignore_non_overridable, const bool ignore_overridden) + PointerRNA *ptr_local, PointerRNA *ptr_reference, const char *root_path, + IDOverrideStatic *override, const eRNAOverrideMatch flags, + eRNAOverrideMatchResult *r_report_flags) { CollectionPropertyIterator iter; PropertyRNA *iterprop; - bool equals = true; + 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_IGNORE_NON_OVERRIDABLE) != 0; + const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0; + +#ifdef DEBUG_OVERRIDE_TIMEIT + static float _sum_time = 0.0f; + static float _num_time = 0.0f; + double _timeit_time; + if (!root_path) { + _timeit_time = PIL_check_seconds_timer(); + } +#endif iterprop = RNA_struct_iterator_property(ptr_local->type); - RNA_property_collection_begin(ptr_local, iterprop, &iter); - for (; iter.valid; RNA_property_collection_next(&iter)) { - PropertyRNA *prop = iter.ptr.data; + 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; - if (ignore_non_overridable && !(prop->flag & PROP_OVERRIDABLE_STATIC)) { - continue; - } + if (prop_local->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_local = (PropertyRNA *)rna_idproperty_find(ptr_local, ((IDProperty *)prop_local)->name); + prop_reference = (PropertyRNA *)rna_idproperty_find(ptr_reference, ((IDProperty *)prop_reference)->name); - if (ignore_overridden) { - /* XXX TODO this will have to be refined to handle collections insertions, and array items */ - char *rna_path = RNA_path_from_ID_to_property(ptr_local, prop); - if (BKE_override_static_property_find(override, rna_path) != NULL) { - MEM_SAFE_FREE(rna_path); + if (ELEM(NULL, prop_local, prop_reference)) { continue; } - MEM_SAFE_FREE(rna_path); } - int flag = 0; - if (ignore_non_overridable) { - flag |= RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE; + if (ignore_non_overridable && !(prop_local->flag & PROP_OVERRIDABLE_STATIC)) { + continue; } - if (ignore_overridden) { - flag |= RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN; + + 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; } - if (rna_property_override_diff(ptr_local, ptr_reference, prop, RNA_EQ_STRICT, override, NULL, NULL, flag) != 0) { - equals = false; - break; + + /* XXX TODO this will have to be refined to handle collections insertions, and array items */ + char *rna_path; + if (root_path) { + /* Inlined building, much much more efficient. */ + if (prop_local->magic == RNA_MAGIC) { + rna_path = BLI_sprintfN("%s.%s", root_path, RNA_property_identifier(prop_local)); + } + else { + rna_path = BLI_sprintfN("%s[\"%s\"]", root_path, RNA_property_identifier(prop_local)); + } + } + else { + rna_path = RNA_path_from_ID_to_property(ptr_local, prop_local); } + if (rna_path == NULL) { + continue; + } + + if (ignore_overridden && BKE_override_static_property_find(override, rna_path) == NULL) { + MEM_SAFE_FREE(rna_path); + continue; + } + + eRNAOverrideMatchResult report_flags = 0; + const int diff = rna_property_override_diff( + ptr_local, ptr_reference, prop_local, prop_reference, rna_path, + RNA_EQ_STRICT, override, flags, &report_flags); + + 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 { + BLI_assert(!"We have differences between reference and overriding data on non-editable property."); + 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; + } + } + } + + MEM_SAFE_FREE(rna_path); } RNA_property_collection_end(&iter); - return equals; +#ifdef DEBUG_OVERRIDE_TIMEIT + if (!root_path) { + const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time); + _sum_time += _delta_time; + _num_time++; + 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 / _num_time), _sum_time, (int)_num_time); + } +#endif + + return matching; } + /** 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) @@ -7362,76 +7501,6 @@ void RNA_struct_override_apply( #endif } -/** Automatically define override rules by comparing \a local and \a reference RNA structs. */ -bool RNA_struct_auto_override( - PointerRNA *ptr_local, PointerRNA *ptr_reference, IDOverrideStatic *override, const char *root_path) -{ - CollectionPropertyIterator iter; - PropertyRNA *iterprop; - bool changed = false; - - BLI_assert(ptr_local->type == ptr_reference->type); - BLI_assert(ptr_local->id.data && ptr_reference->id.data); - - if ((((ID *)ptr_local->id.data)->flag & LIB_OVERRIDE_STATIC_AUTO) == 0) { - return changed; - } - -#ifdef DEBUG_OVERRIDE_TIMEIT - static float _sum_time = 0.0f; - static float _num_time = 0.0f; - double _timeit_time; - if (!root_path) { - _timeit_time = 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 = iter.ptr.data; - - if (!(prop->flag & PROP_OVERRIDABLE_STATIC)) { - continue; - } - if (RNA_property_animated(ptr_local, prop)) { - continue; - } - - /* XXX TODO this will have to be refined to handle collections insertions, and array items */ - char *rna_path; - if (root_path) { - /* Inlined building, much much more efficient. */ - rna_path = BLI_sprintfN("%s.%s", root_path, RNA_property_identifier(prop)); - } - else { - rna_path = RNA_path_from_ID_to_property(ptr_local, prop); - } - if (rna_path == NULL) { - continue; - } - - rna_property_override_diff(ptr_local, ptr_reference, prop, RNA_EQ_STRICT, override, rna_path, &changed, - RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE | RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN); - - MEM_SAFE_FREE(rna_path); - } - RNA_property_collection_end(&iter); - -#ifdef DEBUG_OVERRIDE_TIMEIT - if (!root_path) { - const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time); - _sum_time += _delta_time; - _num_time++; - 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 / _num_time), _sum_time, (int)_num_time); - } -#endif - - return changed; -} - IDOverrideStaticProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop) { ID *id = ptr->id.data; diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index fd0b655e41e..88efff30481 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -121,12 +121,6 @@ typedef int (*PropEnumGetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *pro typedef void (*PropEnumSetFuncEx)(struct PointerRNA *ptr, struct PropertyRNA *prop, int value); /* Handling override operations, and also comparison. */ -enum { - /* Do not compare properties that are not overridable. */ - RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE = 1 << 0, - /* Do not compare properties that are already overridden. */ - RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN = 1 << 1, -}; /** * If \a override is NULL, merely do comparison between prop_a from ptr_a and prop_b from ptr_b, diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 24d56ef2a19..da4eea41223 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1094,10 +1094,12 @@ static int rna_BlenderRNA_structs_lookup_string(PointerRNA *ptr, const char *key /* Default override (and compare) callbacks. */ /* Used for both Pointer and Collection properties. */ -static int rna_property_override_equals_propptr( - PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode, - IDOverrideStatic *override, const char *rna_path, bool *r_override_changed, const int flags) +static int rna_property_override_diff_propptr( + PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode, const bool no_ownership, + IDOverrideStatic *override, const char *rna_path, const int flags, bool *r_override_changed) { + const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && rna_path != NULL; + bool is_id = false; bool is_type_null = false; @@ -1119,46 +1121,38 @@ static int rna_property_override_equals_propptr( if (is_id) { BLI_assert(propptr_a->data == propptr_a->id.data && propptr_b->data == propptr_b->id.data); + BLI_assert(no_ownership); /* For now, once we deal with nodetrees we'll want to get rid of that one. */ } if (override) { - if (rna_path) { - if (is_type_null || is_id) { - /* In case this is an ID (or one of the pointers is NULL), do not compare structs! - * This is a quite safe path to infinite loop. - * Instead, just compare pointers themselves (we assume sub-ID structs cannot loop). */ - const int comp = (propptr_a->data != propptr_b->data); - - if (comp != 0 && rna_path) { - bool created = false; - IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); + if (no_ownership /* || is_id */ || is_type_null) { + /* In case this pointer prop does not own its data (or one is NULL), do not compare structs! + * This is a quite safe path to infinite loop, among other nasty issues. + * Instead, just compare pointers themselves. */ + const int comp = (propptr_a->data != propptr_b->data); - if (op != NULL && created) { /* If not yet overridden... */ - BKE_override_static_property_operation_get( - op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL); - if (r_override_changed) { - *r_override_changed = created; - } - } - } + if (do_create && comp != 0) { + bool created = false; + IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); - return comp; - } - else { - const bool changed = RNA_struct_auto_override(propptr_a, propptr_b, override, rna_path); - if (r_override_changed) { - *r_override_changed = *r_override_changed || changed; + if (op != NULL && created) { /* If not yet overridden... */ + BKE_override_static_property_operation_get( + op, IDOVERRIDESTATIC_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL); + if (r_override_changed) { + *r_override_changed = created; + } } - /* XXX Simplification here, if no override was added we assume they are equal, - * this may not be good behavior, time will say. */ - return !changed; } + + return comp; } else { - return !RNA_struct_override_matches( - propptr_a, propptr_b, override, - flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE, - flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN); + eRNAOverrideMatchResult report_flags = 0; + const bool match = RNA_struct_override_matches(propptr_a, propptr_b, rna_path, override, flags, &report_flags); + if (r_override_changed && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) != 0) { + *r_override_changed = true; + } + return !match; } } else { @@ -1183,6 +1177,10 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, { BLI_assert(len_a == len_b); + /* Note: at this point, we are sure that when len_a is zero, we are not handling an (empty) array. */ + + const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 && rna_path != NULL; + switch (RNA_property_type(prop_a)) { case PROP_BOOLEAN: { @@ -1198,7 +1196,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const int comp = memcmp(array_a, array_b, sizeof(int) * len_a); - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { /* XXX TODO this will have to be refined to handle array items */ bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1225,7 +1223,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const int value_b = RNA_property_boolean_get(ptr_b, prop_b); const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0; - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1256,7 +1254,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const int comp = memcmp(array_a, array_b, sizeof(int) * len_a); - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { /* XXX TODO this will have to be refined to handle array items */ bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1283,7 +1281,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const int value_b = RNA_property_int_get(ptr_b, prop_b); const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0; - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1315,7 +1313,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const int comp = memcmp(array_a, array_b, sizeof(float) * len_a); - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { /* XXX TODO this will have to be refined to handle array items */ bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1343,7 +1341,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const float value_b = RNA_property_float_get(ptr_b, prop_b); const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0; - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1367,7 +1365,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, const int value_b = RNA_property_enum_get(ptr_b, prop_b); const int comp = value_a != value_b; - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1391,7 +1389,7 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, char *value_b = RNA_property_string_get_alloc(ptr_b, prop_b, fixed_b, sizeof(fixed_b), &len_str_b); const int comp = strcmp(value_a, value_b); - if (comp != 0 && rna_path) { + if (do_create && comp != 0) { bool created = false; IDOverrideStaticProperty *op = BKE_override_static_property_get(override, rna_path, &created); @@ -1419,9 +1417,10 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, else { PointerRNA propptr_a = RNA_property_pointer_get(ptr_a, prop_a); PointerRNA propptr_b = RNA_property_pointer_get(ptr_b, prop_b); - return rna_property_override_equals_propptr( - &propptr_a, &propptr_b, mode, - override, rna_path, r_override_changed, flags); + const bool no_ownership = (RNA_property_flag(prop_a) & PROP_PTR_NO_OWNERSHIP) != 0; + return rna_property_override_diff_propptr( + &propptr_a, &propptr_b, mode, no_ownership, + override, rna_path, flags, r_override_changed); } break; } @@ -1468,9 +1467,10 @@ int rna_property_override_diff_default(PointerRNA *ptr_a, PointerRNA *ptr_b, } if (equals) { - const int eq = rna_property_override_equals_propptr( - &iter_a.ptr, &iter_b.ptr, mode, - override, extended_rna_path, r_override_changed, flags); + const bool no_ownership = (RNA_property_flag(prop_a) & PROP_PTR_NO_OWNERSHIP) != 0; + const int eq = rna_property_override_diff_propptr( + &iter_a.ptr, &iter_b.ptr, mode, no_ownership, + override, extended_rna_path, flags, r_override_changed); equals = equals && eq; } |