Cleanup: Sort node type definitions alphabetically
[blender.git] / source / blender / editors / space_action / action_data.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2015 Blender Foundation
17  * This is a new part of Blender
18  */
19
20 /** \file
21  * \ingroup spaction
22  */
23
24 #include <float.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "BLI_utildefines.h"
30
31 #include "BLT_translation.h"
32
33 #include "DNA_anim_types.h"
34 #include "DNA_gpencil_types.h"
35 #include "DNA_key_types.h"
36 #include "DNA_mask_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39
40 #include "RNA_access.h"
41 #include "RNA_define.h"
42 #include "RNA_enum_types.h"
43
44 #include "BKE_action.h"
45 #include "BKE_context.h"
46 #include "BKE_fcurve.h"
47 #include "BKE_key.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_nla.h"
50 #include "BKE_report.h"
51 #include "BKE_scene.h"
52
53 #include "UI_view2d.h"
54
55 #include "ED_anim_api.h"
56 #include "ED_gpencil.h"
57 #include "ED_keyframes_edit.h"
58 #include "ED_keyframing.h"
59 #include "ED_markers.h"
60 #include "ED_mask.h"
61 #include "ED_screen.h"
62
63 #include "WM_api.h"
64 #include "WM_types.h"
65
66 #include "UI_interface.h"
67
68 #include "action_intern.h"
69
70 /* ************************************************************************** */
71 /* ACTION CREATION */
72
73 /* Helper function to find the active AnimData block from the Action Editor context */
74 AnimData *ED_actedit_animdata_from_context(bContext *C)
75 {
76   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
77   Object *ob = CTX_data_active_object(C);
78   AnimData *adt = NULL;
79
80   /* Get AnimData block to use */
81   if (saction->mode == SACTCONT_ACTION) {
82     /* Currently, "Action Editor" means object-level only... */
83     if (ob) {
84       adt = ob->adt;
85     }
86   }
87   else if (saction->mode == SACTCONT_SHAPEKEY) {
88     Key *key = BKE_key_from_object(ob);
89     if (key) {
90       adt = key->adt;
91     }
92   }
93
94   return adt;
95 }
96
97 /* -------------------------------------------------------------------- */
98
99 /* Create new action */
100 static bAction *action_create_new(bContext *C, bAction *oldact)
101 {
102   ScrArea *area = CTX_wm_area(C);
103   bAction *action;
104
105   /* create action - the way to do this depends on whether we've got an
106    * existing one there already, in which case we make a copy of it
107    * (which is useful for "versioning" actions within the same file)
108    */
109   if (oldact && GS(oldact->id.name) == ID_AC) {
110     /* make a copy of the existing action */
111     action = (bAction *)BKE_id_copy(CTX_data_main(C), &oldact->id);
112   }
113   else {
114     /* just make a new (empty) action */
115     action = BKE_action_add(CTX_data_main(C), "Action");
116   }
117
118   /* when creating new ID blocks, there is already 1 user (as for all new datablocks),
119    * but the RNA pointer code will assign all the proper users instead, so we compensate
120    * for that here
121    */
122   BLI_assert(action->id.us == 1);
123   id_us_min(&action->id);
124
125   /* set ID-Root type */
126   if (area->spacetype == SPACE_ACTION) {
127     SpaceAction *saction = (SpaceAction *)area->spacedata.first;
128
129     if (saction->mode == SACTCONT_SHAPEKEY) {
130       action->idroot = ID_KE;
131     }
132     else {
133       action->idroot = ID_OB;
134     }
135   }
136
137   return action;
138 }
139
140 /* Change the active action used by the action editor */
141 static void actedit_change_action(bContext *C, bAction *act)
142 {
143   bScreen *screen = CTX_wm_screen(C);
144   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
145
146   PointerRNA ptr, idptr;
147   PropertyRNA *prop;
148
149   /* create RNA pointers and get the property */
150   RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
151   prop = RNA_struct_find_property(&ptr, "action");
152
153   /* NOTE: act may be NULL here, so better to just use a cast here */
154   RNA_id_pointer_create((ID *)act, &idptr);
155
156   /* set the new pointer, and force a refresh */
157   RNA_property_pointer_set(&ptr, prop, idptr, NULL);
158   RNA_property_update(C, &ptr, prop);
159 }
160
161 /* ******************** New Action Operator *********************** */
162
163 /* Criteria:
164  *  1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
165  *        OR
166  *     The NLA Editor is active (i.e. Animation Data panel -> new action)
167  *  2) The associated AnimData block must not be in tweak-mode.
168  */
169 static bool action_new_poll(bContext *C)
170 {
171   Scene *scene = CTX_data_scene(C);
172
173   /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
174   /* NOTE: unlike for pushdown,
175    * this operator needs to be run when creating an action from nothing... */
176   if (ED_operator_action_active(C)) {
177     SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
178     Object *ob = CTX_data_active_object(C);
179
180     /* For now, actions are only for the active object, and on object and shapekey levels... */
181     if (saction->mode == SACTCONT_ACTION) {
182       /* XXX: This assumes that actions are assigned to the active object in this mode */
183       if (ob) {
184         if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0) {
185           return true;
186         }
187       }
188     }
189     else if (saction->mode == SACTCONT_SHAPEKEY) {
190       Key *key = BKE_key_from_object(ob);
191       if (key) {
192         if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0) {
193           return true;
194         }
195       }
196     }
197   }
198   else if (ED_operator_nla_active(C)) {
199     if (!(scene->flag & SCE_NLA_EDIT_ON)) {
200       return true;
201     }
202   }
203
204   /* something failed... */
205   return false;
206 }
207
208 static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
209 {
210   PointerRNA ptr, idptr;
211   PropertyRNA *prop;
212
213   bAction *oldact = NULL;
214   AnimData *adt = NULL;
215   /* hook into UI */
216   UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
217
218   if (prop) {
219     /* The operator was called from a button. */
220     PointerRNA oldptr;
221
222     oldptr = RNA_property_pointer_get(&ptr, prop);
223     oldact = (bAction *)oldptr.owner_id;
224
225     /* stash the old action to prevent it from being lost */
226     if (ptr.type == &RNA_AnimData) {
227       adt = ptr.data;
228     }
229     else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
230       adt = ED_actedit_animdata_from_context(C);
231     }
232   }
233   else {
234     adt = ED_actedit_animdata_from_context(C);
235     oldact = adt->action;
236   }
237   {
238     bAction *action = NULL;
239
240     /* Perform stashing operation - But only if there is an action */
241     if (adt && oldact) {
242       /* stash the action */
243       if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ptr.owner_id))) {
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!
250          */
251         if (ptr.type == &RNA_SpaceDopeSheetEditor) {
252           SpaceAction *saction = ptr.data;
253           saction->action = NULL;
254         }
255       }
256       else {
257 #if 0
258         printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n",
259                oldact->id.name);
260 #endif
261       }
262     }
263
264     /* create action */
265     action = action_create_new(C, oldact);
266
267     if (prop) {
268       /* set this new action
269        * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
270        */
271       RNA_id_pointer_create(&action->id, &idptr);
272       RNA_property_pointer_set(&ptr, prop, idptr, NULL);
273       RNA_property_update(C, &ptr, prop);
274     }
275   }
276
277   /* set notifier that keyframes have changed */
278   WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
279
280   return OPERATOR_FINISHED;
281 }
282
283 void ACTION_OT_new(wmOperatorType *ot)
284 {
285   /* identifiers */
286   ot->name = "New Action";
287   ot->idname = "ACTION_OT_new";
288   ot->description = "Create new action";
289
290   /* api callbacks */
291   ot->exec = action_new_exec;
292   ot->poll = action_new_poll;
293
294   /* flags */
295   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
296 }
297
298 /* ******************* Action Push-Down Operator ******************** */
299
300 /* Criteria:
301  *  1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
302  *  2) There must be an action active
303  *  3) The associated AnimData block must not be in tweak-mode
304  */
305 static bool action_pushdown_poll(bContext *C)
306 {
307   if (ED_operator_action_active(C)) {
308     SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
309     AnimData *adt = ED_actedit_animdata_from_context(C);
310
311     /* Check for AnimData, Actions, and that tweak-mode is off. */
312     if (adt && saction->action) {
313       /* NOTE: We check this for the AnimData block in question and not the global flag,
314        *       as the global flag may be left dirty by some of the browsing ops here.
315        */
316       if (!(adt->flag & ADT_NLA_EDIT_ON)) {
317         return true;
318       }
319     }
320   }
321
322   /* something failed... */
323   return false;
324 }
325
326 static int action_pushdown_exec(bContext *C, wmOperator *op)
327 {
328   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
329   AnimData *adt = ED_actedit_animdata_from_context(C);
330
331   /* Do the deed... */
332   if (adt) {
333     /* Perform the push-down operation
334      * - This will deal with all the AnimData-side user-counts. */
335     if (action_has_motion(adt->action) == 0) {
336       /* action may not be suitable... */
337       BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
338       return OPERATOR_CANCELLED;
339     }
340
341     /* action can be safely added */
342     const Object *ob = CTX_data_active_object(C);
343     BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(ob));
344
345     /* Stop displaying this action in this editor
346      * NOTE: The editor itself doesn't set a user...
347      */
348     saction->action = NULL;
349   }
350
351   /* Send notifiers that stuff has changed */
352   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
353   return OPERATOR_FINISHED;
354 }
355
356 void ACTION_OT_push_down(wmOperatorType *ot)
357 {
358   /* identifiers */
359   ot->name = "Push Down Action";
360   ot->idname = "ACTION_OT_push_down";
361   ot->description = "Push action down on to the NLA stack as a new strip";
362
363   /* callbacks */
364   ot->exec = action_pushdown_exec;
365   ot->poll = action_pushdown_poll;
366
367   /* flags */
368   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
369 }
370
371 /* ******************* Action Stash Operator ******************** */
372
373 static int action_stash_exec(bContext *C, wmOperator *op)
374 {
375   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
376   AnimData *adt = ED_actedit_animdata_from_context(C);
377
378   /* Perform stashing operation */
379   if (adt) {
380     /* don't do anything if this action is empty... */
381     if (action_has_motion(adt->action) == 0) {
382       /* action may not be suitable... */
383       BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
384       return OPERATOR_CANCELLED;
385     }
386
387     /* stash the action */
388     Object *ob = CTX_data_active_object(C);
389     if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) {
390       /* The stash operation will remove the user already,
391        * so the flushing step later shouldn't double up
392        * the user-count fixes. Hence, we must unset this ref
393        * first before setting the new action.
394        */
395       saction->action = NULL;
396     }
397     else {
398       /* action has already been added - simply warn about this, and clear */
399       BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
400     }
401
402     /* clear action refs from editor, and then also the backing data (not necessary) */
403     actedit_change_action(C, NULL);
404   }
405
406   /* Send notifiers that stuff has changed */
407   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
408   return OPERATOR_FINISHED;
409 }
410
411 void ACTION_OT_stash(wmOperatorType *ot)
412 {
413   /* identifiers */
414   ot->name = "Stash Action";
415   ot->idname = "ACTION_OT_stash";
416   ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
417
418   /* callbacks */
419   ot->exec = action_stash_exec;
420   ot->poll = action_pushdown_poll;
421
422   /* flags */
423   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
424
425   /* properties */
426   ot->prop = RNA_def_boolean(ot->srna,
427                              "create_new",
428                              true,
429                              "Create New Action",
430                              "Create a new action once the existing one has been safely stored");
431 }
432
433 /* ----------------- */
434
435 /* Criteria:
436  *  1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
437  *  2) The associated AnimData block must not be in tweak-mode
438  */
439 static bool action_stash_create_poll(bContext *C)
440 {
441   if (ED_operator_action_active(C)) {
442     AnimData *adt = ED_actedit_animdata_from_context(C);
443
444     /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
445     /* NOTE: unlike for pushdown,
446      * this operator needs to be run when creating an action from nothing... */
447     if (adt) {
448       if (!(adt->flag & ADT_NLA_EDIT_ON)) {
449         return true;
450       }
451     }
452     else {
453       /* There may not be any action/animdata yet, so, just fallback to the global setting
454        * (which may not be totally valid yet if the action editor was used and things are
455        * now in an inconsistent state)
456        */
457       SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
458       Scene *scene = CTX_data_scene(C);
459
460       if (!(scene->flag & SCE_NLA_EDIT_ON)) {
461         /* For now, actions are only for the active object, and on object and shapekey levels... */
462         return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
463       }
464     }
465   }
466
467   /* something failed... */
468   return false;
469 }
470
471 static int action_stash_create_exec(bContext *C, wmOperator *op)
472 {
473   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
474   AnimData *adt = ED_actedit_animdata_from_context(C);
475
476   /* Check for no action... */
477   if (saction->action == NULL) {
478     /* just create a new action */
479     bAction *action = action_create_new(C, NULL);
480     actedit_change_action(C, action);
481   }
482   else if (adt) {
483     /* Perform stashing operation */
484     if (action_has_motion(adt->action) == 0) {
485       /* don't do anything if this action is empty... */
486       BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
487       return OPERATOR_CANCELLED;
488     }
489
490     /* stash the action */
491     Object *ob = CTX_data_active_object(C);
492     if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(ob))) {
493       bAction *new_action = NULL;
494
495       /* Create new action not based on the old one
496        * (since the "new" operator already does that). */
497       new_action = action_create_new(C, NULL);
498
499       /* The stash operation will remove the user already,
500        * so the flushing step later shouldn't double up
501        * the user-count fixes. Hence, we must unset this ref
502        * first before setting the new action.
503        */
504       saction->action = NULL;
505       actedit_change_action(C, new_action);
506     }
507     else {
508       /* action has already been added - simply warn about this, and clear */
509       BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
510       actedit_change_action(C, NULL);
511     }
512   }
513
514   /* Send notifiers that stuff has changed */
515   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
516   return OPERATOR_FINISHED;
517 }
518
519 void ACTION_OT_stash_and_create(wmOperatorType *ot)
520 {
521   /* identifiers */
522   ot->name = "Stash Action";
523   ot->idname = "ACTION_OT_stash_and_create";
524   ot->description =
525       "Store this action in the NLA stack as a non-contributing strip for later use, and create a "
526       "new action";
527
528   /* callbacks */
529   ot->exec = action_stash_create_exec;
530   ot->poll = action_stash_create_poll;
531
532   /* flags */
533   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
534 }
535
536 /* ************************************************************************** */
537 /* ACTION UNLINK */
538
539 /* ******************* Action Unlink Operator ******************** */
540 /* We use a custom unlink operator here, as there are some technicalities which need special care:
541  * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action,
542  *    or else, everything turns to custard.
543  * 2) If the Action doesn't have any other users, the user should at least get
544  *    a warning that it is going to get lost.
545  * 3) We need a convenient way to exit Tweak Mode from the Action Editor
546  */
547
548 void ED_animedit_unlink_action(
549     bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
550 {
551   ScrArea *area = CTX_wm_area(C);
552
553   /* If the old action only has a single user (that it's about to lose),
554    * warn user about it
555    *
556    * TODO: Maybe we should just save it for them? But then, there's the problem of
557    *       trying to get rid of stuff that's actually unwanted!
558    */
559   if (act->id.us == 1) {
560     BKE_reportf(reports,
561                 RPT_WARNING,
562                 "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
563                 act->id.name + 2);
564   }
565
566   /* Clear Fake User and remove action stashing strip (if present) */
567   if (force_delete) {
568     /* Remove stashed strip binding this action to this datablock */
569     /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
570      * but GE users only seem to use/care about single-object binding for now so this
571      * should be fine
572      */
573     if (adt) {
574       NlaTrack *nlt, *nlt_next;
575       NlaStrip *strip, *nstrip;
576
577       for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
578         nlt_next = nlt->next;
579
580         if (strstr(nlt->name, DATA_("[Action Stash]"))) {
581           for (strip = nlt->strips.first; strip; strip = nstrip) {
582             nstrip = strip->next;
583
584             if (strip->act == act) {
585               /* Remove this strip, and the track too if it doesn't have anything else */
586               BKE_nlastrip_free(&nlt->strips, strip, true);
587
588               if (nlt->strips.first == NULL) {
589                 BLI_assert(nstrip == NULL);
590                 BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
591               }
592             }
593           }
594         }
595       }
596     }
597
598     /* Clear Fake User */
599     id_fake_user_clear(&act->id);
600   }
601
602   /* If in Tweak Mode, don't unlink. Instead, this
603    * becomes a shortcut to exit Tweak Mode instead
604    */
605   if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
606     /* Exit Tweak Mode */
607     BKE_nla_tweakmode_exit(adt);
608
609     /* Flush this to the Action Editor (if that's where this change was initiated) */
610     if (area->spacetype == SPACE_ACTION) {
611       actedit_change_action(C, NULL);
612     }
613   }
614   else {
615     /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
616     if (area->spacetype == SPACE_ACTION) {
617       /* clear action editor -> action */
618       actedit_change_action(C, NULL);
619     }
620     else {
621       /* clear AnimData -> action */
622       PointerRNA ptr;
623       PropertyRNA *prop;
624
625       /* create AnimData RNA pointers */
626       RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
627       prop = RNA_struct_find_property(&ptr, "action");
628
629       /* clear... */
630       RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL, NULL);
631       RNA_property_update(C, &ptr, prop);
632     }
633   }
634 }
635
636 /* -------------------------- */
637
638 static bool action_unlink_poll(bContext *C)
639 {
640   if (ED_operator_action_active(C)) {
641     SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
642     AnimData *adt = ED_actedit_animdata_from_context(C);
643
644     /* Only when there's an active action, in the right modes... */
645     if (saction->action && adt) {
646       return true;
647     }
648   }
649
650   /* something failed... */
651   return false;
652 }
653
654 static int action_unlink_exec(bContext *C, wmOperator *op)
655 {
656   AnimData *adt = ED_actedit_animdata_from_context(C);
657   bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
658
659   if (adt && adt->action) {
660     ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
661   }
662
663   return OPERATOR_FINISHED;
664 }
665
666 static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
667 {
668   /* NOTE: this is hardcoded to match the behavior for the unlink button
669    * (in interface_templates.c). */
670   RNA_boolean_set(op->ptr, "force_delete", event->shift != 0);
671   return action_unlink_exec(C, op);
672 }
673
674 void ACTION_OT_unlink(wmOperatorType *ot)
675 {
676   PropertyRNA *prop;
677
678   /* identifiers */
679   ot->name = "Unlink Action";
680   ot->idname = "ACTION_OT_unlink";
681   ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
682
683   /* callbacks */
684   ot->invoke = action_unlink_invoke;
685   ot->exec = action_unlink_exec;
686   ot->poll = action_unlink_poll;
687
688   /* properties */
689   prop = RNA_def_boolean(ot->srna,
690                          "force_delete",
691                          false,
692                          "Force Delete",
693                          "Clear Fake User and remove "
694                          "copy stashed in this data-block's NLA stack");
695   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
696 }
697
698 /* ************************************************************************** */
699 /* ACTION BROWSING */
700
701 /* Try to find NLA Strip to use for action layer up/down tool */
702 static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
703 {
704   NlaStrip *strip;
705
706   for (strip = strips->first; strip; strip = strip->next) {
707     /* Can we use this? */
708     if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
709       /* in range - use this one */
710       return strip;
711     }
712     if ((ctime < strip->start) && (strip->prev == NULL)) {
713       /* before first - use this one */
714       return strip;
715     }
716     if ((ctime > strip->end) && (strip->next == NULL)) {
717       /* after last - use this one */
718       return strip;
719     }
720   }
721
722   /* nothing suitable found... */
723   return NULL;
724 }
725
726 /* Switch NLA Strips/Actions  */
727 static void action_layer_switch_strip(
728     AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip)
729 {
730   /* Exit tweak-mode on old strip
731    * NOTE: We need to manually clear this stuff ourselves, as tweak-mode exit doesn't do it
732    */
733   BKE_nla_tweakmode_exit(adt);
734
735   if (old_strip) {
736     old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
737   }
738   if (old_track) {
739     old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
740   }
741
742   /* Make this one the active one instead */
743   strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
744   nlt->flag |= NLATRACK_ACTIVE;
745
746   /* Copy over "solo" flag - This is useful for stashed actions... */
747   if (old_track) {
748     if (old_track->flag & NLATRACK_SOLO) {
749       old_track->flag &= ~NLATRACK_SOLO;
750       nlt->flag |= NLATRACK_SOLO;
751     }
752   }
753   else {
754     /* NLA muting <==> Solo Tracks */
755     if (adt->flag & ADT_NLA_EVAL_OFF) {
756       /* disable NLA muting */
757       adt->flag &= ~ADT_NLA_EVAL_OFF;
758
759       /* mark this track as being solo */
760       adt->flag |= ADT_NLA_SOLO_TRACK;
761       nlt->flag |= NLATRACK_SOLO;
762
763       /* TODO: Needs rest-pose flushing (when we get reference track) */
764     }
765   }
766
767   /* Enter tweak-mode again - hopefully we're now "it" */
768   BKE_nla_tweakmode_enter(adt);
769   BLI_assert(adt->actstrip == strip);
770 }
771
772 /* ********************** One Layer Up Operator ************************** */
773
774 static bool action_layer_next_poll(bContext *C)
775 {
776   /* Action Editor's action editing modes only */
777   if (ED_operator_action_active(C)) {
778     AnimData *adt = ED_actedit_animdata_from_context(C);
779     if (adt) {
780       /* only allow if we're in tweak-mode, and there's something above us... */
781       if (adt->flag & ADT_NLA_EDIT_ON) {
782         /* We need to check if there are any tracks above the active one
783          * since the track the action comes from is not stored in AnimData
784          */
785         if (adt->nla_tracks.last) {
786           NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
787
788           if (nlt->flag & NLATRACK_DISABLED) {
789             /* A disabled track will either be the track itself,
790              * or one of the ones above it.
791              *
792              * If this is the top-most one, there is the possibility
793              * that there is no active action. For now, we let this
794              * case return true too, so that there is a natural way
795              * to "move to an empty layer", even though this means
796              * that we won't actually have an action.
797              */
798             // return (adt->tmpact != NULL);
799             return true;
800           }
801         }
802       }
803     }
804   }
805
806   /* something failed... */
807   return false;
808 }
809
810 static int action_layer_next_exec(bContext *C, wmOperator *op)
811 {
812   AnimData *adt = ED_actedit_animdata_from_context(C);
813   NlaTrack *act_track;
814
815   Scene *scene = CTX_data_scene(C);
816   float ctime = BKE_scene_frame_get(scene);
817
818   /* Get active track */
819   act_track = BKE_nlatrack_find_tweaked(adt);
820
821   if (act_track == NULL) {
822     BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
823     return OPERATOR_CANCELLED;
824   }
825
826   /* Find next action, and hook it up */
827   if (act_track->next) {
828     NlaTrack *nlt;
829
830     /* Find next action to use */
831     for (nlt = act_track->next; nlt; nlt = nlt->next) {
832       NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
833
834       if (strip) {
835         action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
836         break;
837       }
838     }
839   }
840   else {
841     /* No more actions (strips) - Go back to editing the original active action
842      * NOTE: This will mean exiting tweak-mode...
843      */
844     BKE_nla_tweakmode_exit(adt);
845
846     /* Deal with solo flags...
847      * Assume: Solo Track == NLA Muting
848      */
849     if (adt->flag & ADT_NLA_SOLO_TRACK) {
850       /* turn off solo flags on tracks */
851       act_track->flag &= ~NLATRACK_SOLO;
852       adt->flag &= ~ADT_NLA_SOLO_TRACK;
853
854       /* turn on NLA muting (to keep same effect) */
855       adt->flag |= ADT_NLA_EVAL_OFF;
856
857       /* TODO: Needs rest-pose flushing (when we get reference track) */
858     }
859   }
860
861   /* Update the action that this editor now uses
862    * NOTE: The calls above have already handled the user-count/anim-data side of things. */
863   actedit_change_action(C, adt->action);
864   return OPERATOR_FINISHED;
865 }
866
867 void ACTION_OT_layer_next(wmOperatorType *ot)
868 {
869   /* identifiers */
870   ot->name = "Next Layer";
871   ot->idname = "ACTION_OT_layer_next";
872   ot->description =
873       "Switch to editing action in animation layer above the current action in the NLA Stack";
874
875   /* callbacks */
876   ot->exec = action_layer_next_exec;
877   ot->poll = action_layer_next_poll;
878
879   /* flags */
880   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
881 }
882
883 /* ********************* One Layer Down Operator ************************* */
884
885 static bool action_layer_prev_poll(bContext *C)
886 {
887   /* Action Editor's action editing modes only */
888   if (ED_operator_action_active(C)) {
889     AnimData *adt = ED_actedit_animdata_from_context(C);
890     if (adt) {
891       if (adt->flag & ADT_NLA_EDIT_ON) {
892         /* Tweak Mode: We need to check if there are any tracks below the active one
893          * that we can move to */
894         if (adt->nla_tracks.first) {
895           NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
896
897           /* Since the first disabled track is the track being tweaked/edited,
898            * we can simplify things by only checking the first track:
899            *    - If it is disabled, this is the track being tweaked,
900            *      so there can't be anything below it
901            *    - Otherwise, there is at least 1 track below the tweaking
902            *      track that we can descend to
903            */
904           if ((nlt->flag & NLATRACK_DISABLED) == 0) {
905             /* not disabled = there are actions below the one being tweaked */
906             return true;
907           }
908         }
909       }
910       else {
911         /* Normal Mode: If there are any tracks, we can try moving to those */
912         return (adt->nla_tracks.first != NULL);
913       }
914     }
915   }
916
917   /* something failed... */
918   return false;
919 }
920
921 static int action_layer_prev_exec(bContext *C, wmOperator *op)
922 {
923   AnimData *adt = ED_actedit_animdata_from_context(C);
924   NlaTrack *act_track;
925   NlaTrack *nlt;
926
927   Scene *scene = CTX_data_scene(C);
928   float ctime = BKE_scene_frame_get(scene);
929
930   /* Sanity Check */
931   if (adt == NULL) {
932     BKE_report(
933         op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
934     return OPERATOR_CANCELLED;
935   }
936
937   /* Get active track */
938   act_track = BKE_nlatrack_find_tweaked(adt);
939
940   /* If there is no active track, that means we are using the active action... */
941   if (act_track) {
942     /* Active Track - Start from the one below it */
943     nlt = act_track->prev;
944   }
945   else {
946     /* Active Action - Use the top-most track */
947     nlt = adt->nla_tracks.last;
948   }
949
950   /* Find previous action and hook it up */
951   for (; nlt; nlt = nlt->prev) {
952     NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
953
954     if (strip) {
955       action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
956       break;
957     }
958   }
959
960   /* Update the action that this editor now uses
961    * NOTE: The calls above have already handled the user-count/animdata side of things. */
962   actedit_change_action(C, adt->action);
963   return OPERATOR_FINISHED;
964 }
965
966 void ACTION_OT_layer_prev(wmOperatorType *ot)
967 {
968   /* identifiers */
969   ot->name = "Previous Layer";
970   ot->idname = "ACTION_OT_layer_prev";
971   ot->description =
972       "Switch to editing action in animation layer below the current action in the NLA Stack";
973
974   /* callbacks */
975   ot->exec = action_layer_prev_exec;
976   ot->poll = action_layer_prev_poll;
977
978   /* flags */
979   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
980 }
981
982 /* ************************************************************************** */