diff options
author | Bastien Montagne <bastien@blender.org> | 2021-11-19 11:33:52 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2021-11-19 17:41:53 +0300 |
commit | 33c5e7bcd5e5b790ee95caaa0c4d917996341266 (patch) | |
tree | 9bce351ce98200b7313bb136fac443eb9d98c9a7 /source/blender/makesrna | |
parent | d6ea881a741a254b6f4e931ea25047d3f51686d0 (diff) |
LibOverrides: Refactor how diffing of RNA collections is handled.
Original implementation was a quick prototype which should have never
landed as-is in master. It had very limiting constraints and did not
allow for any real further development.
This commit fixes the internal implementation to make more sensible,
maintainable and evolutive.
NOTE: This commit introduces another forward-incompatibility in the
Blender file format: Files saved after this commit won't open properly
in older versions of blender regarding local inserted constraints or
modifiers into overrides of linked data.
NOTE: Technical details: The 'anchor' item name/index is now stored in
`subitem_reference_` members, and the actual 'source' item name/index is
stored in `subitem_local_` members of the override property operation
data.
Previously, only the `subitem_local_` members were used, storing the
anchor item name/index, and assuming the 'source' item was always the
next in the list.
Milestone I of T82160.
Maniphest Tasks: T82160
Differential Revision: https://developer.blender.org/D13282
Diffstat (limited to 'source/blender/makesrna')
-rw-r--r-- | source/blender/makesrna/intern/rna_animation.c | 10 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object.c | 90 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_pose.c | 29 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_rna.c | 11 |
4 files changed, 56 insertions, 84 deletions
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 52c25bae45a..9068fdb6e72 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -761,8 +761,8 @@ bool rna_NLA_tracks_override_apply(Main *bmain, /* This is not working so well with index-based insertion, especially in case some tracks get * added to lib linked data. So we simply add locale tracks at the end of the list always, order * of override operations should ensure order of local tracks is preserved properly. */ - if (opop->subitem_local_index >= 0) { - nla_track_anchor = BLI_findlink(&anim_data_dst->nla_tracks, opop->subitem_local_index); + if (opop->subitem_reference_index >= 0) { + nla_track_anchor = BLI_findlink(&anim_data_dst->nla_tracks, opop->subitem_reference_index); } /* Otherwise we just insert in first position. */ # else @@ -773,9 +773,11 @@ bool rna_NLA_tracks_override_apply(Main *bmain, if (opop->subitem_local_index >= 0) { nla_track_src = BLI_findlink(&anim_data_src->nla_tracks, opop->subitem_local_index); } - nla_track_src = nla_track_src ? nla_track_src->next : anim_data_src->nla_tracks.first; - BLI_assert(nla_track_src != NULL); + if (nla_track_src == NULL) { + BLI_assert(nla_track_src != NULL); + return false; + } NlaTrack *nla_track_dst = BKE_nlatrack_copy(bmain, nla_track_src, true, 0); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index bf64196c8ab..0cb132786cd 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1705,27 +1705,20 @@ bool rna_Object_constraints_override_apply(Main *UNUSED(bmain), /* Remember that insertion operations are defined and stored in correct order, which means that * even if we insert several items in a row, we always insert first one, then second one, etc. * So we should always find 'anchor' constraint in both _src *and* _dst. */ - bConstraint *con_anchor = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - con_anchor = BLI_findstring( - &ob_dst->constraints, opop->subitem_local_name, offsetof(bConstraint, name)); - } - if (con_anchor == NULL && opop->subitem_local_index >= 0) { - con_anchor = BLI_findlink(&ob_dst->constraints, opop->subitem_local_index); - } - /* Otherwise we just insert in first position. */ - - bConstraint *con_src = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - con_src = BLI_findstring( - &ob_src->constraints, opop->subitem_local_name, offsetof(bConstraint, name)); - } - if (con_src == NULL && opop->subitem_local_index >= 0) { - con_src = BLI_findlink(&ob_src->constraints, opop->subitem_local_index); + const size_t name_offset = offsetof(bConstraint, name); + bConstraint *con_anchor = BLI_listbase_string_or_index_find(&ob_dst->constraints, + opop->subitem_reference_name, + name_offset, + opop->subitem_reference_index); + /* If `con_anchor` is NULL, `con_src` will be inserted in first position. */ + + bConstraint *con_src = BLI_listbase_string_or_index_find( + &ob_src->constraints, opop->subitem_local_name, name_offset, opop->subitem_local_index); + + if (con_src == NULL) { + BLI_assert(con_src != NULL); + return false; } - con_src = con_src ? con_src->next : ob_src->constraints.first; - - BLI_assert(con_src != NULL); bConstraint *con_dst = BKE_constraint_duplicate_ex(con_src, 0, true); @@ -1827,25 +1820,15 @@ bool rna_Object_modifiers_override_apply(Main *bmain, /* Remember that insertion operations are defined and stored in correct order, which means that * even if we insert several items in a row, we always insert first one, then second one, etc. * So we should always find 'anchor' modifier in both _src *and* _dst. */ - ModifierData *mod_anchor = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - mod_anchor = BLI_findstring( - &ob_dst->modifiers, opop->subitem_local_name, offsetof(ModifierData, name)); - } - if (mod_anchor == NULL && opop->subitem_local_index >= 0) { - mod_anchor = BLI_findlink(&ob_dst->modifiers, opop->subitem_local_index); - } - /* Otherwise we just insert in first position. */ + const size_t name_offset = offsetof(ModifierData, name); + ModifierData *mod_anchor = BLI_listbase_string_or_index_find(&ob_dst->modifiers, + opop->subitem_reference_name, + name_offset, + opop->subitem_reference_index); + /* If `mod_anchor` is NULL, `mod_src` will be inserted in first position. */ - ModifierData *mod_src = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - mod_src = BLI_findstring( - &ob_src->modifiers, opop->subitem_local_name, offsetof(ModifierData, name)); - } - if (mod_src == NULL && opop->subitem_local_index >= 0) { - mod_src = BLI_findlink(&ob_src->modifiers, opop->subitem_local_index); - } - mod_src = mod_src ? mod_src->next : ob_src->modifiers.first; + ModifierData *mod_src = BLI_listbase_string_or_index_find( + &ob_src->modifiers, opop->subitem_local_name, name_offset, opop->subitem_local_index); if (mod_src == NULL) { BLI_assert(mod_src != NULL); @@ -1934,25 +1917,18 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain, /* Remember that insertion operations are defined and stored in correct order, which means that * even if we insert several items in a row, we always insert first one, then second one, etc. * So we should always find 'anchor' modifier in both _src *and* _dst. */ - GpencilModifierData *mod_anchor = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - mod_anchor = BLI_findstring( - &ob_dst->greasepencil_modifiers, opop->subitem_local_name, offsetof(ModifierData, name)); - } - if (mod_anchor == NULL && opop->subitem_local_index >= 0) { - mod_anchor = BLI_findlink(&ob_dst->greasepencil_modifiers, opop->subitem_local_index); - } - /* Otherwise we just insert in first position. */ - - GpencilModifierData *mod_src = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - mod_src = BLI_findstring( - &ob_src->greasepencil_modifiers, opop->subitem_local_name, offsetof(ModifierData, name)); - } - if (mod_src == NULL && opop->subitem_local_index >= 0) { - mod_src = BLI_findlink(&ob_src->greasepencil_modifiers, opop->subitem_local_index); - } - mod_src = mod_src ? mod_src->next : ob_src->greasepencil_modifiers.first; + const size_t name_offset = offsetof(GpencilModifierData, name); + GpencilModifierData *mod_anchor = BLI_listbase_string_or_index_find( + &ob_dst->greasepencil_modifiers, + opop->subitem_reference_name, + name_offset, + opop->subitem_reference_index); + /* If `mod_anchor` is NULL, `mod_src` will be inserted in first position. */ + + GpencilModifierData *mod_src = BLI_listbase_string_or_index_find(&ob_src->greasepencil_modifiers, + opop->subitem_local_name, + name_offset, + opop->subitem_local_index); if (mod_src == NULL) { BLI_assert(mod_src != NULL); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index cdf7fe5a7aa..87173adc38f 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -682,29 +682,18 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain), /* Remember that insertion operations are defined and stored in correct order, which means that * even if we insert several items in a row, we always insert first one, then second one, etc. * So we should always find 'anchor' constraint in both _src *and* _dst */ - bConstraint *con_anchor = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - con_anchor = BLI_findstring( - &pchan_dst->constraints, opop->subitem_local_name, offsetof(bConstraint, name)); - } - if (con_anchor == NULL && opop->subitem_local_index >= 0) { - con_anchor = BLI_findlink(&pchan_dst->constraints, opop->subitem_local_index); - } - /* Otherwise we just insert in first position. */ + const size_t name_offset = offsetof(bConstraint, name); + bConstraint *con_anchor = BLI_listbase_string_or_index_find(&pchan_dst->constraints, + opop->subitem_reference_name, + name_offset, + opop->subitem_reference_index); + /* If `con_anchor` is NULL, `con_src` will be inserted in first position. */ - bConstraint *con_src = NULL; - if (opop->subitem_local_name && opop->subitem_local_name[0]) { - con_src = BLI_findstring( - &pchan_src->constraints, opop->subitem_local_name, offsetof(bConstraint, name)); - } - if (con_src == NULL && opop->subitem_local_index >= 0) { - con_src = BLI_findlink(&pchan_src->constraints, opop->subitem_local_index); - } - con_src = con_src ? con_src->next : pchan_src->constraints.first; + bConstraint *con_src = BLI_listbase_string_or_index_find( + &pchan_src->constraints, opop->subitem_local_name, name_offset, opop->subitem_local_index); if (con_src == NULL) { - printf("%s: Could not find constraint to insert, doing nothing...\n", __func__); - BLI_assert(0); + BLI_assert(con_src != NULL); return false; } diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 12fb7a40d13..e5009305fe5 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1916,16 +1916,21 @@ int rna_property_override_diff_default(Main *bmain, /* Collections do not support replacement of their data (except for collections of ID * pointers), since they do not support removing, only in *some* cases, insertion. We - * also assume then that _a data is the one where things are inserted. */ + * also assume then that _a data is the one where things are inserted. + * + * NOTE: In insertion case, both 'local' and 'reference' (aka anchor) sub-item + * identifiers refer to collection items in the local override. The 'reference' may match + * an item in the linked reference data, but it can also be another local-only item added + * by a previous INSERT operation. */ if (is_valid_for_insertion && use_collection_insertion) { op = BKE_lib_override_library_property_get(override, rna_path, &created); BKE_lib_override_library_property_operation_get(op, IDOVERRIDE_LIBRARY_OP_INSERT_AFTER, - NULL, no_prop_name ? NULL : prev_propname_a, - -1, + no_prop_name ? NULL : propname_a, idx_a - 1, + idx_a, true, NULL, NULL); |