Action Management Feature Request/Regression T45535
authorJoshua Leung <aligorith@gmail.com>
Tue, 25 Aug 2015 14:13:17 +0000 (02:13 +1200)
committerJoshua Leung <aligorith@gmail.com>
Tue, 25 Aug 2015 14:30:09 +0000 (02:30 +1200)
By popular request, restored the ability to shift-click on the X (unlink) button
to unlink the action (from the active action slot), clear the Fake User, and
also remove the NLA-stashed copy (only works for the current object/NLA stack though).

source/blender/editors/include/ED_anim_api.h
source/blender/editors/space_action/action_data.c
source/blender/editors/space_nla/nla_channels.c

index dfa667d095ac49fb616e894706b560cee3f8694f..3c8442218beb9ca627e06e45ec9b3a3630515983 100644 (file)
@@ -683,7 +683,9 @@ void ED_operatormacros_action(void);
 
 /* Action Editor - Action Management */
 struct AnimData *ED_actedit_animdata_from_context(struct bContext *C);
-void ED_animedit_unlink_action(struct bContext *C, struct ID *id, struct AnimData *adt, struct bAction *act, struct ReportList *reports);
+void ED_animedit_unlink_action(struct bContext *C, struct ID *id, 
+                               struct AnimData *adt, struct bAction *act,
+                               struct ReportList *reports, bool force_delete);
 
 /* ************************************************ */
 
index bffa9c413aec3da499756c08f2defdeecf631adf..c351942377327c33a6f96c58c7ba81c2cd6e9497 100644 (file)
@@ -532,7 +532,7 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot)
  * 3) We need a convenient way to exit Tweak Mode from the Action Editor
  */
 
-void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports)
+void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
 {
        ScrArea *sa = CTX_wm_area(C);
        
@@ -548,6 +548,45 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
                            act->id.name + 2);
        }
        
+       /* Clear Fake User and remove action stashing strip (if present) */
+       if (force_delete) {
+               /* Remove stashed strip binding this action to this datablock */
+               /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
+                * but GE users only seem to use/care about single-object binding for now so this
+                * should be fine
+                */
+               if (adt) {
+                       NlaTrack *nlt, *nlt_next;
+                       NlaStrip *strip, *nstrip;
+                       
+                       for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
+                               nlt_next = nlt->next;
+                               
+                               if (strstr(nlt->name, DATA_("[Action Stash]"))) {
+                                       for (strip = nlt->strips.first; strip; strip = nstrip) {
+                                               nstrip = strip->next;
+                                               
+                                               if (strip->act == act) {
+                                                       /* Remove this strip, and the track too if it doesn't have anything else */
+                                                       free_nlastrip(&nlt->strips, strip);
+                                                       
+                                                       if (nlt->strips.first == NULL) {
+                                                               BLI_assert(nstrip == NULL);
+                                                               free_nlatrack(&adt->nla_tracks, nlt);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               /* Clear Fake User */
+               if (act->id.flag & LIB_FAKEUSER) {
+                       act->id.flag &= ~LIB_FAKEUSER;
+                       act->id.us--;
+               }
+       }
+       
        /* If in Tweak Mode, don't unlink. Instead, this 
         * becomes a shortcut to exit Tweak Mode instead
         */
@@ -602,24 +641,40 @@ static int action_unlink_poll(bContext *C)
 static int action_unlink_exec(bContext *C, wmOperator *op)
 {
        AnimData *adt = ED_actedit_animdata_from_context(C);
+       bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
        
        if (adt && adt->action) {
-               ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports);
+               ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
        }
        
        return OPERATOR_FINISHED;
 }
 
+static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+{
+       /* NOTE: this is hardcoded to match the behaviour for the unlink button (in interface_templates.c) */
+       RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+       return action_unlink_exec(C, op);
+}
+
 void ACTION_OT_unlink(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
        ot->name = "Unlink Action";
        ot->idname = "ACTION_OT_unlink";
        ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
        
        /* callbacks */
+       ot->invoke = action_unlink_invoke;
        ot->exec = action_unlink_exec;
        ot->poll = action_unlink_poll;
+       
+       /* properties */
+       prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete", 
+                              "Clear Fake User and remove copy stashed in this datablock's NLA stack");
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 /* ************************************************************************** */
index 32a8e660f662d7361c6f7c024bdd063bdaf02cd3..a0ea12b8aa0f5ea688c813f28d32068e60bd706e 100644 (file)
@@ -534,22 +534,38 @@ static int nla_action_unlink_exec(bContext *C, wmOperator *op)
        
        /* do unlinking */
        if (adt && adt->action) {
-               ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports);
+               bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
+               ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete);
        }
        
        return OPERATOR_FINISHED;
 }
 
+static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
+{
+       /* NOTE: this is hardcoded to match the behaviour for the unlink button (in interface_templates.c) */
+       RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
+       return nla_action_unlink_exec(C, op);
+}
+
 void NLA_OT_action_unlink(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+       
        /* identifiers */
        ot->name = "Unlink Action";
        ot->idname = "NLA_OT_action_unlink";
        ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
        
        /* callbacks */
+       ot->invoke = nla_action_unlink_invoke;
        ot->exec = nla_action_unlink_exec;
        ot->poll = nla_action_unlink_poll;
+       
+       /* properties */
+       prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete", 
+                              "Clear Fake User and remove copy stashed in this datablock's NLA stack");
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 /* ******************** Add Tracks Operator ***************************** */