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