Fix T88342: 'To Sphere' and 'Push/Pull' not working in Pose mode
[blender.git] / source / blender / editors / space_nla / nla_edit.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) 2009 Blender Foundation, Joshua Leung
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup spnla
22  */
23
24 #include <math.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "DNA_anim_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_scene_types.h"
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_math.h"
36 #include "BLI_utildefines.h"
37
38 #include "BLT_translation.h"
39
40 #include "BKE_action.h"
41 #include "BKE_context.h"
42 #include "BKE_fcurve.h"
43 #include "BKE_lib_id.h"
44 #include "BKE_main.h"
45 #include "BKE_nla.h"
46 #include "BKE_report.h"
47 #include "BKE_screen.h"
48
49 #include "ED_anim_api.h"
50 #include "ED_keyframes_edit.h"
51 #include "ED_markers.h"
52 #include "ED_screen.h"
53 #include "ED_transform.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57 #include "RNA_enum_types.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #include "DEG_depsgraph_build.h"
63
64 #include "UI_interface.h"
65 #include "UI_view2d.h"
66
67 #include "nla_intern.h"  /* own include */
68 #include "nla_private.h" /* FIXME... maybe this shouldn't be included? */
69
70 /* -------------------------------------------------------------------- */
71 /** \name Public Utilities
72  * \{ */
73
74 /* Perform validation for blending/extend settings */
75 void ED_nla_postop_refresh(bAnimContext *ac)
76 {
77   ListBase anim_data = {NULL, NULL};
78   bAnimListElem *ale;
79   short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_FOREDIT);
80
81   /* get blocks to work on */
82   ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
83
84   for (ale = anim_data.first; ale; ale = ale->next) {
85     /* performing auto-blending, extend-mode validation, etc. */
86     BKE_nla_validate_state(ale->data);
87
88     ale->update |= ANIM_UPDATE_DEPS;
89   }
90
91   /* free temp memory */
92   ANIM_animdata_update(ac, &anim_data);
93   ANIM_animdata_freelist(&anim_data);
94 }
95
96 /** \} */
97
98 /* 'Special' Editing */
99
100 /* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
101  * as if it were the normal Active-Action of its AnimData block.
102  */
103
104 /* -------------------------------------------------------------------- */
105 /** \name Enable Tweak-Mode Operator
106  * \{ */
107
108 static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
109 {
110   bAnimContext ac;
111
112   ListBase anim_data = {NULL, NULL};
113   bAnimListElem *ale;
114   int filter;
115
116   const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
117   bool ok = false;
118
119   /* get editor data */
120   if (ANIM_animdata_get_context(C, &ac) == 0) {
121     return OPERATOR_CANCELLED;
122   }
123
124   /* get a list of the AnimData blocks being shown in the NLA */
125   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
126   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
127
128   /* if no blocks, popup error? */
129   if (BLI_listbase_is_empty(&anim_data)) {
130     BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for");
131     return OPERATOR_CANCELLED;
132   }
133
134   /* for each AnimData block with NLA-data, try setting it in tweak-mode */
135   for (ale = anim_data.first; ale; ale = ale->next) {
136     AnimData *adt = ale->data;
137
138     /* try entering tweakmode if valid */
139     ok |= BKE_nla_tweakmode_enter(adt);
140
141     /* mark the active track as being "solo"? */
142     if (do_solo && adt->actstrip) {
143       NlaTrack *nlt = BKE_nlatrack_find_tweaked(adt);
144
145       if (nlt && !(nlt->flag & NLATRACK_SOLO)) {
146         BKE_nlatrack_solo_toggle(adt, nlt);
147       }
148     }
149
150     ale->update |= ANIM_UPDATE_DEPS;
151   }
152
153   /* free temp data */
154   ANIM_animdata_update(&ac, &anim_data);
155   ANIM_animdata_freelist(&anim_data);
156
157   /* if we managed to enter tweakmode on at least one AnimData block,
158    * set the flag for this in the active scene and send notifiers
159    */
160   if (ac.scene && ok) {
161     /* set editing flag */
162     ac.scene->flag |= SCE_NLA_EDIT_ON;
163
164     /* set notifier that things have changed */
165     WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
166   }
167   else {
168     BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on");
169     return OPERATOR_CANCELLED;
170   }
171
172   /* done */
173   return OPERATOR_FINISHED;
174 }
175
176 void NLA_OT_tweakmode_enter(wmOperatorType *ot)
177 {
178   PropertyRNA *prop;
179
180   /* identifiers */
181   ot->name = "Enter Tweak Mode";
182   ot->idname = "NLA_OT_tweakmode_enter";
183   ot->description =
184       "Enter tweaking mode for the action referenced by the active strip to edit its keyframes";
185
186   /* api callbacks */
187   ot->exec = nlaedit_enable_tweakmode_exec;
188   ot->poll = nlaop_poll_tweakmode_off;
189
190   /* flags */
191   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
192
193   /* properties */
194   prop = RNA_def_boolean(ot->srna,
195                          "isolate_action",
196                          0,
197                          "Isolate Action",
198                          "Enable 'solo' on the NLA Track containing the active strip, "
199                          "to edit it without seeing the effects of the NLA stack");
200   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
201 }
202
203 /** \} */
204
205 /* -------------------------------------------------------------------- */
206 /** \name Disable Tweak-Mode Operator
207  * \{ */
208
209 /* NLA Editor internal API function for exiting tweakmode */
210 bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
211 {
212   ListBase anim_data = {NULL, NULL};
213   bAnimListElem *ale;
214   int filter;
215
216   /* get a list of the AnimData blocks being shown in the NLA */
217   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
218   ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
219
220   /* if no blocks, popup error? */
221   if (BLI_listbase_is_empty(&anim_data)) {
222     BKE_report(ac->reports, RPT_ERROR, "No AnimData blocks in tweak mode to exit from");
223     return false;
224   }
225
226   /* For each AnimData block with NLA-data, try exiting tweak-mode. */
227   for (ale = anim_data.first; ale; ale = ale->next) {
228     AnimData *adt = ale->data;
229
230     /* clear solo flags */
231     if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) && (adt->flag & ADT_NLA_EDIT_ON)) {
232       BKE_nlatrack_solo_toggle(adt, NULL);
233     }
234
235     /* to be sure that we're doing everything right, just exit tweakmode... */
236     BKE_nla_tweakmode_exit(adt);
237
238     ale->update |= ANIM_UPDATE_DEPS;
239   }
240
241   /* free temp data */
242   ANIM_animdata_update(ac, &anim_data);
243   ANIM_animdata_freelist(&anim_data);
244
245   /* if we managed to enter tweakmode on at least one AnimData block,
246    * set the flag for this in the active scene and send notifiers
247    */
248   if (ac->scene) {
249     /* clear editing flag */
250     ac->scene->flag &= ~SCE_NLA_EDIT_ON;
251
252     /* set notifier that things have changed */
253     WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
254   }
255
256   /* done */
257   return true;
258 }
259
260 /* exit tweakmode operator callback */
261 static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
262 {
263   bAnimContext ac;
264
265   const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
266   bool ok = false;
267
268   /* get editor data */
269   if (ANIM_animdata_get_context(C, &ac) == 0) {
270     return OPERATOR_CANCELLED;
271   }
272
273   /* perform operation */
274   ok = nlaedit_disable_tweakmode(&ac, do_solo);
275
276   /* success? */
277   if (ok) {
278     return OPERATOR_FINISHED;
279   }
280   return OPERATOR_CANCELLED;
281 }
282
283 void NLA_OT_tweakmode_exit(wmOperatorType *ot)
284 {
285   PropertyRNA *prop;
286
287   /* identifiers */
288   ot->name = "Exit Tweak Mode";
289   ot->idname = "NLA_OT_tweakmode_exit";
290   ot->description = "Exit tweaking mode for the action referenced by the active strip";
291
292   /* api callbacks */
293   ot->exec = nlaedit_disable_tweakmode_exec;
294   ot->poll = nlaop_poll_tweakmode_on;
295
296   /* flags */
297   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
298
299   /* properties */
300   prop = RNA_def_boolean(ot->srna,
301                          "isolate_action",
302                          0,
303                          "Isolate Action",
304                          "Disable 'solo' on any of the NLA Tracks after exiting tweak mode "
305                          "to get things back to normal");
306   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
307 }
308
309 /** \} */
310
311 /* NLA Strips Range Stuff */
312
313 /* -------------------------------------------------------------------- */
314 /** \name Calculate NLA Strip Range
315  * \{ */
316
317 /* Get the min/max strip extents */
318 static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const bool only_sel)
319 {
320   ListBase anim_data = {NULL, NULL};
321   bAnimListElem *ale;
322   int filter;
323   bool found_bounds = false;
324
325   /* get data to filter */
326   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
327   ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
328
329   /* set large values to try to override */
330   *min = 999999999.0f;
331   *max = -999999999.0f;
332
333   /* check if any channels to set range with */
334   if (anim_data.first) {
335     /* go through channels, finding max extents */
336     for (ale = anim_data.first; ale; ale = ale->next) {
337       NlaTrack *nlt = (NlaTrack *)ale->data;
338       NlaStrip *strip;
339
340       for (strip = nlt->strips.first; strip; strip = strip->next) {
341         /* only consider selected strips? */
342         if ((only_sel == false) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
343           /* extend range if appropriate */
344           *min = min_ff(*min, strip->start);
345           *max = max_ff(*max, strip->end);
346
347           found_bounds = true;
348         }
349       }
350     }
351
352     /* free memory */
353     ANIM_animdata_freelist(&anim_data);
354   }
355
356   /* set default range if nothing happened */
357   if (found_bounds == false) {
358     if (ac->scene) {
359       *min = (float)ac->scene->r.sfra;
360       *max = (float)ac->scene->r.efra;
361     }
362     else {
363       *min = -5;
364       *max = 100;
365     }
366   }
367 }
368
369 /** \} */
370
371 /* -------------------------------------------------------------------- */
372 /** \name Automatic Preview-Range Operator
373  * \{ */
374
375 static int nlaedit_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
376 {
377   bAnimContext ac;
378   Scene *scene;
379   float min, max;
380
381   /* get editor data */
382   if (ANIM_animdata_get_context(C, &ac) == 0) {
383     return OPERATOR_CANCELLED;
384   }
385
386   if (ac.scene == NULL) {
387     return OPERATOR_CANCELLED;
388   }
389
390   scene = ac.scene;
391
392   /* set the range directly */
393   get_nlastrip_extents(&ac, &min, &max, true);
394   scene->r.flag |= SCER_PRV_RANGE;
395   scene->r.psfra = round_fl_to_int(min);
396   scene->r.pefra = round_fl_to_int(max);
397
398   /* set notifier that things have changed */
399   /* XXX err... there's nothing for frame ranges yet, but this should do fine too */
400   WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
401
402   return OPERATOR_FINISHED;
403 }
404
405 void NLA_OT_previewrange_set(wmOperatorType *ot)
406 {
407   /* identifiers */
408   ot->name = "Auto-Set Preview Range";
409   ot->idname = "NLA_OT_previewrange_set";
410   ot->description = "Automatically set Preview Range based on range of keyframes";
411
412   /* api callbacks */
413   ot->exec = nlaedit_previewrange_exec;
414   ot->poll = ED_operator_nla_active;
415
416   /* flags */
417   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
418 }
419
420 /** \} */
421
422 /* -------------------------------------------------------------------- */
423 /** \name View-All Operator
424  * \{ */
425
426 /**
427  * Find the extents of the active channel
428  *
429  * \param r_min: Bottom y-extent of channel.
430  * \param r_max: Top y-extent of channel.
431  * \return Success of finding a selected channel.
432  */
433 static bool nla_channels_get_selected_extents(bAnimContext *ac, float *r_min, float *r_max)
434 {
435   ListBase anim_data = {NULL, NULL};
436   bAnimListElem *ale;
437   int filter;
438
439   SpaceNla *snla = (SpaceNla *)ac->sl;
440   /* NOTE: not bool, since we want prioritize individual channels over expanders. */
441   short found = 0;
442
443   /* get all items - we need to do it this way */
444   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
445   ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
446
447   /* loop through all channels, finding the first one that's selected */
448   float ymax = NLACHANNEL_FIRST_TOP(ac);
449
450   for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
451     const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
452
453     /* must be selected... */
454     if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
455         ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) {
456       /* update best estimate */
457       *r_min = ymax - NLACHANNEL_HEIGHT(snla);
458       *r_max = ymax;
459
460       /* is this high enough priority yet? */
461       found = acf->channel_role;
462
463       /* only stop our search when we've found an actual channel
464        * - data-block expanders get less priority so that we don't abort prematurely
465        */
466       if (found == ACHANNEL_ROLE_CHANNEL) {
467         break;
468       }
469     }
470   }
471
472   /* free all temp data */
473   ANIM_animdata_freelist(&anim_data);
474
475   return (found != 0);
476 }
477
478 static int nlaedit_viewall(bContext *C, const bool only_sel)
479 {
480   bAnimContext ac;
481   View2D *v2d;
482   float extra;
483
484   /* get editor data */
485   if (ANIM_animdata_get_context(C, &ac) == 0) {
486     return OPERATOR_CANCELLED;
487   }
488   v2d = &ac.region->v2d;
489
490   /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
491   get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel);
492
493   extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
494   v2d->cur.xmin -= extra;
495   v2d->cur.xmax += extra;
496
497   /* set vertical range */
498   if (only_sel == false) {
499     /* view all -> the summary channel is usually the shows everything,
500      * and resides right at the top... */
501     v2d->cur.ymax = 0.0f;
502     v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
503   }
504   else {
505     /* locate first selected channel (or the active one), and frame those */
506     float ymin = v2d->cur.ymin;
507     float ymax = v2d->cur.ymax;
508
509     if (nla_channels_get_selected_extents(&ac, &ymin, &ymax)) {
510       /* recenter the view so that this range is in the middle */
511       float ymid = (ymax - ymin) / 2.0f + ymin;
512       float x_center;
513
514       UI_view2d_center_get(v2d, &x_center, NULL);
515       UI_view2d_center_set(v2d, x_center, ymid);
516     }
517   }
518
519   /* do View2D syncing */
520   UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
521
522   /* just redraw this view */
523   ED_area_tag_redraw(CTX_wm_area(C));
524
525   return OPERATOR_FINISHED;
526 }
527
528 /* ......... */
529
530 static int nlaedit_viewall_exec(bContext *C, wmOperator *UNUSED(op))
531 {
532   /* whole range */
533   return nlaedit_viewall(C, false);
534 }
535
536 static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
537 {
538   /* only selected */
539   return nlaedit_viewall(C, true);
540 }
541
542 void NLA_OT_view_all(wmOperatorType *ot)
543 {
544   /* identifiers */
545   ot->name = "Frame All";
546   ot->idname = "NLA_OT_view_all";
547   ot->description = "Reset viewable area to show full strips range";
548
549   /* api callbacks */
550   ot->exec = nlaedit_viewall_exec;
551   ot->poll = ED_operator_nla_active;
552
553   /* flags */
554   ot->flag = 0;
555 }
556
557 void NLA_OT_view_selected(wmOperatorType *ot)
558 {
559   /* identifiers */
560   ot->name = "Frame Selected";
561   ot->idname = "NLA_OT_view_selected";
562   ot->description = "Reset viewable area to show selected strips range";
563
564   /* api callbacks */
565   ot->exec = nlaedit_viewsel_exec;
566   ot->poll = ED_operator_nla_active;
567
568   /* flags */
569   ot->flag = 0;
570 }
571
572 /** \} */
573
574 /* -------------------------------------------------------------------- */
575 /** \name View-Frame Operator
576  * \{ */
577
578 static int nlaedit_viewframe_exec(bContext *C, wmOperator *op)
579 {
580   const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
581   ANIM_center_frame(C, smooth_viewtx);
582   return OPERATOR_FINISHED;
583 }
584
585 void NLA_OT_view_frame(wmOperatorType *ot)
586 {
587   /* identifiers */
588   ot->name = "Go to Current Frame";
589   ot->idname = "NLA_OT_view_frame";
590   ot->description = "Move the view to the current frame";
591
592   /* api callbacks */
593   ot->exec = nlaedit_viewframe_exec;
594   ot->poll = ED_operator_nla_active;
595
596   /* flags */
597   ot->flag = 0;
598 }
599
600 /** \} */
601
602 /* NLA Editing Operations (Constructive/Destructive) */
603
604 /* -------------------------------------------------------------------- */
605 /** \name Add Action-Clip Operator
606  *
607  * Add a new Action-Clip strip to the active track
608  * (or the active block if no space in the track).
609  * \{ */
610
611 /* add the specified action as new strip */
612 static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
613 {
614   Main *bmain = CTX_data_main(C);
615   bAnimContext ac;
616   Scene *scene;
617
618   ListBase anim_data = {NULL, NULL};
619   bAnimListElem *ale;
620   size_t items;
621   int filter;
622
623   bAction *act;
624
625   float cfra;
626
627   /* get editor data */
628   if (ANIM_animdata_get_context(C, &ac) == 0) {
629     return OPERATOR_CANCELLED;
630   }
631
632   scene = ac.scene;
633   cfra = (float)CFRA;
634
635   /* get action to use */
636   act = BLI_findlink(&bmain->actions, RNA_enum_get(op->ptr, "action"));
637
638   if (act == NULL) {
639     BKE_report(op->reports, RPT_ERROR, "No valid action to add");
640     // printf("Add strip - actname = '%s'\n", actname);
641     return OPERATOR_CANCELLED;
642   }
643   if (act->idroot == 0) {
644     /* hopefully in this case (i.e. library of userless actions),
645      * the user knows what they're doing... */
646     BKE_reportf(op->reports,
647                 RPT_WARNING,
648                 "Action '%s' does not specify what data-blocks it can be used on "
649                 "(try setting the 'ID Root Type' setting from the data-blocks editor "
650                 "for this action to avoid future problems)",
651                 act->id.name + 2);
652   }
653
654   /* add tracks to empty but selected animdata blocks so that strips can be added to those directly
655    * without having to manually add tracks first
656    */
657   nlaedit_add_tracks_empty(&ac);
658
659   /* get a list of the editable tracks being shown in the NLA
660    * - this is limited to active ones for now, but could be expanded to
661    */
662   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ACTIVE | ANIMFILTER_FOREDIT);
663   items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
664
665   if (items == 0) {
666     BKE_report(op->reports,
667                RPT_ERROR,
668                "No active track(s) to add strip to, select an existing track or add one before "
669                "trying again");
670     return OPERATOR_CANCELLED;
671   }
672
673   /* for every active track,
674    * try to add strip to free space in track or to the top of the stack if no space */
675   for (ale = anim_data.first; ale; ale = ale->next) {
676     NlaTrack *nlt = (NlaTrack *)ale->data;
677     AnimData *adt = ale->adt;
678     NlaStrip *strip = NULL;
679     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
680
681     /* Sanity check: only apply actions of the right type for this ID.
682      * NOTE: in the case that this hasn't been set,
683      * we've already warned the user about this already
684      */
685     if ((act->idroot) && (act->idroot != GS(ale->id->name))) {
686       BKE_reportf(
687           op->reports,
688           RPT_ERROR,
689           "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'",
690           act->id.name + 2,
691           ale->id->name);
692       continue;
693     }
694
695     /* create a new strip, and offset it to start on the current frame */
696     strip = BKE_nlastrip_new(act);
697
698     strip->end += (cfra - strip->start);
699     strip->start = cfra;
700
701     /* firstly try adding strip to our current track, but if that fails, add to a new track */
702     if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
703       /* trying to add to the current failed (no space),
704        * so add a new track to the stack, and add to that...
705        */
706       nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
707       BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
708     }
709
710     /* auto-name it */
711     BKE_nlastrip_validate_name(adt, strip);
712   }
713
714   /* free temp data */
715   ANIM_animdata_freelist(&anim_data);
716
717   /* refresh auto strip properties */
718   ED_nla_postop_refresh(&ac);
719
720   DEG_relations_tag_update(ac.bmain);
721
722   /* set notifier that things have changed */
723   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
724
725   /* done */
726   return OPERATOR_FINISHED;
727 }
728
729 void NLA_OT_actionclip_add(wmOperatorType *ot)
730 {
731   PropertyRNA *prop;
732
733   /* identifiers */
734   ot->name = "Add Action Strip";
735   ot->idname = "NLA_OT_actionclip_add";
736   ot->description =
737       "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track";
738
739   /* api callbacks */
740   ot->invoke = WM_enum_search_invoke;
741   ot->exec = nlaedit_add_actionclip_exec;
742   ot->poll = nlaop_poll_tweakmode_off;
743
744   /* flags */
745   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
746
747   /* props */
748   /* TODO: this would be nicer as an ID-pointer. */
749   prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
750   RNA_def_enum_funcs(prop, RNA_action_itemf);
751   RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
752   ot->prop = prop;
753 }
754
755 /** \} */
756
757 /* -------------------------------------------------------------------- */
758 /** \name Add Transition Operator
759  *
760  * Add a new transition strip between selected strips.
761  * \{ */
762
763 static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
764 {
765   bAnimContext ac;
766
767   ListBase anim_data = {NULL, NULL};
768   bAnimListElem *ale;
769   int filter;
770
771   bool done = false;
772
773   /* get editor data */
774   if (ANIM_animdata_get_context(C, &ac) == 0) {
775     return OPERATOR_CANCELLED;
776   }
777
778   /* get a list of the editable tracks being shown in the NLA */
779   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
780   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
781
782   /* for each track, find pairs of strips to add transitions to */
783   for (ale = anim_data.first; ale; ale = ale->next) {
784     NlaTrack *nlt = (NlaTrack *)ale->data;
785     AnimData *adt = ale->adt;
786     NlaStrip *s1, *s2;
787
788     /* get initial pair of strips */
789     if (ELEM(nlt->strips.first, NULL, nlt->strips.last)) {
790       continue;
791     }
792     s1 = nlt->strips.first;
793     s2 = s1->next;
794
795     /* loop over strips */
796     for (; s1 && s2; s1 = s2, s2 = s2->next) {
797       NlaStrip *strip;
798
799       /* check if both are selected */
800       if (ELEM(0, (s1->flag & NLASTRIP_FLAG_SELECT), (s2->flag & NLASTRIP_FLAG_SELECT))) {
801         continue;
802       }
803       /* check if there's space between the two */
804       if (IS_EQF(s1->end, s2->start)) {
805         continue;
806       }
807       /* make sure neither one is a transition
808        * - although this is impossible to create with the standard tools,
809        *   the user may have altered the settings
810        */
811       if (ELEM(NLASTRIP_TYPE_TRANSITION, s1->type, s2->type)) {
812         continue;
813       }
814       /* also make sure neither one is a soundclip */
815       if (ELEM(NLASTRIP_TYPE_SOUND, s1->type, s2->type)) {
816         continue;
817       }
818
819       /* allocate new strip */
820       strip = MEM_callocN(sizeof(NlaStrip), "NlaStrip");
821       BLI_insertlinkafter(&nlt->strips, s1, strip);
822
823       /* set the type */
824       strip->type = NLASTRIP_TYPE_TRANSITION;
825
826       /* generic settings
827        * - selected flag to highlight this to the user
828        * - auto-blends to ensure that blend in/out values are automatically
829        *   determined by overlaps of strips
830        */
831       strip->flag = NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_AUTO_BLENDS;
832
833       /* range is simply defined as the endpoints of the adjacent strips */
834       strip->start = s1->end;
835       strip->end = s2->start;
836
837       /* scale and repeat aren't of any use, but shouldn't ever be 0 */
838       strip->scale = 1.0f;
839       strip->repeat = 1.0f;
840
841       /* auto-name it */
842       BKE_nlastrip_validate_name(adt, strip);
843
844       /* make note of this */
845       done = true;
846     }
847   }
848
849   /* free temp data */
850   ANIM_animdata_freelist(&anim_data);
851
852   /* was anything added? */
853   if (done) {
854     /* refresh auto strip properties */
855     ED_nla_postop_refresh(&ac);
856
857     /* set notifier that things have changed */
858     WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
859
860     /* done */
861     return OPERATOR_FINISHED;
862   }
863
864   BKE_report(op->reports,
865              RPT_ERROR,
866              "Needs at least a pair of adjacent selected strips with a gap between them");
867   return OPERATOR_CANCELLED;
868 }
869
870 void NLA_OT_transition_add(wmOperatorType *ot)
871 {
872   /* identifiers */
873   ot->name = "Add Transition";
874   ot->idname = "NLA_OT_transition_add";
875   ot->description = "Add a transition strip between two adjacent selected strips";
876
877   /* api callbacks */
878   ot->exec = nlaedit_add_transition_exec;
879   ot->poll = nlaop_poll_tweakmode_off;
880
881   /* flags */
882   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
883 }
884
885 /** \} */
886
887 /* -------------------------------------------------------------------- */
888 /** \name Add Sound Clip Operator
889  * \{ */
890
891 static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
892 {
893   Main *bmain = CTX_data_main(C);
894   bAnimContext ac;
895
896   ListBase anim_data = {NULL, NULL};
897   bAnimListElem *ale;
898   int filter;
899
900   Scene *scene;
901   int cfra;
902
903   /* get editor data */
904   if (ANIM_animdata_get_context(C, &ac) == 0) {
905     return OPERATOR_CANCELLED;
906   }
907
908   scene = ac.scene;
909   cfra = CFRA;
910
911   /* get a list of the editable tracks being shown in the NLA */
912   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
913             ANIMFILTER_FOREDIT);
914   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
915
916   /* for each track, add sound clips if it belongs to a speaker */
917   /* TODO: what happens if there aren't any tracks,
918    * well that's a more general problem for later. */
919   for (ale = anim_data.first; ale; ale = ale->next) {
920     Object *ob = (Object *)ale->id; /* may not be object until we actually check! */
921
922     AnimData *adt = ale->adt;
923     NlaTrack *nlt = (NlaTrack *)ale->data;
924     NlaStrip *strip;
925     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
926
927     /* does this belong to speaker - assumed to live on Object level only */
928     if ((GS(ale->id->name) != ID_OB) || (ob->type != OB_SPEAKER)) {
929       continue;
930     }
931
932     /* create a new strip, and offset it to start on the current frame */
933     strip = BKE_nla_add_soundstrip(bmain, ac.scene, ob->data);
934
935     strip->start += cfra;
936     strip->end += cfra;
937
938     /* firstly try adding strip to our current track, but if that fails, add to a new track */
939     if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
940       /* trying to add to the current failed (no space),
941        * so add a new track to the stack, and add to that...
942        */
943       nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
944       BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
945     }
946
947     /* auto-name it */
948     BKE_nlastrip_validate_name(adt, strip);
949   }
950
951   /* free temp data */
952   ANIM_animdata_freelist(&anim_data);
953
954   /* refresh auto strip properties */
955   ED_nla_postop_refresh(&ac);
956
957   /* set notifier that things have changed */
958   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
959
960   /* done */
961   return OPERATOR_FINISHED;
962 }
963
964 void NLA_OT_soundclip_add(wmOperatorType *ot)
965 {
966   /* identifiers */
967   ot->name = "Add Sound Clip";
968   ot->idname = "NLA_OT_soundclip_add";
969   ot->description = "Add a strip for controlling when speaker plays its sound clip";
970
971   /* api callbacks */
972   ot->exec = nlaedit_add_sound_exec;
973   ot->poll = nlaop_poll_tweakmode_off;
974
975   /* flags */
976   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
977 }
978
979 /** \} */
980
981 /* -------------------------------------------------------------------- */
982 /** \name Add Meta-Strip Operator
983  *
984  * Add new meta-strips incorporating the selected strips.
985  * \{ */
986
987 /* add the specified action as new strip */
988 static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op))
989 {
990   bAnimContext ac;
991
992   ListBase anim_data = {NULL, NULL};
993   bAnimListElem *ale;
994   int filter;
995
996   /* get editor data */
997   if (ANIM_animdata_get_context(C, &ac) == 0) {
998     return OPERATOR_CANCELLED;
999   }
1000
1001   /* get a list of the editable tracks being shown in the NLA */
1002   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1003   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1004
1005   /* for each track, find pairs of strips to add transitions to */
1006   for (ale = anim_data.first; ale; ale = ale->next) {
1007     NlaTrack *nlt = (NlaTrack *)ale->data;
1008     AnimData *adt = ale->adt;
1009     NlaStrip *strip;
1010
1011     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
1012       /* No making metastrips in non-local tracks of override data. */
1013       continue;
1014     }
1015
1016     /* create meta-strips from the continuous chains of selected strips */
1017     BKE_nlastrips_make_metas(&nlt->strips, 0);
1018
1019     /* name the metas */
1020     for (strip = nlt->strips.first; strip; strip = strip->next) {
1021       /* auto-name this strip if selected (that means it is a meta) */
1022       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1023         BKE_nlastrip_validate_name(adt, strip);
1024       }
1025     }
1026
1027     ale->update |= ANIM_UPDATE_DEPS;
1028   }
1029
1030   /* free temp data */
1031   ANIM_animdata_update(&ac, &anim_data);
1032   ANIM_animdata_freelist(&anim_data);
1033
1034   /* set notifier that things have changed */
1035   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
1036
1037   /* done */
1038   return OPERATOR_FINISHED;
1039 }
1040
1041 void NLA_OT_meta_add(wmOperatorType *ot)
1042 {
1043   /* identifiers */
1044   ot->name = "Add Meta-Strips";
1045   ot->idname = "NLA_OT_meta_add";
1046   ot->description = "Add new meta-strips incorporating the selected strips";
1047
1048   /* api callbacks */
1049   ot->exec = nlaedit_add_meta_exec;
1050   ot->poll = nlaop_poll_tweakmode_off;
1051
1052   /* flags */
1053   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1054 }
1055
1056 /** \} */
1057
1058 /* -------------------------------------------------------------------- */
1059 /** \name Remove Meta-Strip Operator
1060  *
1061  * Separate out the strips held by the selected meta-strips.
1062  * \{ */
1063
1064 static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op))
1065 {
1066   bAnimContext ac;
1067
1068   ListBase anim_data = {NULL, NULL};
1069   bAnimListElem *ale;
1070   int filter;
1071
1072   /* get editor data */
1073   if (ANIM_animdata_get_context(C, &ac) == 0) {
1074     return OPERATOR_CANCELLED;
1075   }
1076
1077   /* get a list of the editable tracks being shown in the NLA */
1078   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1079   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1080
1081   /* for each track, find pairs of strips to add transitions to */
1082   for (ale = anim_data.first; ale; ale = ale->next) {
1083     NlaTrack *nlt = (NlaTrack *)ale->data;
1084
1085     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
1086       /* No removing metastrips from non-local tracks of override data. */
1087       continue;
1088     }
1089
1090     /* clear all selected meta-strips, regardless of whether they are temporary or not */
1091     BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
1092
1093     ale->update |= ANIM_UPDATE_DEPS;
1094   }
1095
1096   /* free temp data */
1097   ANIM_animdata_update(&ac, &anim_data);
1098   ANIM_animdata_freelist(&anim_data);
1099
1100   /* set notifier that things have changed */
1101   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
1102
1103   /* done */
1104   return OPERATOR_FINISHED;
1105 }
1106
1107 void NLA_OT_meta_remove(wmOperatorType *ot)
1108 {
1109   /* identifiers */
1110   ot->name = "Remove Meta-Strips";
1111   ot->idname = "NLA_OT_meta_remove";
1112   ot->description = "Separate out the strips held by the selected meta-strips";
1113
1114   /* api callbacks */
1115   ot->exec = nlaedit_remove_meta_exec;
1116   ot->poll = nlaop_poll_tweakmode_off;
1117
1118   /* flags */
1119   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1120 }
1121
1122 /** \} */
1123
1124 /* -------------------------------------------------------------------- */
1125 /** \name Duplicate Strips Operator
1126  *
1127  * Duplicates the selected NLA-Strips,
1128  * putting them on new tracks above the one the originals were housed in.
1129  * \{ */
1130
1131 static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
1132 {
1133   bAnimContext ac;
1134
1135   ListBase anim_data = {NULL, NULL};
1136   bAnimListElem *ale;
1137   int filter;
1138
1139   bool linked = RNA_boolean_get(op->ptr, "linked");
1140   bool done = false;
1141
1142   /* get editor data */
1143   if (ANIM_animdata_get_context(C, &ac) == 0) {
1144     return OPERATOR_CANCELLED;
1145   }
1146
1147   /* get a list of editable tracks being shown in the NLA */
1148   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1149   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1150
1151   /* duplicate strips in tracks starting from the last one so that we're
1152    * less likely to duplicate strips we just duplicated...
1153    */
1154   for (ale = anim_data.last; ale; ale = ale->prev) {
1155     NlaTrack *nlt = (NlaTrack *)ale->data;
1156     AnimData *adt = ale->adt;
1157     NlaStrip *strip, *nstrip, *next;
1158     NlaTrack *track;
1159
1160     /* Note: We allow this operator in override context because it is almost always (from possible
1161      * default user interactions) paired with the transform one, which will ensure that the new
1162      * strip ends up in a valid (local) track. */
1163
1164     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1165     for (strip = nlt->strips.first; strip; strip = next) {
1166       next = strip->next;
1167
1168       /* if selected, split the strip at its midpoint */
1169       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1170         /* make a copy (assume that this is possible) */
1171         nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0);
1172
1173         /* in case there's no space in the track above,
1174          * or we haven't got a reference to it yet, try adding */
1175         if (BKE_nlatrack_add_strip(nlt->next, nstrip, is_liboverride) == 0) {
1176           /* need to add a new track above the one above the current one
1177            * - if the current one is the last one, nlt->next will be NULL, which defaults to adding
1178            *   at the top of the stack anyway...
1179            */
1180           track = BKE_nlatrack_add(adt, nlt->next, is_liboverride);
1181           BKE_nlatrack_add_strip(track, nstrip, is_liboverride);
1182         }
1183
1184         /* deselect the original and the active flag */
1185         strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
1186
1187         /* auto-name newly created strip */
1188         BKE_nlastrip_validate_name(adt, nstrip);
1189
1190         done = true;
1191       }
1192     }
1193   }
1194
1195   /* free temp data */
1196   ANIM_animdata_freelist(&anim_data);
1197
1198   if (done) {
1199     /* refresh auto strip properties */
1200     ED_nla_postop_refresh(&ac);
1201
1202     if (!linked) {
1203       DEG_relations_tag_update(ac.bmain);
1204     }
1205
1206     /* set notifier that things have changed */
1207     WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
1208
1209     /* done */
1210     return OPERATOR_FINISHED;
1211   }
1212
1213   return OPERATOR_CANCELLED;
1214 }
1215
1216 static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1217 {
1218   nlaedit_duplicate_exec(C, op);
1219
1220   RNA_enum_set(op->ptr, "mode", TFM_TRANSLATION);
1221   WM_operator_name_call(C, "TRANSFORM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
1222
1223   return OPERATOR_FINISHED;
1224 }
1225
1226 void NLA_OT_duplicate(wmOperatorType *ot)
1227 {
1228   /* identifiers */
1229   ot->name = "Duplicate Strips";
1230   ot->idname = "NLA_OT_duplicate";
1231   ot->description =
1232       "Duplicate selected NLA-Strips, adding the new strips in new tracks above the originals";
1233
1234   /* api callbacks */
1235   ot->invoke = nlaedit_duplicate_invoke;
1236   ot->exec = nlaedit_duplicate_exec;
1237   ot->poll = nlaop_poll_tweakmode_off;
1238
1239   /* flags */
1240   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1241
1242   /* own properties */
1243   ot->prop = RNA_def_boolean(ot->srna,
1244                              "linked",
1245                              false,
1246                              "Linked",
1247                              "When duplicating strips, assign new copies of the actions they use");
1248
1249   /* to give to transform */
1250   RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
1251 }
1252
1253 /** \} */
1254
1255 /* -------------------------------------------------------------------- */
1256 /** \name Delete Strips Operator
1257  *
1258  * Deletes the selected NLA-Strips.
1259  * \{ */
1260
1261 static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
1262 {
1263   bAnimContext ac;
1264
1265   ListBase anim_data = {NULL, NULL};
1266   bAnimListElem *ale;
1267   int filter;
1268
1269   /* get editor data */
1270   if (ANIM_animdata_get_context(C, &ac) == 0) {
1271     return OPERATOR_CANCELLED;
1272   }
1273
1274   /* get a list of the editable tracks being shown in the NLA */
1275   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1276   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1277
1278   /* for each NLA-Track, delete all selected strips */
1279   for (ale = anim_data.first; ale; ale = ale->next) {
1280     NlaTrack *nlt = (NlaTrack *)ale->data;
1281     NlaStrip *strip, *nstrip;
1282
1283     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
1284       /* No deletion of strips in non-local tracks of override data. */
1285       continue;
1286     }
1287
1288     for (strip = nlt->strips.first; strip; strip = nstrip) {
1289       nstrip = strip->next;
1290
1291       /* if selected, delete */
1292       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1293         /* if a strip either side of this was a transition, delete those too */
1294         if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
1295           BKE_nlastrip_free(&nlt->strips, strip->prev, true);
1296         }
1297         if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
1298           nstrip = nstrip->next;
1299           BKE_nlastrip_free(&nlt->strips, strip->next, true);
1300         }
1301
1302         /* finally, delete this strip */
1303         BKE_nlastrip_free(&nlt->strips, strip, true);
1304       }
1305     }
1306   }
1307
1308   /* free temp data */
1309   ANIM_animdata_freelist(&anim_data);
1310
1311   /* refresh auto strip properties */
1312   ED_nla_postop_refresh(&ac);
1313
1314   DEG_relations_tag_update(ac.bmain);
1315
1316   /* set notifier that things have changed */
1317   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
1318
1319   /* done */
1320   return OPERATOR_FINISHED;
1321 }
1322
1323 void NLA_OT_delete(wmOperatorType *ot)
1324 {
1325   /* identifiers */
1326   ot->name = "Delete Strips";
1327   ot->idname = "NLA_OT_delete";
1328   ot->description = "Delete selected strips";
1329
1330   /* api callbacks */
1331   ot->exec = nlaedit_delete_exec;
1332   ot->poll = nlaop_poll_tweakmode_off;
1333
1334   /* flags */
1335   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1336 }
1337
1338 /** \} */
1339
1340 /* -------------------------------------------------------------------- */
1341 /** \name Split Strips Operator
1342  *
1343  * Splits the selected NLA-Strips into two strips at the midpoint of the strip.
1344  *
1345  * TODO's?
1346  * - multiple splits
1347  * - variable-length splits?
1348  * \{ */
1349
1350 /* split a given Action-Clip strip */
1351 static void nlaedit_split_strip_actclip(
1352     Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
1353 {
1354   NlaStrip *nstrip;
1355   float splitframe, splitaframe;
1356
1357   /* calculate the frames to do the splitting at
1358    * - use current frame if within extents of strip
1359    */
1360   if ((cfra > strip->start) && (cfra < strip->end)) {
1361     /* use the current frame */
1362     splitframe = cfra;
1363     splitaframe = nlastrip_get_frame(strip, cfra, NLATIME_CONVERT_UNMAP);
1364   }
1365   else {
1366     /* split in the middle */
1367     float len;
1368
1369     /* strip extents */
1370     len = strip->end - strip->start;
1371     if (IS_EQF(len, 0.0f)) {
1372       return;
1373     }
1374
1375     splitframe = strip->start + (len / 2.0f);
1376
1377     /* action range */
1378     len = strip->actend - strip->actstart;
1379     if (IS_EQF(len, 0.0f)) {
1380       splitaframe = strip->actend;
1381     }
1382     else {
1383       splitaframe = strip->actstart + (len / 2.0f);
1384     }
1385   }
1386
1387   /* make a copy (assume that this is possible) and append
1388    * it immediately after the current strip
1389    */
1390   nstrip = BKE_nlastrip_copy(bmain, strip, true, 0);
1391   BLI_insertlinkafter(&nlt->strips, strip, nstrip);
1392
1393   /* Set the endpoint of the first strip and the start of the new strip
1394    * to the split-frame values calculated above.
1395    */
1396   strip->end = splitframe;
1397   nstrip->start = splitframe;
1398
1399   if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) {
1400     /* only do this if we're splitting down the middle...  */
1401     strip->actend = splitaframe;
1402     nstrip->actstart = splitaframe;
1403   }
1404
1405   /* clear the active flag from the copy */
1406   nstrip->flag &= ~NLASTRIP_FLAG_ACTIVE;
1407
1408   /* auto-name the new strip */
1409   BKE_nlastrip_validate_name(adt, nstrip);
1410 }
1411
1412 /* split a given Meta strip */
1413 static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip)
1414 {
1415   /* simply ungroup it for now...  */
1416   BKE_nlastrips_clear_metastrip(&nlt->strips, strip);
1417 }
1418
1419 /* ----- */
1420
1421 static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op))
1422 {
1423   bAnimContext ac;
1424
1425   ListBase anim_data = {NULL, NULL};
1426   bAnimListElem *ale;
1427   int filter;
1428
1429   /* get editor data */
1430   if (ANIM_animdata_get_context(C, &ac) == 0) {
1431     return OPERATOR_CANCELLED;
1432   }
1433
1434   /* get a list of editable tracks being shown in the NLA */
1435   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1436   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1437
1438   /* for each NLA-Track, split all selected strips into two strips */
1439   for (ale = anim_data.first; ale; ale = ale->next) {
1440     NlaTrack *nlt = (NlaTrack *)ale->data;
1441     AnimData *adt = ale->adt;
1442     NlaStrip *strip, *next;
1443
1444     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
1445       /* No splitting of strips in non-local tracks of override data. */
1446       continue;
1447     }
1448
1449     for (strip = nlt->strips.first; strip; strip = next) {
1450       next = strip->next;
1451
1452       /* if selected, split the strip at its midpoint */
1453       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1454         /* splitting method depends on the type of strip */
1455         switch (strip->type) {
1456           case NLASTRIP_TYPE_CLIP: /* action-clip */
1457             nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra);
1458             break;
1459
1460           case NLASTRIP_TYPE_META: /* meta-strips need special handling */
1461             nlaedit_split_strip_meta(nlt, strip);
1462             break;
1463
1464           default: /* for things like Transitions, do not split! */
1465             break;
1466         }
1467       }
1468     }
1469   }
1470
1471   /* free temp data */
1472   ANIM_animdata_freelist(&anim_data);
1473
1474   /* refresh auto strip properties */
1475   ED_nla_postop_refresh(&ac);
1476
1477   /* set notifier that things have changed */
1478   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
1479
1480   /* done */
1481   return OPERATOR_FINISHED;
1482 }
1483
1484 void NLA_OT_split(wmOperatorType *ot)
1485 {
1486   /* identifiers */
1487   ot->name = "Split Strips";
1488   ot->idname = "NLA_OT_split";
1489   ot->description = "Split selected strips at their midpoints";
1490
1491   /* api callbacks */
1492   ot->exec = nlaedit_split_exec;
1493   ot->poll = nlaop_poll_tweakmode_off;
1494
1495   /* flags */
1496   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1497 }
1498
1499 /** \} */
1500
1501 /* NLA Editing Operations (Modifying) */
1502
1503 /* -------------------------------------------------------------------- */
1504 /** \name Toggle Muting Operator
1505  *
1506  * Toggles whether strips are muted or not.
1507  * \{ */
1508
1509 static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op))
1510 {
1511   bAnimContext ac;
1512
1513   ListBase anim_data = {NULL, NULL};
1514   bAnimListElem *ale;
1515   int filter;
1516
1517   /* get editor data */
1518   if (ANIM_animdata_get_context(C, &ac) == 0) {
1519     return OPERATOR_CANCELLED;
1520   }
1521
1522   /* get a list of the editable tracks being shown in the NLA */
1523   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1524   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1525
1526   /* go over all selected strips */
1527   for (ale = anim_data.first; ale; ale = ale->next) {
1528     NlaTrack *nlt = (NlaTrack *)ale->data;
1529     NlaStrip *strip;
1530
1531     /* for every selected strip, toggle muting  */
1532     for (strip = nlt->strips.first; strip; strip = strip->next) {
1533       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1534         /* just flip the mute flag for now */
1535         /* TODO: have a pre-pass to check if mute all or unmute all? */
1536         strip->flag ^= NLASTRIP_FLAG_MUTED;
1537
1538         /* tag AnimData to get recalculated */
1539         ale->update |= ANIM_UPDATE_DEPS;
1540       }
1541     }
1542   }
1543
1544   /* cleanup */
1545   ANIM_animdata_update(&ac, &anim_data);
1546   ANIM_animdata_freelist(&anim_data);
1547
1548   /* set notifier that things have changed */
1549   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
1550
1551   /* done */
1552   return OPERATOR_FINISHED;
1553 }
1554
1555 void NLA_OT_mute_toggle(wmOperatorType *ot)
1556 {
1557   /* identifiers */
1558   ot->name = "Toggle Muting";
1559   ot->idname = "NLA_OT_mute_toggle";
1560   ot->description = "Mute or un-mute selected strips";
1561
1562   /* api callbacks */
1563   ot->exec = nlaedit_toggle_mute_exec;
1564   ot->poll = nlaop_poll_tweakmode_off;
1565
1566   /* flags */
1567   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1568 }
1569
1570 /** \} */
1571
1572 /* -------------------------------------------------------------------- */
1573 /** \name Swap Strips Operator
1574  *
1575  * Tries to exchange strips within their owner tracks.
1576  * \{ */
1577
1578 static int nlaedit_swap_exec(bContext *C, wmOperator *op)
1579 {
1580   bAnimContext ac;
1581
1582   ListBase anim_data = {NULL, NULL};
1583   bAnimListElem *ale;
1584   int filter;
1585
1586   /* get editor data */
1587   if (ANIM_animdata_get_context(C, &ac) == 0) {
1588     return OPERATOR_CANCELLED;
1589   }
1590
1591   /* get a list of the editable tracks being shown in the NLA */
1592   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1593   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1594
1595   /* consider each track in turn */
1596   for (ale = anim_data.first; ale; ale = ale->next) {
1597     NlaTrack *nlt = (NlaTrack *)ale->data;
1598
1599     NlaStrip *strip, *stripN = NULL;
1600     NlaStrip *area = NULL, *sb = NULL;
1601     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1602
1603     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
1604       /* No re-ordering of strips within non-local tracks of override data. */
1605       continue;
1606     }
1607
1608     /* Make temporary meta-strips so that entire islands of selections can be moved around. */
1609     BKE_nlastrips_make_metas(&nlt->strips, 1);
1610
1611     /* special case: if there is only 1 island
1612      * (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this,
1613      * and this island has two strips inside it, then we should be able to just swap these still...
1614      */
1615     if (BLI_listbase_is_empty(&nlt->strips) == false) {
1616       NlaStrip *mstrip = (NlaStrip *)nlt->strips.first;
1617
1618       if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) &&
1619           (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2)) {
1620         /* remove this temp meta, so that we can see the strips inside */
1621         BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
1622       }
1623     }
1624
1625     /* get two selected strips only (these will be metas due to prev step) to operate on
1626      * - only allow swapping 2, as with more the context becomes unclear
1627      */
1628     for (strip = nlt->strips.first; strip; strip = stripN) {
1629       stripN = strip->next;
1630
1631       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1632         /* first or second strip? */
1633         if (area == NULL) {
1634           /* store as first */
1635           area = strip;
1636         }
1637         else if (sb == NULL) {
1638           /* store as second */
1639           sb = strip;
1640         }
1641         else {
1642           /* too many selected */
1643           break;
1644         }
1645       }
1646     }
1647
1648     if (strip) {
1649       /* too many selected warning */
1650       BKE_reportf(
1651           op->reports,
1652           RPT_WARNING,
1653           "Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
1654           nlt->name);
1655     }
1656     else if (area == NULL) {
1657       /* no warning as this is just a common case,
1658        * and it may get annoying when doing multiple tracks */
1659     }
1660     else if (sb == NULL) {
1661       /* too few selected warning */
1662       BKE_reportf(
1663           op->reports,
1664           RPT_WARNING,
1665           "Too few clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
1666           nlt->name);
1667     }
1668     else {
1669       float nsa[2], nsb[2];
1670
1671       /* remove these strips from the track,
1672        * so that we can test if they can fit in the proposed places */
1673       BLI_remlink(&nlt->strips, area);
1674       BLI_remlink(&nlt->strips, sb);
1675
1676       /* calculate new extents for strips */
1677       /* a --> b */
1678       nsa[0] = sb->start;
1679       nsa[1] = sb->start + (area->end - area->start);
1680       /* b --> a */
1681       nsb[0] = area->start;
1682       nsb[1] = area->start + (sb->end - sb->start);
1683
1684       /* check if the track has room for the strips to be swapped */
1685       if (BKE_nlastrips_has_space(&nlt->strips, nsa[0], nsa[1]) &&
1686           BKE_nlastrips_has_space(&nlt->strips, nsb[0], nsb[1])) {
1687         /* set new extents for strips then */
1688         area->start = nsa[0];
1689         area->end = nsa[1];
1690         BKE_nlameta_flush_transforms(area);
1691
1692         sb->start = nsb[0];
1693         sb->end = nsb[1];
1694         BKE_nlameta_flush_transforms(sb);
1695       }
1696       else {
1697         /* not enough room to swap, so show message */
1698         if ((area->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) {
1699           BKE_report(
1700               op->reports,
1701               RPT_WARNING,
1702               "Cannot swap selected strips as they will not be able to fit in their new places");
1703         }
1704         else {
1705           BKE_reportf(op->reports,
1706                       RPT_WARNING,
1707                       "Cannot swap '%s' and '%s' as one or both will not be able to fit in their "
1708                       "new places",
1709                       area->name,
1710                       sb->name);
1711         }
1712       }
1713
1714       /* add strips back to track now */
1715       BKE_nlatrack_add_strip(nlt, area, is_liboverride);
1716       BKE_nlatrack_add_strip(nlt, sb, is_liboverride);
1717     }
1718
1719     /* clear (temp) metastrips */
1720     BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
1721   }
1722
1723   /* free temp data */
1724   ANIM_animdata_freelist(&anim_data);
1725
1726   /* refresh auto strip properties */
1727   ED_nla_postop_refresh(&ac);
1728
1729   /* set notifier that things have changed */
1730   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
1731   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ORDER, NULL);
1732
1733   /* done */
1734   return OPERATOR_FINISHED;
1735 }
1736
1737 void NLA_OT_swap(wmOperatorType *ot)
1738 {
1739   /* identifiers */
1740   ot->name = "Swap Strips";
1741   ot->idname = "NLA_OT_swap";
1742   ot->description = "Swap order of selected strips within tracks";
1743
1744   /* api callbacks */
1745   ot->exec = nlaedit_swap_exec;
1746   ot->poll = nlaop_poll_tweakmode_off;
1747
1748   /* flags */
1749   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1750 }
1751
1752 /** \} */
1753
1754 /* -------------------------------------------------------------------- */
1755 /** \name Move Strips Up Operator
1756  *
1757  * Tries to move the selected strips into the track above if possible.
1758  * \{ */
1759
1760 static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
1761 {
1762   bAnimContext ac;
1763
1764   ListBase anim_data = {NULL, NULL};
1765   bAnimListElem *ale;
1766   int filter;
1767
1768   /* get editor data */
1769   if (ANIM_animdata_get_context(C, &ac) == 0) {
1770     return OPERATOR_CANCELLED;
1771   }
1772
1773   /* get a list of the editable tracks being shown in the NLA */
1774   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1775   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1776
1777   /* since we're potentially moving strips from lower tracks to higher tracks, we should
1778    * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks
1779    */
1780   for (ale = anim_data.last; ale; ale = ale->prev) {
1781     NlaTrack *nlt = (NlaTrack *)ale->data;
1782     NlaTrack *nltn = nlt->next;
1783     NlaStrip *strip, *stripn;
1784
1785     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1786
1787     /* if this track has no tracks after it, skip for now... */
1788     if (nltn == NULL) {
1789       continue;
1790     }
1791
1792     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) ||
1793         BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltn)) {
1794       /* No moving of strips in non-local tracks of override data. */
1795       continue;
1796     }
1797
1798     /* for every selected strip, try to move */
1799     for (strip = nlt->strips.first; strip; strip = stripn) {
1800       stripn = strip->next;
1801
1802       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1803         /* check if the track above has room for this strip */
1804         if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
1805           /* remove from its current track, and add to the one above
1806            * (it 'should' work, so no need to worry) */
1807           BLI_remlink(&nlt->strips, strip);
1808           BKE_nlatrack_add_strip(nltn, strip, is_liboverride);
1809         }
1810       }
1811     }
1812   }
1813
1814   /* free temp data */
1815   ANIM_animdata_freelist(&anim_data);
1816
1817   /* refresh auto strip properties */
1818   ED_nla_postop_refresh(&ac);
1819
1820   /* set notifier that things have changed */
1821   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
1822   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ORDER, NULL);
1823
1824   /* done */
1825   return OPERATOR_FINISHED;
1826 }
1827
1828 void NLA_OT_move_up(wmOperatorType *ot)
1829 {
1830   /* identifiers */
1831   ot->name = "Move Strips Up";
1832   ot->idname = "NLA_OT_move_up";
1833   ot->description = "Move selected strips up a track if there's room";
1834
1835   /* api callbacks */
1836   ot->exec = nlaedit_move_up_exec;
1837   ot->poll = nlaop_poll_tweakmode_off;
1838
1839   /* flags */
1840   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1841 }
1842
1843 /** \} */
1844
1845 /* -------------------------------------------------------------------- */
1846 /** \name Move Strips Down Operator
1847  *
1848  * Tries to move the selected strips into the track above if possible.
1849  * \{ */
1850
1851 static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
1852 {
1853   bAnimContext ac;
1854
1855   ListBase anim_data = {NULL, NULL};
1856   bAnimListElem *ale;
1857   int filter;
1858
1859   /* get editor data */
1860   if (ANIM_animdata_get_context(C, &ac) == 0) {
1861     return OPERATOR_CANCELLED;
1862   }
1863
1864   /* get a list of the editable tracks being shown in the NLA */
1865   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1866   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1867
1868   /* loop through the tracks in normal order, since we're pushing strips down,
1869    * strips won't get operated on twice
1870    */
1871   for (ale = anim_data.first; ale; ale = ale->next) {
1872     NlaTrack *nlt = (NlaTrack *)ale->data;
1873     NlaTrack *nltp = nlt->prev;
1874     NlaStrip *strip, *stripn;
1875
1876     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1877
1878     /* if this track has no tracks before it, skip for now... */
1879     if (nltp == NULL) {
1880       continue;
1881     }
1882
1883     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt) ||
1884         BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nltp)) {
1885       /* No moving of strips in non-local tracks of override data. */
1886       continue;
1887     }
1888
1889     /* for every selected strip, try to move */
1890     for (strip = nlt->strips.first; strip; strip = stripn) {
1891       stripn = strip->next;
1892
1893       if (strip->flag & NLASTRIP_FLAG_SELECT) {
1894         /* check if the track below has room for this strip */
1895         if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
1896           /* remove from its current track, and add to the one above
1897            * (it 'should' work, so no need to worry) */
1898           BLI_remlink(&nlt->strips, strip);
1899           BKE_nlatrack_add_strip(nltp, strip, is_liboverride);
1900         }
1901       }
1902     }
1903   }
1904
1905   /* free temp data */
1906   ANIM_animdata_freelist(&anim_data);
1907
1908   /* refresh auto strip properties */
1909   ED_nla_postop_refresh(&ac);
1910
1911   /* set notifier that things have changed */
1912   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
1913   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ORDER, NULL);
1914
1915   /* done */
1916   return OPERATOR_FINISHED;
1917 }
1918
1919 void NLA_OT_move_down(wmOperatorType *ot)
1920 {
1921   /* identifiers */
1922   ot->name = "Move Strips Down";
1923   ot->idname = "NLA_OT_move_down";
1924   ot->description = "Move selected strips down a track if there's room";
1925
1926   /* api callbacks */
1927   ot->exec = nlaedit_move_down_exec;
1928   ot->poll = nlaop_poll_tweakmode_off;
1929
1930   /* flags */
1931   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1932 }
1933
1934 /** \} */
1935
1936 /* -------------------------------------------------------------------- */
1937 /** \name Sync Action Length Operator
1938  *
1939  * Recalculate the extents of the action ranges used for the selected strips.
1940  * \{ */
1941
1942 static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op)
1943 {
1944   bAnimContext ac;
1945
1946   ListBase anim_data = {NULL, NULL};
1947   bAnimListElem *ale;
1948   int filter;
1949   const bool active_only = RNA_boolean_get(op->ptr, "active");
1950
1951   /* get editor data */
1952   if (ANIM_animdata_get_context(C, &ac) == 0) {
1953     return OPERATOR_CANCELLED;
1954   }
1955
1956   /* get a list of the editable tracks being shown in the NLA */
1957   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
1958   if (active_only) {
1959     filter |= ANIMFILTER_ACTIVE;
1960   }
1961   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1962
1963   /* for each NLA-Track, apply scale of all selected strips */
1964   for (ale = anim_data.first; ale; ale = ale->next) {
1965     NlaTrack *nlt = (NlaTrack *)ale->data;
1966     NlaStrip *strip;
1967
1968     for (strip = nlt->strips.first; strip; strip = strip->next) {
1969       /* strip selection/active status check */
1970       if (active_only) {
1971         if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
1972           continue;
1973         }
1974       }
1975       else {
1976         if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) {
1977           continue;
1978         }
1979       }
1980
1981       /* must be action-clip only (transitions don't have scale) */
1982       if (strip->type == NLASTRIP_TYPE_CLIP) {
1983         if (strip->act == NULL) {
1984           continue;
1985         }
1986
1987         BKE_nlastrip_recalculate_bounds_sync_action(strip);
1988
1989         ale->update |= ANIM_UPDATE_DEPS;
1990       }
1991     }
1992   }
1993
1994   /* free temp data */
1995   ANIM_animdata_update(&ac, &anim_data);
1996   ANIM_animdata_freelist(&anim_data);
1997
1998   /* set notifier that things have changed */
1999   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
2000
2001   /* done */
2002   return OPERATOR_FINISHED;
2003 }
2004
2005 void NLA_OT_action_sync_length(wmOperatorType *ot)
2006 {
2007   /* identifiers */
2008   ot->name = "Sync Action Length";
2009   ot->idname = "NLA_OT_action_sync_length";
2010   ot->description =
2011       "Synchronize the length of the referenced Action with the length used in the strip";
2012
2013   /* api callbacks */
2014   ot->exec = nlaedit_sync_actlen_exec;
2015   ot->poll = nlaop_poll_tweakmode_off;
2016
2017   /* flags */
2018   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2019
2020   /* properties */
2021   ot->prop = RNA_def_boolean(ot->srna,
2022                              "active",
2023                              1,
2024                              "Active Strip Only",
2025                              "Only sync the active length for the active strip");
2026 }
2027
2028 /** \} */
2029
2030 /* -------------------------------------------------------------------- */
2031 /** \name Make Single User
2032  *
2033  * Ensure that each strip has its own action.
2034  * \{ */
2035
2036 static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op))
2037 {
2038   Main *bmain = CTX_data_main(C);
2039   bAnimContext ac;
2040
2041   ListBase anim_data = {NULL, NULL};
2042   bAnimListElem *ale;
2043   int filter;
2044   bool copied = false;
2045
2046   /* get editor data */
2047   if (ANIM_animdata_get_context(C, &ac) == 0) {
2048     return OPERATOR_CANCELLED;
2049   }
2050
2051   /* get a list of the editable tracks being shown in the NLA */
2052   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2053   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2054
2055   /* Ensure that each action used only has a single user
2056    *   - This is done in reverse order so that the original strips are
2057    *     likely to still get to keep their action
2058    */
2059   for (ale = anim_data.last; ale; ale = ale->prev) {
2060     NlaTrack *nlt = (NlaTrack *)ale->data;
2061     NlaStrip *strip;
2062
2063     for (strip = nlt->strips.last; strip; strip = strip->prev) {
2064       /* must be action-clip only (as only these have actions) */
2065       if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
2066         if (strip->act == NULL) {
2067           continue;
2068         }
2069
2070         /* multi-user? */
2071         if (ID_REAL_USERS(strip->act) > 1) {
2072           /* make a new copy of the action for us to use (it will have 1 user already) */
2073           bAction *new_action = (bAction *)BKE_id_copy(bmain, &strip->act->id);
2074
2075           /* decrement user count of our existing action */
2076           id_us_min(&strip->act->id);
2077
2078           /* switch to the new copy */
2079           strip->act = new_action;
2080
2081           ale->update |= ANIM_UPDATE_DEPS;
2082           copied = true;
2083         }
2084       }
2085     }
2086   }
2087
2088   /* free temp data */
2089   ANIM_animdata_update(&ac, &anim_data);
2090   ANIM_animdata_freelist(&anim_data);
2091
2092   if (copied) {
2093     DEG_relations_tag_update(ac.bmain);
2094   }
2095
2096   /* set notifier that things have changed */
2097   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
2098
2099   /* done */
2100   return OPERATOR_FINISHED;
2101 }
2102
2103 void NLA_OT_make_single_user(wmOperatorType *ot)
2104 {
2105   /* identifiers */
2106   ot->name = "Make Single User";
2107   ot->idname = "NLA_OT_make_single_user";
2108   ot->description = "Ensure that each action is only used once in the set of strips selected";
2109
2110   /* api callbacks */
2111   ot->invoke = WM_operator_confirm;
2112   ot->exec = nlaedit_make_single_user_exec;
2113   ot->poll = nlaop_poll_tweakmode_off;
2114
2115   /* flags */
2116   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2117 }
2118
2119 /** \} */
2120
2121 /* -------------------------------------------------------------------- */
2122 /** \name Apply Scale Operator
2123  *
2124  * Reset the scaling of the selected strips to 1.0f.
2125  * \{ */
2126
2127 /* apply scaling to keyframe */
2128 static short bezt_apply_nlamapping(KeyframeEditData *ked, BezTriple *bezt)
2129 {
2130   /* NLA-strip which has this scaling is stored in ked->data */
2131   NlaStrip *strip = (NlaStrip *)ked->data;
2132
2133   /* adjust all the times */
2134   bezt->vec[0][0] = nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP);
2135   bezt->vec[1][0] = nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP);
2136   bezt->vec[2][0] = nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP);
2137
2138   /* nothing to return or else we exit */
2139   return 0;
2140 }
2141
2142 static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
2143 {
2144   Main *bmain = CTX_data_main(C);
2145   bAnimContext ac;
2146
2147   ListBase anim_data = {NULL, NULL};
2148   bAnimListElem *ale;
2149   int filter;
2150   bool copied = false;
2151
2152   KeyframeEditData ked = {{NULL}};
2153
2154   /* get editor data */
2155   if (ANIM_animdata_get_context(C, &ac) == 0) {
2156     return OPERATOR_CANCELLED;
2157   }
2158
2159   /* get a list of the editable tracks being shown in the NLA */
2160   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2161   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2162
2163   /* for each NLA-Track, apply scale of all selected strips */
2164   for (ale = anim_data.first; ale; ale = ale->next) {
2165     NlaTrack *nlt = (NlaTrack *)ale->data;
2166     NlaStrip *strip;
2167
2168     for (strip = nlt->strips.first; strip; strip = strip->next) {
2169       /* strip must be selected, and must be action-clip only
2170        * (transitions don't have scale) */
2171       if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
2172         if (strip->act == NULL || ID_IS_OVERRIDE_LIBRARY(strip->act) || ID_IS_LINKED(strip->act)) {
2173           continue;
2174         }
2175         /* if the referenced action is used by other strips,
2176          * make this strip use its own copy */
2177         if (strip->act->id.us > 1) {
2178           /* make a copy of the Action to work on */
2179           bAction *act = (bAction *)BKE_id_copy(bmain, &strip->act->id);
2180
2181           /* set this as the new referenced action,
2182            * decrementing the users of the old one */
2183           id_us_min(&strip->act->id);
2184           strip->act = act;
2185
2186           copied = true;
2187         }
2188
2189         /* setup iterator, and iterate over all the keyframes in the action,
2190          * applying this scaling */
2191         ked.data = strip;
2192         ANIM_animchanneldata_keyframes_loop(
2193             &ked, ac.ads, strip->act, ALE_ACT, NULL, bezt_apply_nlamapping, calchandles_fcurve);
2194
2195         /* clear scale of strip now that it has been applied,
2196          * and recalculate the extents of the action now that it has been scaled
2197          * but leave everything else alone
2198          */
2199         strip->scale = 1.0f;
2200         calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
2201
2202         ale->update |= ANIM_UPDATE_DEPS;
2203       }
2204     }
2205   }
2206
2207   /* free temp data */
2208   ANIM_animdata_update(&ac, &anim_data);
2209   ANIM_animdata_freelist(&anim_data);
2210
2211   if (copied) {
2212     DEG_relations_tag_update(ac.bmain);
2213   }
2214
2215   /* set notifier that things have changed */
2216   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
2217
2218   /* done */
2219   return OPERATOR_FINISHED;
2220 }
2221
2222 void NLA_OT_apply_scale(wmOperatorType *ot)
2223 {
2224   /* identifiers */
2225   ot->name = "Apply Scale";
2226   ot->idname = "NLA_OT_apply_scale";
2227   ot->description = "Apply scaling of selected strips to their referenced Actions";
2228
2229   /* api callbacks */
2230   ot->exec = nlaedit_apply_scale_exec;
2231   ot->poll = nlaop_poll_tweakmode_off;
2232
2233   /* flags */
2234   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2235 }
2236
2237 /** \} */
2238
2239 /* -------------------------------------------------------------------- */
2240 /** \name Clear Scale Operator
2241  *
2242  * Reset the scaling of the selected strips to 1.0f.
2243  * \{ */
2244
2245 static int nlaedit_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
2246 {
2247   bAnimContext ac;
2248
2249   ListBase anim_data = {NULL, NULL};
2250   bAnimListElem *ale;
2251   int filter;
2252
2253   /* get editor data */
2254   if (ANIM_animdata_get_context(C, &ac) == 0) {
2255     return OPERATOR_CANCELLED;
2256   }
2257
2258   /* get a list of the editable tracks being shown in the NLA */
2259   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2260   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2261
2262   /* for each NLA-Track, reset scale of all selected strips */
2263   for (ale = anim_data.first; ale; ale = ale->next) {
2264     NlaTrack *nlt = (NlaTrack *)ale->data;
2265     NlaStrip *strip;
2266
2267     for (strip = nlt->strips.first; strip; strip = strip->next) {
2268       /* strip must be selected, and must be action-clip only
2269        * (transitions don't have scale) */
2270       if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
2271         PointerRNA strip_ptr;
2272
2273         RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
2274         RNA_float_set(&strip_ptr, "scale", 1.0f);
2275       }
2276     }
2277   }
2278
2279   /* free temp data */
2280   ANIM_animdata_freelist(&anim_data);
2281
2282   /* refresh auto strip properties */
2283   ED_nla_postop_refresh(&ac);
2284
2285   /* set notifier that things have changed */
2286   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
2287
2288   /* done */
2289   return OPERATOR_FINISHED;
2290 }
2291
2292 void NLA_OT_clear_scale(wmOperatorType *ot)
2293 {
2294   /* identifiers */
2295   ot->name = "Clear Scale";
2296   ot->idname = "NLA_OT_clear_scale";
2297   ot->description = "Reset scaling of selected strips";
2298
2299   /* api callbacks */
2300   ot->exec = nlaedit_clear_scale_exec;
2301   ot->poll = nlaop_poll_tweakmode_off;
2302
2303   /* flags */
2304   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2305 }
2306
2307 /** \} */
2308
2309 /* -------------------------------------------------------------------- */
2310 /** \name Snap Strips Operator
2311  *
2312  * Moves the start-point of the selected strips to the specified places.
2313  * \{ */
2314
2315 /* defines for snap keyframes tool */
2316 static const EnumPropertyItem prop_nlaedit_snap_types[] = {
2317     {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Selection to Current Frame", ""},
2318     /* XXX as single entry? */
2319     {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Selection to Nearest Frame", ""},
2320     /* XXX as single entry? */
2321     {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Selection to Nearest Second", ""},
2322     {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Selection to Nearest Marker", ""},
2323     {0, NULL, 0, NULL, NULL},
2324 };
2325
2326 static int nlaedit_snap_exec(bContext *C, wmOperator *op)
2327 {
2328   bAnimContext ac;
2329
2330   ListBase anim_data = {NULL, NULL};
2331   bAnimListElem *ale;
2332   int filter;
2333
2334   Scene *scene;
2335   int mode = RNA_enum_get(op->ptr, "type");
2336   float secf;
2337
2338   /* get editor data */
2339   if (ANIM_animdata_get_context(C, &ac) == 0) {
2340     return OPERATOR_CANCELLED;
2341   }
2342
2343   /* get a list of the editable tracks being shown in the NLA */
2344   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2345   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2346
2347   /* get some necessary vars */
2348   scene = ac.scene;
2349   secf = (float)FPS;
2350
2351   bool any_added = false;
2352
2353   /* since we may add tracks, perform this in reverse order */
2354   for (ale = anim_data.last; ale; ale = ale->prev) {
2355     ListBase tmp_strips = {NULL, NULL};
2356     AnimData *adt = ale->adt;
2357     NlaTrack *nlt = (NlaTrack *)ale->data;
2358     NlaStrip *strip, *stripn;
2359     NlaTrack *track;
2360
2361     const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
2362
2363     /* create meta-strips from the continuous chains of selected strips */
2364     BKE_nlastrips_make_metas(&nlt->strips, 1);
2365
2366     /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added
2367      * back to the original only if they still fit
2368      */
2369     for (strip = nlt->strips.first; strip; strip = stripn) {
2370       stripn = strip->next;
2371
2372       if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
2373         float start, end;
2374
2375         /* get the existing end-points */
2376         start = strip->start;
2377         end = strip->end;
2378
2379         /* calculate new start position based on snapping mode */
2380         switch (mode) {
2381           case NLAEDIT_SNAP_CFRA: /* to current frame */
2382             strip->start = (float)CFRA;
2383             break;
2384           case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */
2385             strip->start = floorf(start + 0.5f);
2386             break;
2387           case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */
2388             strip->start = floorf(start / secf + 0.5f) * secf;
2389             break;
2390           case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */
2391             strip->start = (float)ED_markers_find_nearest_marker_time(ac.markers, start);
2392             break;
2393           default: /* just in case... no snapping */
2394             strip->start = start;
2395             break;
2396         }
2397
2398         /* get new endpoint based on start-point (and old length) */
2399         strip->end = strip->start + (end - start);
2400
2401         /* apply transforms to meta-strip to its children */
2402         BKE_nlameta_flush_transforms(strip);
2403
2404         /* remove strip from track, and add to the temp buffer */
2405         BLI_remlink(&nlt->strips, strip);
2406         BLI_addtail(&tmp_strips, strip);
2407       }
2408     }
2409
2410     /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */
2411     for (strip = tmp_strips.first; strip; strip = stripn) {
2412       stripn = strip->next;
2413
2414       /* remove from temp-strips list */
2415       BLI_remlink(&tmp_strips, strip);
2416
2417       /* in case there's no space in the current track, try adding */
2418       if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
2419         /* need to add a new track above the current one */
2420         track = BKE_nlatrack_add(adt, nlt, is_liboverride);
2421         BKE_nlatrack_add_strip(track, strip, is_liboverride);
2422
2423         /* clear temp meta-strips on this new track,
2424          * as we may not be able to get back to it */
2425         BKE_nlastrips_clear_metas(&track->strips, 0, 1);
2426
2427         any_added = true;
2428       }
2429     }
2430
2431     /* remove the meta-strips now that we're done */
2432     BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
2433
2434     /* tag for recalculating the animation */
2435     ale->update |= ANIM_UPDATE_DEPS;
2436   }
2437
2438   /* cleanup */
2439   ANIM_animdata_update(&ac, &anim_data);
2440   ANIM_animdata_freelist(&anim_data);
2441
2442   /* refresh auto strip properties */
2443   ED_nla_postop_refresh(&ac);
2444
2445   /* set notifier that things have changed */
2446   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
2447   if (any_added) {
2448     WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
2449   }
2450
2451   /* done */
2452   return OPERATOR_FINISHED;
2453 }
2454
2455 void NLA_OT_snap(wmOperatorType *ot)
2456 {
2457   /* identifiers */
2458   ot->name = "Snap Strips";
2459   ot->idname = "NLA_OT_snap";
2460   ot->description = "Move start of strips to specified time";
2461
2462   /* api callbacks */
2463   ot->invoke = WM_menu_invoke;
2464   ot->exec = nlaedit_snap_exec;
2465   ot->poll = nlaop_poll_tweakmode_off;
2466
2467   /* flags */
2468   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2469
2470   /* properties */
2471   ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
2472 }
2473
2474 /** \} */
2475
2476 /* NLA Modifiers */
2477
2478 /* -------------------------------------------------------------------- */
2479 /** \name Add F-Modifier Operator
2480  * \{ */
2481
2482 static const EnumPropertyItem *nla_fmodifier_itemf(bContext *C,
2483                                                    PointerRNA *UNUSED(ptr),
2484                                                    PropertyRNA *UNUSED(prop),
2485                                                    bool *r_free)
2486 {
2487   EnumPropertyItem *item = NULL;
2488   int totitem = 0;
2489   int i = 0;
2490
2491   if (C == NULL) {
2492     return rna_enum_fmodifier_type_items;
2493   }
2494
2495   /* start from 1 to skip the 'Invalid' modifier type */
2496   for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
2497     const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
2498     int index;
2499
2500     /* check if modifier is valid for this context */
2501     if (fmi == NULL) {
2502       continue;
2503     }
2504     if (i == FMODIFIER_TYPE_CYCLES) { /* we already have repeat... */
2505       continue;
2506     }
2507
2508     index = RNA_enum_from_value(rna_enum_fmodifier_type_items, fmi->type);
2509     if (index != -1) { /* Not all types are implemented yet... */
2510       RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
2511     }
2512   }
2513
2514   RNA_enum_item_end(&item, &totitem);
2515   *r_free = true;
2516
2517   return item;
2518 }
2519
2520 static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
2521 {
2522   bAnimContext ac;
2523
2524   ListBase anim_data = {NULL, NULL};
2525   bAnimListElem *ale;
2526   int filter;
2527
2528   FModifier *fcm;
2529   int type = RNA_enum_get(op->ptr, "type");
2530   const bool active_only = RNA_boolean_get(op->ptr, "only_active");
2531
2532   /* get editor data */
2533   if (ANIM_animdata_get_context(C, &ac) == 0) {
2534     return OPERATOR_CANCELLED;
2535   }
2536
2537   /* get a list of the editable tracks being shown in the NLA */
2538   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2539   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2540
2541   /* for each NLA-Track, add the specified modifier to all selected strips */
2542   for (ale = anim_data.first; ale; ale = ale->next) {
2543     NlaTrack *nlt = (NlaTrack *)ale->data;
2544     NlaStrip *strip;
2545
2546     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
2547       /* No adding f-modifiers to strips in non-local tracks of override data. */
2548       continue;
2549     }
2550
2551     for (strip = nlt->strips.first; strip; strip = strip->next) {
2552       /* can F-Modifier be added to the current strip? */
2553       if (active_only) {
2554         /* if not active, cannot add since we're only adding to active strip */
2555         if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
2556           continue;
2557         }
2558       }
2559       else {
2560         /* strip must be selected, since we're not just doing active */
2561         if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) {
2562           continue;
2563         }
2564       }
2565
2566       /* sound clips are not affected by FModifiers */
2567       if (strip->type == NLASTRIP_TYPE_SOUND) {
2568         continue;
2569       }
2570
2571       /* add F-Modifier of specified type to selected, and make it the active one */
2572       fcm = add_fmodifier(&strip->modifiers, type, NULL);
2573
2574       if (fcm) {
2575         set_active_fmodifier(&strip->modifiers, fcm);
2576         ale->update |= ANIM_UPDATE_DEPS;
2577       }
2578       else {
2579         BKE_reportf(op->reports,
2580                     RPT_ERROR,
2581                     "Modifier could not be added to (%s : %s) (see console for details)",
2582                     nlt->name,
2583                     strip->name);
2584       }
2585     }
2586   }
2587
2588   /* free temp data */
2589   ANIM_animdata_update(&ac, &anim_data);
2590   ANIM_animdata_freelist(&anim_data);
2591
2592   /* set notifier that things have changed */
2593   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
2594
2595   /* done */
2596   return OPERATOR_FINISHED;
2597 }
2598
2599 void NLA_OT_fmodifier_add(wmOperatorType *ot)
2600 {
2601   /* identifiers */
2602   ot->name = "Add F-Modifier";
2603   ot->idname = "NLA_OT_fmodifier_add";
2604   ot->description = "Add F-Modifier to the active/selected NLA-Strips";
2605
2606   /* api callbacks */
2607   ot->invoke = WM_menu_invoke;
2608   ot->exec = nla_fmodifier_add_exec;
2609   ot->poll = nlaop_poll_tweakmode_off;
2610
2611   /* flags */
2612   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2613
2614   /* id-props */
2615   ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
2616   RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION);
2617   RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
2618
2619   RNA_def_boolean(ot->srna,
2620                   "only_active",
2621                   true,
2622                   "Only Active",
2623                   "Only add a F-Modifier of the specified type to the active strip");
2624 }
2625
2626 /** \} */
2627
2628 /* -------------------------------------------------------------------- */
2629 /** \name Copy F-Modifiers Operator
2630  * \{ */
2631
2632 static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
2633 {
2634   bAnimContext ac;
2635   ListBase anim_data = {NULL, NULL};
2636   bAnimListElem *ale;
2637   int filter;
2638   bool ok = false;
2639
2640   /* get editor data */
2641   if (ANIM_animdata_get_context(C, &ac) == 0) {
2642     return OPERATOR_CANCELLED;
2643   }
2644
2645   /* clear buffer first */
2646   ANIM_fmodifiers_copybuf_free();
2647
2648   /* get a list of the editable tracks being shown in the NLA */
2649   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2650   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2651
2652   /* for each NLA-Track, add the specified modifier to all selected strips */
2653   for (ale = anim_data.first; ale; ale = ale->next) {
2654     NlaTrack *nlt = (NlaTrack *)ale->data;
2655     NlaStrip *strip;
2656
2657     for (strip = nlt->strips.first; strip; strip = strip->next) {
2658       /* only add F-Modifier if on active strip? */
2659       if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
2660         continue;
2661       }
2662
2663       /* TODO: when 'active' vs 'all' boolean is added, change last param! */
2664       ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
2665     }
2666   }
2667
2668   /* free temp data */
2669   ANIM_animdata_freelist(&anim_data);
2670
2671   /* successful or not? */
2672   if (ok == 0) {
2673     BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
2674     return OPERATOR_CANCELLED;
2675   }
2676
2677   /* no updates needed - copy is non-destructive operation */
2678   return OPERATOR_FINISHED;
2679 }
2680
2681 void NLA_OT_fmodifier_copy(wmOperatorType *ot)
2682 {
2683   /* identifiers */
2684   ot->name = "Copy F-Modifiers";
2685   ot->idname = "NLA_OT_fmodifier_copy";
2686   ot->description = "Copy the F-Modifier(s) of the active NLA-Strip";
2687
2688   /* api callbacks */
2689   ot->exec = nla_fmodifier_copy_exec;
2690   ot->poll = nlaop_poll_tweakmode_off;
2691
2692   /* flags */
2693   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2694
2695   /* id-props */
2696 #if 0
2697   ot->prop = RNA_def_boolean(ot->srna,
2698                              "all",
2699                              1,
2700                              "All F-Modifiers",
2701                              "Copy all the F-Modifiers, instead of just the active one");
2702 #endif
2703 }
2704
2705 /** \} */
2706
2707 /* -------------------------------------------------------------------- */
2708 /** \name Paste F-Modifiers Operator
2709  * \{ */
2710
2711 static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
2712 {
2713   bAnimContext ac;
2714   ListBase anim_data = {NULL, NULL};
2715   bAnimListElem *ale;
2716   int filter, ok = 0;
2717
2718   const bool active_only = RNA_boolean_get(op->ptr, "only_active");
2719   const bool replace = RNA_boolean_get(op->ptr, "replace");
2720
2721   /* get editor data */
2722   if (ANIM_animdata_get_context(C, &ac) == 0) {
2723     return OPERATOR_CANCELLED;
2724   }
2725
2726   /* get a list of the editable tracks being shown in the NLA */
2727   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
2728             ANIMFILTER_NODUPLIS);
2729   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2730
2731   /* for each NLA-Track, add the specified modifier to all selected strips */
2732   for (ale = anim_data.first; ale; ale = ale->next) {
2733     NlaTrack *nlt = (NlaTrack *)ale->data;
2734     NlaStrip *strip;
2735
2736     if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
2737       /* No pasting in non-local tracks of override data. */
2738       continue;
2739     }
2740
2741     for (strip = nlt->strips.first; strip; strip = strip->next) {
2742       /* can F-Modifier be added to the current strip? */
2743       if (active_only) {
2744         /* if not active, cannot add since we're only adding to active strip */
2745         if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
2746           continue;
2747         }
2748       }
2749       else {
2750         /* strip must be selected, since we're not just doing active */
2751         if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) {
2752           continue;
2753         }
2754       }
2755
2756       /* paste FModifiers from buffer */
2757       ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL);
2758       ale->update |= ANIM_UPDATE_DEPS;
2759     }
2760   }
2761
2762   /* clean up */
2763   ANIM_animdata_update(&ac, &anim_data);
2764   ANIM_animdata_freelist(&anim_data);
2765
2766   /* successful or not? */
2767   if (ok) {
2768     WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
2769     return OPERATOR_FINISHED;
2770   }
2771
2772   BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
2773   return OPERATOR_CANCELLED;
2774 }
2775
2776 void NLA_OT_fmodifier_paste(wmOperatorType *ot)
2777 {
2778   /* identifiers */
2779   ot->name = "Paste F-Modifiers";
2780   ot->idname = "NLA_OT_fmodifier_paste";
2781   ot->description = "Add copied F-Modifiers to the selected NLA-Strips";
2782
2783   /* api callbacks */
2784   ot->exec = nla_fmodifier_paste_exec;
2785   ot->poll = nlaop_poll_tweakmode_off;
2786
2787   /* flags */
2788   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2789
2790   /* properties */
2791   RNA_def_boolean(
2792       ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
2793   RNA_def_boolean(
2794       ot->srna,
2795       "replace",
2796       false,
2797       "Replace Existing",
2798       "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
2799 }
2800
2801 /** \} */