2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2015 Blender Foundation
19 * This is a new part of Blender
21 * Contributor(s): Joshua Leung
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/space_action/action_data.c
37 #include "BLI_blenlib.h"
39 #include "BLI_utildefines.h"
41 #include "BLT_translation.h"
43 #include "DNA_anim_types.h"
44 #include "DNA_gpencil_types.h"
45 #include "DNA_key_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_mask_types.h"
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52 #include "RNA_enum_types.h"
54 #include "BKE_animsys.h"
55 #include "BKE_action.h"
56 #include "BKE_fcurve.h"
57 #include "BKE_global.h"
58 #include "BKE_library.h"
62 #include "BKE_scene.h"
63 #include "BKE_context.h"
64 #include "BKE_report.h"
66 #include "UI_view2d.h"
68 #include "ED_anim_api.h"
69 #include "ED_gpencil.h"
70 #include "ED_keyframing.h"
71 #include "ED_keyframes_edit.h"
72 #include "ED_screen.h"
73 #include "ED_markers.h"
79 #include "UI_interface.h"
81 #include "action_intern.h"
83 /* ************************************************************************** */
86 /* Helper function to find the active AnimData block from the Action Editor context */
87 AnimData *ED_actedit_animdata_from_context(bContext *C)
89 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
90 Object *ob = CTX_data_active_object(C);
93 /* Get AnimData block to use */
94 if (saction->mode == SACTCONT_ACTION) {
95 /* Currently, "Action Editor" means object-level only... */
100 else if (saction->mode == SACTCONT_SHAPEKEY) {
101 Key *key = BKE_key_from_object(ob);
110 /* -------------------------------------------------------------------- */
112 /* Create new action */
113 static bAction *action_create_new(bContext *C, bAction *oldact)
115 ScrArea *sa = CTX_wm_area(C);
118 /* create action - the way to do this depends on whether we've got an
119 * existing one there already, in which case we make a copy of it
120 * (which is useful for "versioning" actions within the same file)
122 if (oldact && GS(oldact->id.name) == ID_AC) {
123 /* make a copy of the existing action */
124 action = BKE_action_copy(oldact);
127 /* just make a new (empty) action */
128 action = add_empty_action(CTX_data_main(C), "Action");
131 /* when creating new ID blocks, there is already 1 user (as for all new datablocks),
132 * but the RNA pointer code will assign all the proper users instead, so we compensate
135 BLI_assert(action->id.us == 1);
136 id_us_min(&action->id);
138 /* set ID-Root type */
139 if (sa->spacetype == SPACE_ACTION) {
140 SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
142 if (saction->mode == SACTCONT_SHAPEKEY)
143 action->idroot = ID_KE;
145 action->idroot = ID_OB;
151 /* Change the active action used by the action editor */
152 static void actedit_change_action(bContext *C, bAction *act)
154 bScreen *screen = CTX_wm_screen(C);
155 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
157 PointerRNA ptr, idptr;
160 /* create RNA pointers and get the property */
161 RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
162 prop = RNA_struct_find_property(&ptr, "action");
164 /* NOTE: act may be NULL here, so better to just use a cast here */
165 RNA_id_pointer_create((ID *)act, &idptr);
167 /* set the new pointer, and force a refresh */
168 RNA_property_pointer_set(&ptr, prop, idptr);
169 RNA_property_update(C, &ptr, prop);
172 /* ******************** New Action Operator *********************** */
175 * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
177 * The NLA Editor is active (i.e. Animation Data panel -> new action)
178 * 2) The associated AnimData block must not be in tweakmode
180 static int action_new_poll(bContext *C)
182 Scene *scene = CTX_data_scene(C);
184 /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
185 /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
186 if (ED_operator_action_active(C)) {
187 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
188 Object *ob = CTX_data_active_object(C);
190 /* For now, actions are only for the active object, and on object and shapekey levels... */
191 if (saction->mode == SACTCONT_ACTION) {
192 /* XXX: This assumes that actions are assigned to the active object in this mode */
194 if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0)
198 else if (saction->mode == SACTCONT_SHAPEKEY) {
199 Key *key = BKE_key_from_object(ob);
201 if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0)
206 else if (ED_operator_nla_active(C)) {
207 if (!(scene->flag & SCE_NLA_EDIT_ON)) {
212 /* something failed... */
216 static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
218 PointerRNA ptr, idptr;
222 UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
225 bAction *action = NULL, *oldact = NULL;
226 AnimData *adt = NULL;
229 oldptr = RNA_property_pointer_get(&ptr, prop);
230 oldact = (bAction *)oldptr.id.data;
232 /* stash the old action to prevent it from being lost */
233 if (ptr.type == &RNA_AnimData) {
236 else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
237 adt = ED_actedit_animdata_from_context(C);
240 /* Perform stashing operation - But only if there is an action */
242 /* stash the action */
243 if (BKE_nla_action_stash(adt)) {
244 /* The stash operation will remove the user already
245 * (and unlink the action from the AnimData action slot).
246 * Hence, we must unset the ref to the action in the
247 * action editor too (if this is where we're being called from)
248 * first before setting the new action once it is created,
249 * or else the user gets decremented twice!
251 if (ptr.type == &RNA_SpaceDopeSheetEditor) {
252 SpaceAction *saction = (SpaceAction *)ptr.data;
253 saction->action = NULL;
257 //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name);
262 action = action_create_new(C, oldact);
264 /* set this new action
265 * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
267 RNA_id_pointer_create(&action->id, &idptr);
268 RNA_property_pointer_set(&ptr, prop, idptr);
269 RNA_property_update(C, &ptr, prop);
272 /* set notifier that keyframes have changed */
273 WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
275 return OPERATOR_FINISHED;
278 void ACTION_OT_new(wmOperatorType *ot)
281 ot->name = "New Action";
282 ot->idname = "ACTION_OT_new";
283 ot->description = "Create new action";
286 ot->exec = action_new_exec;
287 ot->poll = action_new_poll;
290 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
293 /* ******************* Action Push-Down Operator ******************** */
296 * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
297 * 2) There must be an action active
298 * 3) The associated AnimData block must not be in tweakmode
300 static int action_pushdown_poll(bContext *C)
302 if (ED_operator_action_active(C)) {
303 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
304 AnimData *adt = ED_actedit_animdata_from_context(C);
306 /* Check for AnimData, Actions, and that tweakmode is off */
307 if (adt && saction->action) {
308 /* NOTE: We check this for the AnimData block in question and not the global flag,
309 * as the global flag may be left dirty by some of the browsing ops here.
311 if (!(adt->flag & ADT_NLA_EDIT_ON))
316 /* something failed... */
320 static int action_pushdown_exec(bContext *C, wmOperator *op)
322 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
323 AnimData *adt = ED_actedit_animdata_from_context(C);
327 /* Perform the pushdown operation
328 * - This will deal with all the AnimData-side usercounts
330 if (action_has_motion(adt->action) == 0) {
331 /* action may not be suitable... */
332 BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
333 return OPERATOR_CANCELLED;
336 /* action can be safely added */
337 BKE_nla_action_pushdown(adt);
340 /* Stop displaying this action in this editor
341 * NOTE: The editor itself doesn't set a user...
343 saction->action = NULL;
346 /* Send notifiers that stuff has changed */
347 WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
348 return OPERATOR_FINISHED;
351 void ACTION_OT_push_down(wmOperatorType *ot)
354 ot->name = "Push Down Action";
355 ot->idname = "ACTION_OT_push_down";
356 ot->description = "Push action down on to the NLA stack as a new strip";
359 ot->exec = action_pushdown_exec;
360 ot->poll = action_pushdown_poll;
363 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
366 /* ******************* Action Stash Operator ******************** */
368 static int action_stash_exec(bContext *C, wmOperator *op)
370 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
371 AnimData *adt = ED_actedit_animdata_from_context(C);
373 /* Perform stashing operation */
375 /* don't do anything if this action is empty... */
376 if (action_has_motion(adt->action) == 0) {
377 /* action may not be suitable... */
378 BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
379 return OPERATOR_CANCELLED;
382 /* stash the action */
383 if (BKE_nla_action_stash(adt)) {
384 /* The stash operation will remove the user already,
385 * so the flushing step later shouldn't double up
386 * the usercount fixes. Hence, we must unset this ref
387 * first before setting the new action.
389 saction->action = NULL;
392 /* action has already been added - simply warn about this, and clear */
393 BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
396 /* clear action refs from editor, and then also the backing data (not necessary) */
397 actedit_change_action(C, NULL);
401 /* Send notifiers that stuff has changed */
402 WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
403 return OPERATOR_FINISHED;
406 void ACTION_OT_stash(wmOperatorType *ot)
409 ot->name = "Stash Action";
410 ot->idname = "ACTION_OT_stash";
411 ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
414 ot->exec = action_stash_exec;
415 ot->poll = action_pushdown_poll;
418 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
421 ot->prop = RNA_def_boolean(ot->srna, "create_new", true, "Create New Action",
422 "Create a new action once the existing one has been safely stored");
425 /* ----------------- */
428 * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
429 * 2) The associated AnimData block must not be in tweakmode
431 static int action_stash_create_poll(bContext *C)
433 if (ED_operator_action_active(C)) {
434 AnimData *adt = ED_actedit_animdata_from_context(C);
436 /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
437 /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
439 if (!(adt->flag & ADT_NLA_EDIT_ON))
443 /* There may not be any action/animdata yet, so, just fallback to the global setting
444 * (which may not be totally valid yet if the action editor was used and things are
445 * now in an inconsistent state)
447 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
448 Scene *scene = CTX_data_scene(C);
450 if (!(scene->flag & SCE_NLA_EDIT_ON)) {
451 /* For now, actions are only for the active object, and on object and shapekey levels... */
452 return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
457 /* something failed... */
461 static int action_stash_create_exec(bContext *C, wmOperator *op)
463 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
464 AnimData *adt = ED_actedit_animdata_from_context(C);
466 /* Check for no action... */
467 if (saction->action == NULL) {
468 /* just create a new action */
469 bAction *action = action_create_new(C, NULL);
470 actedit_change_action(C, action);
473 /* Perform stashing operation */
474 if (action_has_motion(adt->action) == 0) {
475 /* don't do anything if this action is empty... */
476 BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
477 return OPERATOR_CANCELLED;
480 /* stash the action */
481 if (BKE_nla_action_stash(adt)) {
482 bAction *new_action = NULL;
484 /* create new action not based on the old one (since the "new" operator already does that) */
485 new_action = action_create_new(C, NULL);
487 /* The stash operation will remove the user already,
488 * so the flushing step later shouldn't double up
489 * the usercount fixes. Hence, we must unset this ref
490 * first before setting the new action.
492 saction->action = NULL;
493 actedit_change_action(C, new_action);
496 /* action has already been added - simply warn about this, and clear */
497 BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
498 actedit_change_action(C, NULL);
503 /* Send notifiers that stuff has changed */
504 WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
505 return OPERATOR_FINISHED;
508 void ACTION_OT_stash_and_create(wmOperatorType *ot)
511 ot->name = "Stash Action";
512 ot->idname = "ACTION_OT_stash_and_create";
513 ot->description = "Store this action in the NLA stack as a non-contributing strip for later use, and create a new action";
516 ot->exec = action_stash_create_exec;
517 ot->poll = action_stash_create_poll;
520 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
523 /* ************************************************************************** */
526 /* ******************* Action Unlink Operator ******************** */
527 /* We use a custom unlink operator here, as there are some technicalities which need special care:
528 * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action,
529 * or else, everything turns to custard.
530 * 2) If the Action doesn't have any other users, the user should at least get
531 * a warning that it is going to get lost.
532 * 3) We need a convenient way to exit Tweak Mode from the Action Editor
535 void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
537 ScrArea *sa = CTX_wm_area(C);
539 /* If the old action only has a single user (that it's about to lose),
542 * TODO: Maybe we should just save it for them? But then, there's the problem of
543 * trying to get rid of stuff that's actually unwanted!
545 if (act->id.us == 1) {
546 BKE_reportf(reports, RPT_WARNING,
547 "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
551 /* Clear Fake User and remove action stashing strip (if present) */
553 /* Remove stashed strip binding this action to this datablock */
554 /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
555 * but GE users only seem to use/care about single-object binding for now so this
559 NlaTrack *nlt, *nlt_next;
560 NlaStrip *strip, *nstrip;
562 for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
563 nlt_next = nlt->next;
565 if (strstr(nlt->name, DATA_("[Action Stash]"))) {
566 for (strip = nlt->strips.first; strip; strip = nstrip) {
567 nstrip = strip->next;
569 if (strip->act == act) {
570 /* Remove this strip, and the track too if it doesn't have anything else */
571 free_nlastrip(&nlt->strips, strip);
573 if (nlt->strips.first == NULL) {
574 BLI_assert(nstrip == NULL);
575 free_nlatrack(&adt->nla_tracks, nlt);
583 /* Clear Fake User */
584 id_fake_user_clear(&act->id);
587 /* If in Tweak Mode, don't unlink. Instead, this
588 * becomes a shortcut to exit Tweak Mode instead
590 if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
591 /* Exit Tweak Mode */
592 BKE_nla_tweakmode_exit(adt);
594 /* Flush this to the Action Editor (if that's where this change was initiated) */
595 if (sa->spacetype == SPACE_ACTION) {
596 actedit_change_action(C, NULL);
600 /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
601 if (sa->spacetype == SPACE_ACTION) {
602 /* clear action editor -> action */
603 actedit_change_action(C, NULL);
606 /* clear AnimData -> action */
610 /* create AnimData RNA pointers */
611 RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
612 prop = RNA_struct_find_property(&ptr, "action");
615 RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL);
616 RNA_property_update(C, &ptr, prop);
621 /* -------------------------- */
623 static int action_unlink_poll(bContext *C)
625 if (ED_operator_action_active(C)) {
626 SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
627 AnimData *adt = ED_actedit_animdata_from_context(C);
629 /* Only when there's an active action, in the right modes... */
630 if (saction->action && adt)
634 /* something failed... */
638 static int action_unlink_exec(bContext *C, wmOperator *op)
640 AnimData *adt = ED_actedit_animdata_from_context(C);
641 bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
643 if (adt && adt->action) {
644 ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
647 return OPERATOR_FINISHED;
650 static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
652 /* NOTE: this is hardcoded to match the behaviour for the unlink button (in interface_templates.c) */
653 RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
654 return action_unlink_exec(C, op);
657 void ACTION_OT_unlink(wmOperatorType *ot)
662 ot->name = "Unlink Action";
663 ot->idname = "ACTION_OT_unlink";
664 ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
667 ot->invoke = action_unlink_invoke;
668 ot->exec = action_unlink_exec;
669 ot->poll = action_unlink_poll;
672 prop = RNA_def_boolean(ot->srna, "force_delete", false, "Force Delete",
673 "Clear Fake User and remove copy stashed in this datablock's NLA stack");
674 RNA_def_property_flag(prop, PROP_SKIP_SAVE);
677 /* ************************************************************************** */
678 /* ACTION BROWSING */
680 /* Try to find NLA Strip to use for action layer up/down tool */
681 static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
685 for (strip = strips->first; strip; strip = strip->next) {
686 /* Can we use this? */
687 if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
688 /* in range - use this one */
691 else if ((ctime < strip->start) && (strip->prev == NULL)) {
692 /* before first - use this one */
695 else if ((ctime > strip->end) && (strip->next == NULL)) {
696 /* after last - use this one */
701 /* nothing suitable found... */
705 /* Switch NLA Strips/Actions */
706 static void action_layer_switch_strip(AnimData *adt,
707 NlaTrack *old_track, NlaStrip *old_strip,
708 NlaTrack *nlt, NlaStrip *strip)
710 /* Exit tweakmode on old strip
711 * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it
713 BKE_nla_tweakmode_exit(adt);
716 old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
719 old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
722 /* Make this one the active one instead */
723 strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
724 nlt->flag |= NLATRACK_ACTIVE;
726 /* Copy over "solo" flag - This is useful for stashed actions... */
728 if (old_track->flag & NLATRACK_SOLO) {
729 old_track->flag &= ~NLATRACK_SOLO;
730 nlt->flag |= NLATRACK_SOLO;
734 /* NLA muting <==> Solo Tracks */
735 if (adt->flag & ADT_NLA_EVAL_OFF) {
736 /* disable NLA muting */
737 adt->flag &= ~ADT_NLA_EVAL_OFF;
739 /* mark this track as being solo */
740 adt->flag |= ADT_NLA_SOLO_TRACK;
741 nlt->flag |= NLATRACK_SOLO;
743 // TODO: Needs restpose flushing (when we get reference track)
747 /* Enter tweakmode again - hopefully we're now "it" */
748 BKE_nla_tweakmode_enter(adt);
749 BLI_assert(adt->actstrip == strip);
752 /* ********************** One Layer Up Operator ************************** */
754 static int action_layer_next_poll(bContext *C)
756 /* Action Editor's action editing modes only */
757 if (ED_operator_action_active(C)) {
758 AnimData *adt = ED_actedit_animdata_from_context(C);
760 /* only allow if we're in tweakmode, and there's something above us... */
761 if (adt->flag & ADT_NLA_EDIT_ON) {
762 /* We need to check if there are any tracks above the active one
763 * since the track the action comes from is not stored in AnimData
765 if (adt->nla_tracks.last) {
766 NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
768 if (nlt->flag & NLATRACK_DISABLED) {
769 /* A disabled track will either be the track itself,
770 * or one of the ones above it.
772 * If this is the top-most one, there is the possibility
773 * that there is no active action. For now, we let this
774 * case return true too, so that there is a natural way
775 * to "move to an empty layer", even though this means
776 * that we won't actually have an action.
778 // return (adt->tmpact != NULL);
786 /* something failed... */
790 static int action_layer_next_exec(bContext *C, wmOperator *op)
792 AnimData *adt = ED_actedit_animdata_from_context(C);
795 Scene *scene = CTX_data_scene(C);
796 float ctime = BKE_scene_frame_get(scene);
798 /* Get active track */
799 act_track = BKE_nlatrack_find_tweaked(adt);
801 if (act_track == NULL) {
802 BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
803 return OPERATOR_CANCELLED;
806 /* Find next action, and hook it up */
807 if (act_track->next) {
810 /* Find next action to use */
811 for (nlt = act_track->next; nlt; nlt = nlt->next) {
812 NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
815 action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
821 /* No more actions (strips) - Go back to editing the original active action
822 * NOTE: This will mean exiting tweakmode...
824 BKE_nla_tweakmode_exit(adt);
826 /* Deal with solo flags...
827 * Assume: Solo Track == NLA Muting
829 if (adt->flag & ADT_NLA_SOLO_TRACK) {
830 /* turn off solo flags on tracks */
831 act_track->flag &= ~NLATRACK_SOLO;
832 adt->flag &= ~ADT_NLA_SOLO_TRACK;
834 /* turn on NLA muting (to keep same effect) */
835 adt->flag |= ADT_NLA_EVAL_OFF;
837 // TODO: Needs restpose flushing (when we get reference track)
841 /* Update the action that this editor now uses
842 * NOTE: The calls above have already handled the usercount/animdata side of things
844 actedit_change_action(C, adt->action);
845 return OPERATOR_FINISHED;
848 void ACTION_OT_layer_next(wmOperatorType *ot)
851 ot->name = "Next Layer";
852 ot->idname = "ACTION_OT_layer_next";
853 ot->description = "Switch to editing action in animation layer above the current action in the NLA Stack";
856 ot->exec = action_layer_next_exec;
857 ot->poll = action_layer_next_poll;
860 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
863 /* ********************* One Layer Down Operator ************************* */
865 static int action_layer_prev_poll(bContext *C)
867 /* Action Editor's action editing modes only */
868 if (ED_operator_action_active(C)) {
869 AnimData *adt = ED_actedit_animdata_from_context(C);
871 if (adt->flag & ADT_NLA_EDIT_ON) {
872 /* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */
873 if (adt->nla_tracks.first) {
874 NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
876 /* Since the first disabled track is the track being tweaked/edited,
877 * we can simplify things by only checking the first track:
878 * - If it is disabled, this is the track being tweaked,
879 * so there can't be anything below it
880 * - Otherwise, there is at least 1 track below the tweaking
881 * track that we can descend to
883 if ((nlt->flag & NLATRACK_DISABLED) == 0) {
884 /* not disabled = there are actions below the one being tweaked */
890 /* Normal Mode: If there are any tracks, we can try moving to those */
891 return (adt->nla_tracks.first != NULL);
896 /* something failed... */
900 static int action_layer_prev_exec(bContext *C, wmOperator *op)
902 AnimData *adt = ED_actedit_animdata_from_context(C);
906 Scene *scene = CTX_data_scene(C);
907 float ctime = BKE_scene_frame_get(scene);
911 BKE_report(op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
912 return OPERATOR_CANCELLED;
915 /* Get active track */
916 act_track = BKE_nlatrack_find_tweaked(adt);
918 /* If there is no active track, that means we are using the active action... */
920 /* Active Track - Start from the one below it */
921 nlt = act_track->prev;
924 /* Active Action - Use the top-most track */
925 nlt = adt->nla_tracks.last;
928 /* Find previous action and hook it up */
929 for (; nlt; nlt = nlt->prev) {
930 NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
933 action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
938 /* Update the action that this editor now uses
939 * NOTE: The calls above have already handled the usercount/animdata side of things
941 actedit_change_action(C, adt->action);
942 return OPERATOR_FINISHED;
945 void ACTION_OT_layer_prev(wmOperatorType *ot)
948 ot->name = "Previous Layer";
949 ot->idname = "ACTION_OT_layer_prev";
950 ot->description = "Switch to editing action in animation layer below the current action in the NLA Stack";
953 ot->exec = action_layer_prev_exec;
954 ot->poll = action_layer_prev_poll;
957 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
960 /* ************************************************************************** */