diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_dopesheet.py | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 8 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_data.c | 126 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_ops.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_buttons.c | 6 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_channels.c | 46 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_nla/nla_ops.c | 1 |
9 files changed, 179 insertions, 15 deletions
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index c4452ee61f4..bb08a7c392e 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -118,7 +118,7 @@ class DOPESHEET_HT_header(Header): row.operator("action.layer_prev", text="", icon='TRIA_DOWN') row.operator("action.layer_next", text="", icon='TRIA_UP') - layout.template_ID(st, "action", new="action.new") + layout.template_ID(st, "action", new="action.new", unlink="action.unlink") row = layout.row(align=True) row.operator("action.push_down", text="Push Down", icon='NLA_PUSHDOWN') diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 4c7c78df349..9dea66adc7c 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -676,6 +676,14 @@ void ED_operatormacros_graph(void); void ED_operatormacros_action(void); /* ************************************************ */ +/* Animation Editor Exports */ +/* XXX: Should we be doing these here, or at all? */ + +/* 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); + +/* ************************************************ */ #endif /* __ED_ANIM_API_H__ */ diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index a4eadd8a63b..e55da7dd4b3 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -81,10 +81,10 @@ #include "action_intern.h" /* ************************************************************************** */ -/* ACTION MANAGEMENT */ +/* ACTION CREATION */ /* Helper function to find the active AnimData block from the Action Editor context */ -static AnimData *actedit_animdata_from_context(bContext *C) +AnimData *ED_actedit_animdata_from_context(bContext *C) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); Object *ob = CTX_data_active_object(C); @@ -234,7 +234,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) adt = ptr.data; } else if (ptr.type == &RNA_SpaceDopeSheetEditor) { - adt = actedit_animdata_from_context(C); + adt = ED_actedit_animdata_from_context(C); } /* Perform stashing operation - But only if there is an action */ @@ -301,7 +301,7 @@ static int action_pushdown_poll(bContext *C) { if (ED_operator_action_active(C)) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Check for AnimData, Actions, and that tweakmode is off */ if (adt && saction->action) { @@ -320,7 +320,7 @@ static int action_pushdown_poll(bContext *C) static int action_pushdown_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Do the deed... */ if (adt) { @@ -368,7 +368,7 @@ void ACTION_OT_push_down(wmOperatorType *ot) static int action_stash_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Perform stashing operation */ if (adt) { @@ -431,7 +431,7 @@ void ACTION_OT_stash(wmOperatorType *ot) static int action_stash_create_poll(bContext *C) { if (ED_operator_action_active(C)) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ @@ -461,7 +461,7 @@ static int action_stash_create_poll(bContext *C) static int action_stash_create_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); /* Check for no action... */ if (saction->action == NULL) { @@ -521,6 +521,108 @@ void ACTION_OT_stash_and_create(wmOperatorType *ot) } /* ************************************************************************** */ +/* ACTION UNLINK */ + +/* ******************* Action Unlink Operator ******************** */ +/* We use a custom unlink operator here, as there are some technicalities which need special care: + * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action, + * or else, everything turns to custard. + * 2) If the Action doesn't have any other users, the user should at least get + * a warning that it is going to get lost. + * 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) +{ + ScrArea *sa = CTX_wm_area(C); + + /* If the old action only has a single user (that it's about to lose), + * warn user about it + * + * TODO: Maybe we should just save it for them? But then, there's the problem of + * trying to get rid of stuff that's actually unwanted! + */ + if (act->id.us == 1) { + BKE_reportf(reports, RPT_ERROR, + "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", + act->id.name + 2); + } + + /* If in Tweak Mode, don't unlink. Instead, this + * becomes a shortcut to exit Tweak Mode instead + */ + if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { + /* Exit Tweak Mode */ + BKE_nla_tweakmode_exit(adt); + + /* Flush this to the Action Editor (if that's where this change was initiated) */ + if (sa->spacetype == SPACE_ACTION) { + actedit_change_action(C, NULL); + } + } + else { + /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */ + if (sa->spacetype == SPACE_ACTION) { + /* clear action editor -> action */ + actedit_change_action(C, NULL); + } + else { + /* clear AnimData -> action */ + PointerRNA ptr; + PropertyRNA *prop; + + /* create AnimData RNA pointers */ + RNA_pointer_create(id, &RNA_AnimData, adt, &ptr); + prop = RNA_struct_find_property(&ptr, "action"); + + /* clear... */ + RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL); + RNA_property_update(C, &ptr, prop); + } + } +} + +/* -------------------------- */ + +static int action_unlink_poll(bContext *C) +{ + if (ED_operator_action_active(C)) { + SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); + AnimData *adt = ED_actedit_animdata_from_context(C); + + /* Only when there's an active action, in the right modes... */ + if (saction->action && adt) + return true; + } + + /* something failed... */ + return false; +} + +static int action_unlink_exec(bContext *C, wmOperator *op) +{ + AnimData *adt = ED_actedit_animdata_from_context(C); + + if (adt && adt->action) { + ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports); + } + + return OPERATOR_FINISHED; +} + +void ACTION_OT_unlink(wmOperatorType *ot) +{ + /* 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->exec = action_unlink_exec; + ot->poll = action_unlink_poll; +} + +/* ************************************************************************** */ /* ACTION BROWSING */ /* Get the NLA Track that the active action comes from, since this is not stored in AnimData */ @@ -631,7 +733,7 @@ static int action_layer_next_poll(bContext *C) { /* Action Editor's action editing modes only */ if (ED_operator_action_active(C)) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { /* only allow if we're in tweakmode, and there's something above us... */ if (adt->flag & ADT_NLA_EDIT_ON) { @@ -665,7 +767,7 @@ static int action_layer_next_poll(bContext *C) static int action_layer_next_exec(bContext *C, wmOperator *op) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); NlaTrack *act_track; Scene *scene = CTX_data_scene(C); @@ -742,7 +844,7 @@ static int action_layer_prev_poll(bContext *C) { /* Action Editor's action editing modes only */ if (ED_operator_action_active(C)) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { if (adt->flag & ADT_NLA_EDIT_ON) { /* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */ @@ -775,7 +877,7 @@ static int action_layer_prev_poll(bContext *C) static int action_layer_prev_exec(bContext *C, wmOperator *op) { - AnimData *adt = actedit_animdata_from_context(C); + AnimData *adt = ED_actedit_animdata_from_context(C); NlaTrack *act_track; NlaTrack *nlt; diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 3b0da089b9b..9f9b15c3c26 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -98,6 +98,8 @@ void ACTION_OT_snap(struct wmOperatorType *ot); void ACTION_OT_mirror(struct wmOperatorType *ot); void ACTION_OT_new(struct wmOperatorType *ot); +void ACTION_OT_unlink(struct wmOperatorType *ot); + void ACTION_OT_push_down(struct wmOperatorType *ot); void ACTION_OT_stash(struct wmOperatorType *ot); void ACTION_OT_stash_and_create(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 431dd27d064..9ad0931a957 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -79,6 +79,8 @@ void action_operatortypes(void) WM_operatortype_append(ACTION_OT_paste); WM_operatortype_append(ACTION_OT_new); + WM_operatortype_append(ACTION_OT_unlink); + WM_operatortype_append(ACTION_OT_push_down); WM_operatortype_append(ACTION_OT_stash); WM_operatortype_append(ACTION_OT_stash_and_create); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 66023ce1243..1fb7228dd98 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -159,7 +159,9 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p } /* AnimData pointer */ - RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); + if (adt_ptr) { + RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); + } /* set found status to -1, since setting to 1 would break the loop * and potentially skip an active NLA-Track in some cases... @@ -282,7 +284,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa) /* Active Action Properties ------------------------------------- */ /* action */ row = uiLayoutRow(layout, true); - uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, NULL /*"ACTION_OT_unlink"*/); // XXX: need to make these operators + uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, "NLA_OT_action_unlink"); /* extrapolation */ row = uiLayoutRow(layout, true); diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 5476d1c2683..70d9bfe99fe 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -504,6 +504,52 @@ void NLA_OT_action_pushdown(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } +/* ******************** Action Unlink ******************************** */ + +static int nla_action_unlink_poll(bContext *C) +{ + if (ED_operator_nla_active(C)) { + return nla_panel_context(C, NULL, NULL, NULL); + } + + /* something failed... */ + return false; +} + +static int nla_action_unlink_exec(bContext *C, wmOperator *op) +{ + PointerRNA adt_ptr; + AnimData *adt; + + /* check context and also validity of pointer */ + if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) + return OPERATOR_CANCELLED; + + /* get animdata */ + adt = adt_ptr.data; + if (adt == NULL) + return OPERATOR_CANCELLED; + + /* do unlinking */ + if (adt && adt->action) { + ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports); + } + + return OPERATOR_FINISHED; +} + +void NLA_OT_action_unlink(wmOperatorType *ot) +{ + /* 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->exec = nla_action_unlink_exec; + ot->poll = nla_action_unlink_poll; +} + /* ******************** Add Tracks Operator ***************************** */ /* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */ diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index bd96b5a4de5..70fdb2d478d 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -137,6 +137,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac); void NLA_OT_channels_click(wmOperatorType *ot); void NLA_OT_action_pushdown(wmOperatorType *ot); +void NLA_OT_action_unlink(wmOperatorType *ot); void NLA_OT_tracks_add(wmOperatorType *ot); void NLA_OT_tracks_delete(wmOperatorType *ot); diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index b3a875047db..43bc4b9df0f 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -114,6 +114,7 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_channels_click); WM_operatortype_append(NLA_OT_action_pushdown); + WM_operatortype_append(NLA_OT_action_unlink); WM_operatortype_append(NLA_OT_tracks_add); WM_operatortype_append(NLA_OT_tracks_delete); |