CMake: add WITH_LINKER_LLD option for unix platforms
[blender-staging.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 = BKE_action_copy(CTX_data_main(C), oldact);
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 tweakmode
168  */
169 static bool action_new_poll(bContext *C)
170 {
171   Scene *scene = CTX_data_scene(C);
172
173   /* Check tweakmode 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)) {
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 tweakmode
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 tweakmode 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 pushdown operation
334      * - This will deal with all the AnimData-side usercounts
335      */
336     if (action_has_motion(adt->action) == 0) {
337       /* action may not be suitable... */
338       BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
339       return OPERATOR_CANCELLED;
340     }
341     else {
342       /* action can be safely added */
343       BKE_nla_action_pushdown(adt);
344     }
345
346     /* Stop displaying this action in this editor
347      * NOTE: The editor itself doesn't set a user...
348      */
349     saction->action = NULL;
350   }
351
352   /* Send notifiers that stuff has changed */
353   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
354   return OPERATOR_FINISHED;
355 }
356
357 void ACTION_OT_push_down(wmOperatorType *ot)
358 {
359   /* identifiers */
360   ot->name = "Push Down Action";
361   ot->idname = "ACTION_OT_push_down";
362   ot->description = "Push action down on to the NLA stack as a new strip";
363
364   /* callbacks */
365   ot->exec = action_pushdown_exec;
366   ot->poll = action_pushdown_poll;
367
368   /* flags */
369   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
370 }
371
372 /* ******************* Action Stash Operator ******************** */
373
374 static int action_stash_exec(bContext *C, wmOperator *op)
375 {
376   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
377   AnimData *adt = ED_actedit_animdata_from_context(C);
378
379   /* Perform stashing operation */
380   if (adt) {
381     /* don't do anything if this action is empty... */
382     if (action_has_motion(adt->action) == 0) {
383       /* action may not be suitable... */
384       BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
385       return OPERATOR_CANCELLED;
386     }
387     else {
388       /* stash the action */
389       if (BKE_nla_action_stash(adt)) {
390         /* The stash operation will remove the user already,
391          * so the flushing step later shouldn't double up
392          * the usercount 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
407   /* Send notifiers that stuff has changed */
408   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
409   return OPERATOR_FINISHED;
410 }
411
412 void ACTION_OT_stash(wmOperatorType *ot)
413 {
414   /* identifiers */
415   ot->name = "Stash Action";
416   ot->idname = "ACTION_OT_stash";
417   ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
418
419   /* callbacks */
420   ot->exec = action_stash_exec;
421   ot->poll = action_pushdown_poll;
422
423   /* flags */
424   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
425
426   /* properties */
427   ot->prop = RNA_def_boolean(ot->srna,
428                              "create_new",
429                              true,
430                              "Create New Action",
431                              "Create a new action once the existing one has been safely stored");
432 }
433
434 /* ----------------- */
435
436 /* Criteria:
437  *  1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
438  *  2) The associated AnimData block must not be in tweakmode
439  */
440 static bool action_stash_create_poll(bContext *C)
441 {
442   if (ED_operator_action_active(C)) {
443     AnimData *adt = ED_actedit_animdata_from_context(C);
444
445     /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
446     /* NOTE: unlike for pushdown,
447      * this operator needs to be run when creating an action from nothing... */
448     if (adt) {
449       if (!(adt->flag & ADT_NLA_EDIT_ON)) {
450         return true;
451       }
452     }
453     else {
454       /* There may not be any action/animdata yet, so, just fallback to the global setting
455        * (which may not be totally valid yet if the action editor was used and things are
456        * now in an inconsistent state)
457        */
458       SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
459       Scene *scene = CTX_data_scene(C);
460
461       if (!(scene->flag & SCE_NLA_EDIT_ON)) {
462         /* For now, actions are only for the active object, and on object and shapekey levels... */
463         return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
464       }
465     }
466   }
467
468   /* something failed... */
469   return false;
470 }
471
472 static int action_stash_create_exec(bContext *C, wmOperator *op)
473 {
474   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
475   AnimData *adt = ED_actedit_animdata_from_context(C);
476
477   /* Check for no action... */
478   if (saction->action == NULL) {
479     /* just create a new action */
480     bAction *action = action_create_new(C, NULL);
481     actedit_change_action(C, action);
482   }
483   else if (adt) {
484     /* Perform stashing operation */
485     if (action_has_motion(adt->action) == 0) {
486       /* don't do anything if this action is empty... */
487       BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
488       return OPERATOR_CANCELLED;
489     }
490     else {
491       /* stash the action */
492       if (BKE_nla_action_stash(adt)) {
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 usercount 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
515   /* Send notifiers that stuff has changed */
516   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
517   return OPERATOR_FINISHED;
518 }
519
520 void ACTION_OT_stash_and_create(wmOperatorType *ot)
521 {
522   /* identifiers */
523   ot->name = "Stash Action";
524   ot->idname = "ACTION_OT_stash_and_create";
525   ot->description =
526       "Store this action in the NLA stack as a non-contributing strip for later use, and create a "
527       "new action";
528
529   /* callbacks */
530   ot->exec = action_stash_create_exec;
531   ot->poll = action_stash_create_poll;
532
533   /* flags */
534   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
535 }
536
537 /* ************************************************************************** */
538 /* ACTION UNLINK */
539
540 /* ******************* Action Unlink Operator ******************** */
541 /* We use a custom unlink operator here, as there are some technicalities which need special care:
542  * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action,
543  *    or else, everything turns to custard.
544  * 2) If the Action doesn't have any other users, the user should at least get
545  *    a warning that it is going to get lost.
546  * 3) We need a convenient way to exit Tweak Mode from the Action Editor
547  */
548
549 void ED_animedit_unlink_action(
550     bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
551 {
552   ScrArea *area = CTX_wm_area(C);
553
554   /* If the old action only has a single user (that it's about to lose),
555    * warn user about it
556    *
557    * TODO: Maybe we should just save it for them? But then, there's the problem of
558    *       trying to get rid of stuff that's actually unwanted!
559    */
560   if (act->id.us == 1) {
561     BKE_reportf(reports,
562                 RPT_WARNING,
563                 "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
564                 act->id.name + 2);
565   }
566
567   /* Clear Fake User and remove action stashing strip (if present) */
568   if (force_delete) {
569     /* Remove stashed strip binding this action to this datablock */
570     /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
571      * but GE users only seem to use/care about single-object binding for now so this
572      * should be fine
573      */
574     if (adt) {
575       NlaTrack *nlt, *nlt_next;
576       NlaStrip *strip, *nstrip;
577
578       for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
579         nlt_next = nlt->next;
580
581         if (strstr(nlt->name, DATA_("[Action Stash]"))) {
582           for (strip = nlt->strips.first; strip; strip = nstrip) {
583             nstrip = strip->next;
584
585             if (strip->act == act) {
586               /* Remove this strip, and the track too if it doesn't have anything else */
587               BKE_nlastrip_free(&nlt->strips, strip, true);
588
589               if (nlt->strips.first == NULL) {
590                 BLI_assert(nstrip == NULL);
591                 BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
592               }
593             }
594           }
595         }
596       }
597     }
598
599     /* Clear Fake User */
600     id_fake_user_clear(&act->id);
601   }
602
603   /* If in Tweak Mode, don't unlink. Instead, this
604    * becomes a shortcut to exit Tweak Mode instead
605    */
606   if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
607     /* Exit Tweak Mode */
608     BKE_nla_tweakmode_exit(adt);
609
610     /* Flush this to the Action Editor (if that's where this change was initiated) */
611     if (area->spacetype == SPACE_ACTION) {
612       actedit_change_action(C, NULL);
613     }
614   }
615   else {
616     /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
617     if (area->spacetype == SPACE_ACTION) {
618       /* clear action editor -> action */
619       actedit_change_action(C, NULL);
620     }
621     else {
622       /* clear AnimData -> action */
623       PointerRNA ptr;
624       PropertyRNA *prop;
625
626       /* create AnimData RNA pointers */
627       RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
628       prop = RNA_struct_find_property(&ptr, "action");
629
630       /* clear... */
631       RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL, NULL);
632       RNA_property_update(C, &ptr, prop);
633     }
634   }
635 }
636
637 /* -------------------------- */
638
639 static bool action_unlink_poll(bContext *C)
640 {
641   if (ED_operator_action_active(C)) {
642     SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
643     AnimData *adt = ED_actedit_animdata_from_context(C);
644
645     /* Only when there's an active action, in the right modes... */
646     if (saction->action && adt) {
647       return true;
648     }
649   }
650
651   /* something failed... */
652   return false;
653 }
654
655 static int action_unlink_exec(bContext *C, wmOperator *op)
656 {
657   AnimData *adt = ED_actedit_animdata_from_context(C);
658   bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
659
660   if (adt && adt->action) {
661     ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
662   }
663
664   return OPERATOR_FINISHED;
665 }
666
667 static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
668 {
669   /* NOTE: this is hardcoded to match the behavior for the unlink button
670    * (in interface_templates.c). */
671   RNA_boolean_set(op->ptr, "force_delete", evt->shift != 0);
672   return action_unlink_exec(C, op);
673 }
674
675 void ACTION_OT_unlink(wmOperatorType *ot)
676 {
677   PropertyRNA *prop;
678
679   /* identifiers */
680   ot->name = "Unlink Action";
681   ot->idname = "ACTION_OT_unlink";
682   ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
683
684   /* callbacks */
685   ot->invoke = action_unlink_invoke;
686   ot->exec = action_unlink_exec;
687   ot->poll = action_unlink_poll;
688
689   /* properties */
690   prop = RNA_def_boolean(ot->srna,
691                          "force_delete",
692                          false,
693                          "Force Delete",
694                          "Clear Fake User and remove "
695                          "copy stashed in this data-block's NLA stack");
696   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
697 }
698
699 /* ************************************************************************** */
700 /* ACTION BROWSING */
701
702 /* Try to find NLA Strip to use for action layer up/down tool */
703 static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
704 {
705   NlaStrip *strip;
706
707   for (strip = strips->first; strip; strip = strip->next) {
708     /* Can we use this? */
709     if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
710       /* in range - use this one */
711       return strip;
712     }
713     else if ((ctime < strip->start) && (strip->prev == NULL)) {
714       /* before first - use this one */
715       return strip;
716     }
717     else if ((ctime > strip->end) && (strip->next == NULL)) {
718       /* after last - use this one */
719       return strip;
720     }
721   }
722
723   /* nothing suitable found... */
724   return NULL;
725 }
726
727 /* Switch NLA Strips/Actions  */
728 static void action_layer_switch_strip(
729     AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip)
730 {
731   /* Exit tweakmode on old strip
732    * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it
733    */
734   BKE_nla_tweakmode_exit(adt);
735
736   if (old_strip) {
737     old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
738   }
739   if (old_track) {
740     old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
741   }
742
743   /* Make this one the active one instead */
744   strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
745   nlt->flag |= NLATRACK_ACTIVE;
746
747   /* Copy over "solo" flag - This is useful for stashed actions... */
748   if (old_track) {
749     if (old_track->flag & NLATRACK_SOLO) {
750       old_track->flag &= ~NLATRACK_SOLO;
751       nlt->flag |= NLATRACK_SOLO;
752     }
753   }
754   else {
755     /* NLA muting <==> Solo Tracks */
756     if (adt->flag & ADT_NLA_EVAL_OFF) {
757       /* disable NLA muting */
758       adt->flag &= ~ADT_NLA_EVAL_OFF;
759
760       /* mark this track as being solo */
761       adt->flag |= ADT_NLA_SOLO_TRACK;
762       nlt->flag |= NLATRACK_SOLO;
763
764       // TODO: Needs restpose flushing (when we get reference track)
765     }
766   }
767
768   /* Enter tweakmode again - hopefully we're now "it" */
769   BKE_nla_tweakmode_enter(adt);
770   BLI_assert(adt->actstrip == strip);
771 }
772
773 /* ********************** One Layer Up Operator ************************** */
774
775 static bool action_layer_next_poll(bContext *C)
776 {
777   /* Action Editor's action editing modes only */
778   if (ED_operator_action_active(C)) {
779     AnimData *adt = ED_actedit_animdata_from_context(C);
780     if (adt) {
781       /* only allow if we're in tweakmode, and there's something above us... */
782       if (adt->flag & ADT_NLA_EDIT_ON) {
783         /* We need to check if there are any tracks above the active one
784          * since the track the action comes from is not stored in AnimData
785          */
786         if (adt->nla_tracks.last) {
787           NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
788
789           if (nlt->flag & NLATRACK_DISABLED) {
790             /* A disabled track will either be the track itself,
791              * or one of the ones above it.
792              *
793              * If this is the top-most one, there is the possibility
794              * that there is no active action. For now, we let this
795              * case return true too, so that there is a natural way
796              * to "move to an empty layer", even though this means
797              * that we won't actually have an action.
798              */
799             // return (adt->tmpact != NULL);
800             return true;
801           }
802         }
803       }
804     }
805   }
806
807   /* something failed... */
808   return false;
809 }
810
811 static int action_layer_next_exec(bContext *C, wmOperator *op)
812 {
813   AnimData *adt = ED_actedit_animdata_from_context(C);
814   NlaTrack *act_track;
815
816   Scene *scene = CTX_data_scene(C);
817   float ctime = BKE_scene_frame_get(scene);
818
819   /* Get active track */
820   act_track = BKE_nlatrack_find_tweaked(adt);
821
822   if (act_track == NULL) {
823     BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
824     return OPERATOR_CANCELLED;
825   }
826
827   /* Find next action, and hook it up */
828   if (act_track->next) {
829     NlaTrack *nlt;
830
831     /* Find next action to use */
832     for (nlt = act_track->next; nlt; nlt = nlt->next) {
833       NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
834
835       if (strip) {
836         action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
837         break;
838       }
839     }
840   }
841   else {
842     /* No more actions (strips) - Go back to editing the original active action
843      * NOTE: This will mean exiting tweakmode...
844      */
845     BKE_nla_tweakmode_exit(adt);
846
847     /* Deal with solo flags...
848      * Assume: Solo Track == NLA Muting
849      */
850     if (adt->flag & ADT_NLA_SOLO_TRACK) {
851       /* turn off solo flags on tracks */
852       act_track->flag &= ~NLATRACK_SOLO;
853       adt->flag &= ~ADT_NLA_SOLO_TRACK;
854
855       /* turn on NLA muting (to keep same effect) */
856       adt->flag |= ADT_NLA_EVAL_OFF;
857
858       // TODO: Needs restpose flushing (when we get reference track)
859     }
860   }
861
862   /* Update the action that this editor now uses
863    * NOTE: The calls above have already handled the usercount/animdata side of things
864    */
865   actedit_change_action(C, adt->action);
866   return OPERATOR_FINISHED;
867 }
868
869 void ACTION_OT_layer_next(wmOperatorType *ot)
870 {
871   /* identifiers */
872   ot->name = "Next Layer";
873   ot->idname = "ACTION_OT_layer_next";
874   ot->description =
875       "Switch to editing action in animation layer above the current action in the NLA Stack";
876
877   /* callbacks */
878   ot->exec = action_layer_next_exec;
879   ot->poll = action_layer_next_poll;
880
881   /* flags */
882   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
883 }
884
885 /* ********************* One Layer Down Operator ************************* */
886
887 static bool action_layer_prev_poll(bContext *C)
888 {
889   /* Action Editor's action editing modes only */
890   if (ED_operator_action_active(C)) {
891     AnimData *adt = ED_actedit_animdata_from_context(C);
892     if (adt) {
893       if (adt->flag & ADT_NLA_EDIT_ON) {
894         /* Tweak Mode: We need to check if there are any tracks below the active one
895          * that we can move to */
896         if (adt->nla_tracks.first) {
897           NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
898
899           /* Since the first disabled track is the track being tweaked/edited,
900            * we can simplify things by only checking the first track:
901            *    - If it is disabled, this is the track being tweaked,
902            *      so there can't be anything below it
903            *    - Otherwise, there is at least 1 track below the tweaking
904            *      track that we can descend to
905            */
906           if ((nlt->flag & NLATRACK_DISABLED) == 0) {
907             /* not disabled = there are actions below the one being tweaked */
908             return true;
909           }
910         }
911       }
912       else {
913         /* Normal Mode: If there are any tracks, we can try moving to those */
914         return (adt->nla_tracks.first != NULL);
915       }
916     }
917   }
918
919   /* something failed... */
920   return false;
921 }
922
923 static int action_layer_prev_exec(bContext *C, wmOperator *op)
924 {
925   AnimData *adt = ED_actedit_animdata_from_context(C);
926   NlaTrack *act_track;
927   NlaTrack *nlt;
928
929   Scene *scene = CTX_data_scene(C);
930   float ctime = BKE_scene_frame_get(scene);
931
932   /* Sanity Check */
933   if (adt == NULL) {
934     BKE_report(
935         op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
936     return OPERATOR_CANCELLED;
937   }
938
939   /* Get active track */
940   act_track = BKE_nlatrack_find_tweaked(adt);
941
942   /* If there is no active track, that means we are using the active action... */
943   if (act_track) {
944     /* Active Track - Start from the one below it */
945     nlt = act_track->prev;
946   }
947   else {
948     /* Active Action - Use the top-most track */
949     nlt = adt->nla_tracks.last;
950   }
951
952   /* Find previous action and hook it up */
953   for (; nlt; nlt = nlt->prev) {
954     NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
955
956     if (strip) {
957       action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
958       break;
959     }
960   }
961
962   /* Update the action that this editor now uses
963    * NOTE: The calls above have already handled the usercount/animdata side of things
964    */
965   actedit_change_action(C, adt->action);
966   return OPERATOR_FINISHED;
967 }
968
969 void ACTION_OT_layer_prev(wmOperatorType *ot)
970 {
971   /* identifiers */
972   ot->name = "Previous Layer";
973   ot->idname = "ACTION_OT_layer_prev";
974   ot->description =
975       "Switch to editing action in animation layer below the current action in the NLA Stack";
976
977   /* callbacks */
978   ot->exec = action_layer_prev_exec;
979   ot->poll = action_layer_prev_poll;
980
981   /* flags */
982   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
983 }
984
985 /* ************************************************************************** */