From e80ceb52df7eba37a1aee226b586d9e4cee6ff4a Mon Sep 17 00:00:00 2001 From: Christoph Lendenfeld Date: Thu, 17 Jul 2025 11:35:18 +0200 Subject: [PATCH] Fix #139509: Slot assignment is lost when loading file saved in tweak mode The issue was that the `AnimData.tmp_slot_handle` had no RNA property associated with it and so it couldn't be saved in the lib override. The fix is to add the property. To ensure the correct code is called, most of the previous code was replaced with a call to `blender::animrig::assign_tmpaction` Pull Request: https://projects.blender.org/blender/blender/pulls/141395 --- source/blender/blenkernel/BKE_anim_data.hh | 5 -- source/blender/blenkernel/intern/anim_data.cc | 65 ------------------- .../blender/makesrna/intern/rna_animation.cc | 22 ++++++- 3 files changed, 19 insertions(+), 73 deletions(-) diff --git a/source/blender/blenkernel/BKE_anim_data.hh b/source/blender/blenkernel/BKE_anim_data.hh index e2cf666f260..acbad30526c 100644 --- a/source/blender/blenkernel/BKE_anim_data.hh +++ b/source/blender/blenkernel/BKE_anim_data.hh @@ -75,11 +75,6 @@ AnimData *BKE_animdata_ensure_id(ID *id); */ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act); -/** - * Same as BKE_animdata_set_action(), except sets `tmpact` instead of `action`. - */ -bool BKE_animdata_set_tmpact(ReportList *reports, ID *id, bAction *act); - bool BKE_animdata_action_editable(const AnimData *adt); /** diff --git a/source/blender/blenkernel/intern/anim_data.cc b/source/blender/blenkernel/intern/anim_data.cc index af89302298e..df3226569fe 100644 --- a/source/blender/blenkernel/intern/anim_data.cc +++ b/source/blender/blenkernel/intern/anim_data.cc @@ -119,71 +119,6 @@ AnimData *BKE_animdata_ensure_id(ID *id) return nullptr; } -/* Action / `tmpact` Setter shared code ------------------------- - * - * Both the action and `tmpact` setter functions have essentially - * identical semantics, because `tmpact` is just a place to temporarily - * store the main action during tweaking. This function contains the - * shared code between those two setter functions, setting the action - * of the passed `act_slot` to `act`. - * - * Preconditions: - * - `id` and `act_slot` must be non-null (but the pointer `act_slot` - * points to can be null). - * - `id` must have animation data. - * - `act_slot` must be a pointer to either the `action` or `tmpact` - * field of `id`'s animation data. - */ -static bool animdata_set_action(ReportList *reports, ID *id, bAction **act_slot, bAction *act) -{ - /* Action must have same type as owner. */ - if (!BKE_animdata_action_ensure_idroot(id, act)) { - /* Cannot set to this type. */ - BKE_reportf( - reports, - RPT_ERROR, - "Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths " - "for this purpose", - act->id.name + 2, - id->name); - return false; - } - - if (*act_slot == act) { - /* Don't bother reducing and increasing the user count when there is nothing changing. */ - return true; - } - - /* Unassign current action. */ - if (*act_slot) { - id_us_min((ID *)*act_slot); - *act_slot = nullptr; - } - - if (act == nullptr) { - return true; - } - - *act_slot = act; - id_us_plus((ID *)*act_slot); - - return true; -} - -/* Tmpact Setter --------------------------------------- */ - -bool BKE_animdata_set_tmpact(ReportList *reports, ID *id, bAction *act) -{ - AnimData *adt = BKE_animdata_from_id(id); - - if (adt == nullptr) { - BKE_report(reports, RPT_WARNING, "No AnimData to set tmpact on"); - return false; - } - - return animdata_set_action(reports, id, &adt->tmpact, act); -} - /* Action Setter --------------------------------------- */ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act) diff --git a/source/blender/makesrna/intern/rna_animation.cc b/source/blender/makesrna/intern/rna_animation.cc index c659eb1ef73..be143f5e624 100644 --- a/source/blender/makesrna/intern/rna_animation.cc +++ b/source/blender/makesrna/intern/rna_animation.cc @@ -227,8 +227,14 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value, ReportLis static void rna_AnimData_tmpact_set(PointerRNA *ptr, PointerRNA value, ReportList *reports) { - ID *ownerId = ptr->owner_id; - BKE_animdata_set_tmpact(reports, ownerId, static_cast(value.data)); + ID *owner_id = ptr->owner_id; + AnimData *adt = (AnimData *)ptr->data; + BLI_assert(adt != nullptr); + + bAction *action = static_cast(value.data); + if (!blender::animrig::assign_tmpaction(action, {*owner_id, *adt})) { + BKE_report(reports, RPT_WARNING, "Failed to set tmpact"); + } } static void rna_AnimData_tweakmode_set(PointerRNA *ptr, const bool value) @@ -1695,7 +1701,17 @@ static void rna_def_animdata(BlenderRNA *brna) prop, nullptr, "rna_AnimData_tmpact_set", nullptr, "rna_Action_id_poll"); RNA_def_property_ui_text(prop, "Tweak Mode Action Storage", - "Slot to temporarily hold the main action while in tweak mode"); + "Storage to temporarily hold the main action while in tweak mode"); + RNA_def_property_update(prop, NC_ANIMATION | ND_NLA_ACTCHANGE, "rna_AnimData_dependency_update"); + + /* Temporary action slot for tweak mode. Just like `action_slot_handle` this is needed for + * library overrides to work.*/ + prop = RNA_def_property(srna, "action_slot_handle_tweak_storage", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, nullptr, "tmp_slot_handle"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_EDITABLE); + RNA_def_property_ui_text(prop, + "Tweak Mode Action Slot Storage", + "Storage to temporarily hold the main action slot while in tweak mode"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA_ACTCHANGE, "rna_AnimData_dependency_update"); /* Drivers */