Blender  V2.93
nla_edit.c
Go to the documentation of this file.
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 
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 /* -------------------------------------------------------------------- */
74 /* Perform validation for blending/extend settings */
76 {
77  ListBase anim_data = {NULL, NULL};
78  bAnimListElem *ale;
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. */
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 
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 /* -------------------------------------------------------------------- */
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 */
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) {
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 */
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 
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 */
189 
190  /* flags */
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");
201 }
202 
205 /* -------------------------------------------------------------------- */
209 /* NLA Editor internal API function for exiting tweakmode */
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 */
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)) {
233  }
234 
235  /* to be sure that we're doing everything right, just exit tweakmode... */
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 */
254  }
255 
256  /* done */
257  return true;
258 }
259 
260 /* exit tweakmode operator callback */
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 
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 */
295 
296  /* flags */
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");
307 }
308 
311 /* NLA Strips Range Stuff */
312 
313 /* -------------------------------------------------------------------- */
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 */
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 
371 /* -------------------------------------------------------------------- */
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);
397 
398  /* set notifier that things have changed */
399  /* XXX err... there's nothing for frame ranges yet, but this should do fine too */
401 
402  return OPERATOR_FINISHED;
403 }
404 
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 */
415 
416  /* flags */
418 }
419 
422 /* -------------------------------------------------------------------- */
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 */
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)) {
452 
453  /* must be selected... */
454  if (acf && acf->has_setting(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 */
521 
522  /* just redraw this view */
524 
525  return OPERATOR_FINISHED;
526 }
527 
528 /* ......... */
529 
531 {
532  /* whole range */
533  return nlaedit_viewall(C, false);
534 }
535 
537 {
538  /* only selected */
539  return nlaedit_viewall(C, true);
540 }
541 
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 */
552 
553  /* flags */
554  ot->flag = 0;
555 }
556 
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 */
567 
568  /* flags */
569  ot->flag = 0;
570 }
571 
574 /* -------------------------------------------------------------------- */
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 
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 */
595 
596  /* flags */
597  ot->flag = 0;
598 }
599 
602 /* NLA Editing Operations (Constructive/Destructive) */
603 
604 /* -------------------------------------------------------------------- */
611 /* add the specified action as new strip */
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  */
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  */
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 */
719 
721 
722  /* set notifier that things have changed */
724 
725  /* done */
726  return OPERATOR_FINISHED;
727 }
728 
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 */
743 
744  /* flags */
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", "");
752  ot->prop = prop;
753 }
754 
757 /* -------------------------------------------------------------------- */
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 */
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 */
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  */
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 */
856 
857  /* set notifier that things have changed */
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 
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 */
880 
881  /* flags */
883 }
884 
887 /* -------------------------------------------------------------------- */
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 */
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 */
956 
957  /* set notifier that things have changed */
959 
960  /* done */
961  return OPERATOR_FINISHED;
962 }
963 
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 */
974 
975  /* flags */
977 }
978 
981 /* -------------------------------------------------------------------- */
987 /* add the specified action as new strip */
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 */
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 
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 */
1036 
1037  /* done */
1038  return OPERATOR_FINISHED;
1039 }
1040 
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 */
1051 
1052  /* flags */
1054 }
1055 
1058 /* -------------------------------------------------------------------- */
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 */
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 
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 */
1102 
1103  /* done */
1104  return OPERATOR_FINISHED;
1105 }
1106 
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 */
1117 
1118  /* flags */
1120 }
1121 
1124 /* -------------------------------------------------------------------- */
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 */
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 */
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) {
1204  }
1205 
1206  /* set notifier that things have changed */
1208 
1209  /* done */
1210  return OPERATOR_FINISHED;
1211  }
1212 
1213  return OPERATOR_CANCELLED;
1214 }
1215 
1217 {
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 
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 */
1238 
1239  /* flags */
1241 
1242  /* own properties */
1244  "linked",
1245  false,
1246  "Linked",
1247  "When duplicating strips, assign new copies of the actions they use");
1248 
1249  /* to give to transform */
1251 }
1252 
1255 /* -------------------------------------------------------------------- */
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 */
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 
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 
1315 
1316  /* set notifier that things have changed */
1318 
1319  /* done */
1320  return OPERATOR_FINISHED;
1321 }
1322 
1324 {
1325  /* identifiers */
1326  ot->name = "Delete Strips";
1327  ot->idname = "NLA_OT_delete";
1328  ot->description = "Delete selected strips";
1329 
1330  /* api callbacks */
1333 
1334  /* flags */
1336 }
1337 
1340 /* -------------------------------------------------------------------- */
1350 /* split a given Action-Clip strip */
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 
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 */
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 
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 */
1479 
1480  /* done */
1481  return OPERATOR_FINISHED;
1482 }
1483 
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 */
1494 
1495  /* flags */
1497 }
1498 
1501 /* NLA Editing Operations (Modifying) */
1502 
1503 /* -------------------------------------------------------------------- */
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 */
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 */
1550 
1551  /* done */
1552  return OPERATOR_FINISHED;
1553 }
1554 
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 */
1565 
1566  /* flags */
1568 }
1569 
1572 /* -------------------------------------------------------------------- */
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 */
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 
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];
1691 
1692  sb->start = nsb[0];
1693  sb->end = nsb[1];
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 */
1732 
1733  /* done */
1734  return OPERATOR_FINISHED;
1735 }
1736 
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 */
1747 
1748  /* flags */
1750 }
1751 
1754 /* -------------------------------------------------------------------- */
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 */
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 
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 */
1823 
1824  /* done */
1825  return OPERATOR_FINISHED;
1826 }
1827 
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 */
1838 
1839  /* flags */
1841 }
1842 
1845 /* -------------------------------------------------------------------- */
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 */
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 
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 */
1914 
1915  /* done */
1916  return OPERATOR_FINISHED;
1917 }
1918 
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 */
1929 
1930  /* flags */
1932 }
1933 
1936 /* -------------------------------------------------------------------- */
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 */
1958  if (active_only) {
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 
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 */
2000 
2001  /* done */
2002  return OPERATOR_FINISHED;
2003 }
2004 
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 */
2016 
2017  /* flags */
2019 
2020  /* properties */
2022  "active",
2023  1,
2024  "Active Strip Only",
2025  "Only sync the active length for the active strip");
2026 }
2027 
2030 /* -------------------------------------------------------------------- */
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 */
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) {
2094  }
2095 
2096  /* set notifier that things have changed */
2098 
2099  /* done */
2100  return OPERATOR_FINISHED;
2101 }
2102 
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 */
2114 
2115  /* flags */
2117 }
2118 
2121 /* -------------------------------------------------------------------- */
2127 /* apply scaling to keyframe */
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 
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 */
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;
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) {
2213  }
2214 
2215  /* set notifier that things have changed */
2217 
2218  /* done */
2219  return OPERATOR_FINISHED;
2220 }
2221 
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 */
2232 
2233  /* flags */
2235 }
2236 
2239 /* -------------------------------------------------------------------- */
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 */
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 */
2287 
2288  /* done */
2289  return OPERATOR_FINISHED;
2290 }
2291 
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 */
2302 
2303  /* flags */
2305 }
2306 
2309 /* -------------------------------------------------------------------- */
2315 /* defines for snap keyframes tool */
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 
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 */
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 */
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 */
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 */
2447  if (any_added) {
2449  }
2450 
2451  /* done */
2452  return OPERATOR_FINISHED;
2453 }
2454 
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 */
2466 
2467  /* flags */
2469 
2470  /* properties */
2471  ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
2472 }
2473 
2476 /* NLA Modifiers */
2477 
2478 /* -------------------------------------------------------------------- */
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) {
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 
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 
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 */
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 
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 */
2594 
2595  /* done */
2596  return OPERATOR_FINISHED;
2597 }
2598 
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 */
2610 
2611  /* flags */
2613 
2614  /* id-props */
2615  ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
2618 
2620  "only_active",
2621  true,
2622  "Only Active",
2623  "Only add a F-Modifier of the specified type to the active strip");
2624 }
2625 
2628 /* -------------------------------------------------------------------- */
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 */
2647 
2648  /* get a list of the editable tracks being shown in the NLA */
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 
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 */
2691 
2692  /* flags */
2694 
2695  /* id-props */
2696 #if 0
2698  "all",
2699  1,
2700  "All F-Modifiers",
2701  "Copy all the F-Modifiers, instead of just the active one");
2702 #endif
2703 }
2704 
2707 /* -------------------------------------------------------------------- */
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 */
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 
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) {
2769  return OPERATOR_FINISHED;
2770  }
2771 
2772  BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
2773  return OPERATOR_CANCELLED;
2774 }
2775 
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 */
2786 
2787  /* flags */
2789 
2790  /* properties */
2792  ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
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 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers)
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:709
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm)
Definition: fmodifier.c:1311
const FModifierTypeInfo * get_fmodifier_typeinfo(const int type)
Definition: fmodifier.c:1072
void calchandles_fcurve(struct FCurve *fcu)
Definition: fcurve.c:1391
struct FModifier * add_fmodifier(ListBase *modifiers, int type, struct FCurve *owner_fcu)
Definition: fmodifier.c:1114
struct ID * BKE_id_copy(struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:297
bool BKE_nlatrack_is_nonlocal_in_liboverride(const struct ID *id, const struct NlaTrack *nlt)
void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip)
Definition: nla.c:807
bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end)
Definition: nla.c:1112
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip)
Definition: nla.c:1626
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
Definition: nla.c:833
void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip)
Definition: nla.c:912
struct NlaStrip * BKE_nla_add_soundstrip(struct Main *bmain, struct Scene *scene, struct Speaker *speaker)
Definition: nla.c:401
@ NLATIME_CONVERT_MAP
Definition: BKE_nla.h:156
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:153
bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
Definition: nla.c:631
void BKE_nla_validate_state(struct AnimData *adt)
Definition: nla.c:1800
struct NlaStrip * BKE_nlastrip_new(struct bAction *act)
Definition: nla.c:327
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt)
Definition: nla.c:1054
bool BKE_nla_tweakmode_enter(struct AnimData *adt)
Definition: nla.c:2034
struct NlaStrip * BKE_nlastrip_copy(struct Main *bmain, struct NlaStrip *strip, const bool use_same_action, const int flag)
Definition: nla.c:169
struct NlaTrack * BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev, bool is_liboverride)
Definition: nla.c:283
void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip)
Definition: nla.c:1389
void BKE_nla_tweakmode_exit(struct AnimData *adt)
Definition: nla.c:2148
bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, const bool is_liboverride)
Definition: nla.c:1149
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user)
Definition: nla.c:72
void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp)
Definition: nla.c:753
struct NlaTrack * BKE_nlatrack_find_tweaked(struct AnimData *adt)
Definition: nla.c:1020
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:352
int BLI_listbase_count_at_most(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int round_fl_to_int(float a)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
#define UNUSED(x)
#define ELEM(...)
#define IS_EQF(a, b)
#define BLT_I18NCONTEXT_ID_ACTION
void DEG_relations_tag_update(struct Main *bmain)
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:413
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:445
@ ID_OB
Definition: DNA_ID_enums.h:59
@ NLASTRIP_FLAG_ACTIVE
@ NLASTRIP_FLAG_TEMP_META
@ NLASTRIP_FLAG_AUTO_BLENDS
@ NLASTRIP_FLAG_MUTED
@ NLASTRIP_FLAG_SELECT
@ ADT_NLA_SOLO_TRACK
@ ADT_NLA_EDIT_ON
@ FMODIFIER_TYPE_CYCLES
@ FMODIFIER_NUM_TYPES
@ NLASTRIP_TYPE_SOUND
@ NLASTRIP_TYPE_META
@ NLASTRIP_TYPE_TRANSITION
@ NLASTRIP_TYPE_CLIP
@ NLATRACK_SOLO
Object is a sort of wrapper for general info.
@ OB_SPEAKER
#define SCE_NLA_EDIT_ON
#define CFRA
#define SCER_PRV_RANGE
#define FPS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define NLACHANNEL_STEP(snla)
Definition: ED_anim_api.h:451
@ ACHANNEL_ROLE_CHANNEL
Definition: ED_anim_api.h:502
@ ALE_ACT
Definition: ED_anim_api.h:266
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:275
#define NLACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:445
@ ACHANNEL_SETTING_SELECT
Definition: ED_anim_api.h:519
#define NLACHANNEL_HEIGHT(snla)
Definition: ED_anim_api.h:447
@ ANIMFILTER_ACTIVE
Definition: ED_anim_api.h:306
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:315
@ ANIMFILTER_ANIMDATA
Definition: ED_anim_api.h:325
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:298
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:303
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:311
void ED_area_tag_redraw(ScrArea *area)
Definition: area.c:745
bool ED_operator_nla_active(struct bContext *C)
Definition: screen_ops.c:334
@ TFM_TRANSLATION
Definition: ED_transform.h:46
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
StructRNA RNA_NlaStrip
const EnumPropertyItem * RNA_action_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free)
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:279
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
Definition: view2d.c:1950
#define V2D_LOCK_COPY
Definition: UI_view2d.h:84
void UI_view2d_sync(struct bScreen *screen, struct ScrArea *area, struct View2D *v2dcur, int flag)
Definition: view2d.c:876
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
Definition: view2d.c:1940
#define ND_NLA_ACTCHANGE
Definition: WM_types.h:398
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NC_ANIMATION
Definition: WM_types.h:289
@ WM_OP_INVOKE_REGION_WIN
Definition: WM_types.h:198
#define NC_SCENE
Definition: WM_types.h:279
#define NA_ADDED
Definition: WM_types.h:464
#define NA_EDITED
Definition: WM_types.h:462
#define ND_FRAME
Definition: WM_types.h:334
#define NA_REMOVED
Definition: WM_types.h:465
#define ND_NLA_ORDER
Definition: WM_types.h:400
#define ND_NLA
Definition: WM_types.h:397
short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
const bAnimChannelType * ANIM_channel_get_typeinfo(bAnimListElem *ale)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:425
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:330
void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
Definition: anim_draw.c:588
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:405
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3442
int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
Definition: anim_markers.c:193
Scene scene
bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *curve)
void ANIM_fmodifiers_copybuf_free(void)
Definition: fmodifier_ui.c:976
bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active)
Definition: fmodifier_ui.c:986
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
#define GS(x)
Definition: iris.c:241
#define floorf(x)
short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static ulong * next
static void area(int d1, int d2, int e1, int e2, float weights[2])
float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode)
Definition: nla.c:562
bool nlaedit_add_tracks_empty(bAnimContext *ac)
Definition: nla_channels.c:682
void NLA_OT_view_frame(wmOperatorType *ot)
Definition: nla_edit.c:585
static int nlaedit_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:375
static int nlaedit_snap_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2326
static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:763
void NLA_OT_view_all(wmOperatorType *ot)
Definition: nla_edit.c:542
void NLA_OT_fmodifier_add(wmOperatorType *ot)
Definition: nla_edit.c:2599
static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:1942
static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1760
void NLA_OT_split(wmOperatorType *ot)
Definition: nla_edit.c:1484
void NLA_OT_tweakmode_exit(wmOperatorType *ot)
Definition: nla_edit.c:283
static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2520
void ED_nla_postop_refresh(bAnimContext *ac)
Definition: nla_edit.c:75
static int nlaedit_viewall(bContext *C, const bool only_sel)
Definition: nla_edit.c:478
static int nlaedit_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:2245
void NLA_OT_soundclip_add(wmOperatorType *ot)
Definition: nla_edit.c:964
void NLA_OT_tweakmode_enter(wmOperatorType *ot)
Definition: nla_edit.c:176
void NLA_OT_clear_scale(wmOperatorType *ot)
Definition: nla_edit.c:2292
void NLA_OT_make_single_user(wmOperatorType *ot)
Definition: nla_edit.c:2103
static int nlaedit_viewall_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:530
void NLA_OT_meta_add(wmOperatorType *ot)
Definition: nla_edit.c:1041
static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const bool only_sel)
Definition: nla_edit.c:318
static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2711
void NLA_OT_meta_remove(wmOperatorType *ot)
Definition: nla_edit.c:1107
void NLA_OT_snap(wmOperatorType *ot)
Definition: nla_edit.c:2455
static const EnumPropertyItem * nla_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: nla_edit.c:2482
static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:261
static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1421
void NLA_OT_swap(wmOperatorType *ot)
Definition: nla_edit.c:1737
void NLA_OT_mute_toggle(wmOperatorType *ot)
Definition: nla_edit.c:1555
void NLA_OT_move_up(wmOperatorType *ot)
Definition: nla_edit.c:1828
static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip)
Definition: nla_edit.c:1413
void NLA_OT_delete(wmOperatorType *ot)
Definition: nla_edit.c:1323
static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:891
static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:2036
void NLA_OT_previewrange_set(wmOperatorType *ot)
Definition: nla_edit.c:405
void NLA_OT_fmodifier_copy(wmOperatorType *ot)
Definition: nla_edit.c:2681
void NLA_OT_move_down(wmOperatorType *ot)
Definition: nla_edit.c:1919
void NLA_OT_transition_add(wmOperatorType *ot)
Definition: nla_edit.c:870
static int nlaedit_viewframe_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:578
static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:988
static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:536
static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:1131
void NLA_OT_view_selected(wmOperatorType *ot)
Definition: nla_edit.c:557
static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:108
static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1261
void NLA_OT_duplicate(wmOperatorType *ot)
Definition: nla_edit.c:1226
static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
Definition: nla_edit.c:1351
bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
Definition: nla_edit.c:210
static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1851
static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:612
void NLA_OT_actionclip_add(wmOperatorType *ot)
Definition: nla_edit.c:729
void NLA_OT_fmodifier_paste(wmOperatorType *ot)
Definition: nla_edit.c:2776
static bool nla_channels_get_selected_extents(bAnimContext *ac, float *r_min, float *r_max)
Definition: nla_edit.c:433
void NLA_OT_action_sync_length(wmOperatorType *ot)
Definition: nla_edit.c:2005
static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2632
static int nlaedit_swap_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:1578
static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1064
void NLA_OT_apply_scale(wmOperatorType *ot)
Definition: nla_edit.c:2222
static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1509
static const EnumPropertyItem prop_nlaedit_snap_types[]
Definition: nla_edit.c:2316
static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:2142
static short bezt_apply_nlamapping(KeyframeEditData *ked, BezTriple *bezt)
Definition: nla_edit.c:2128
static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: nla_edit.c:1216
bool nlaop_poll_tweakmode_on(bContext *C)
Definition: nla_ops.c:67
bool nlaop_poll_tweakmode_off(bContext *C)
Definition: nla_ops.c:43
@ NLAEDIT_SNAP_NEAREST_MARKER
Definition: nla_intern.h:73
@ NLAEDIT_SNAP_NEAREST_SECOND
Definition: nla_intern.h:72
@ NLAEDIT_SNAP_NEAREST_FRAME
Definition: nla_intern.h:71
@ NLAEDIT_SNAP_CFRA
Definition: nla_intern.h:70
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1902
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4470
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4416
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
Definition: rna_define.c:2870
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3819
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const EnumPropertyItem rna_enum_fmodifier_type_items[]
Definition: rna_fcurve.c:45
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:40
#define min(a, b)
Definition: sort.c:51
NlaStrip * actstrip
float vec[3][3]
char name[66]
Definition: DNA_ID.h:283
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
ListBase actions
Definition: BKE_main.h:169
float actstart
struct NlaStrip * next
ListBase strips
float actend
float repeat
struct NlaStrip * prev
ListBase strips
struct NlaTrack * next
char name[64]
struct NlaTrack * prev
void * data
short flag
struct RenderData r
bool(* has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
Definition: ED_anim_api.h:562
eAnimChannel_Role channel_role
Definition: ED_anim_api.h:541
ListBase * markers
Definition: ED_anim_api.h:105
struct ARegion * region
Definition: ED_anim_api.h:89
struct Scene * scene
Definition: ED_anim_api.h:97
struct bDopeSheet * ads
Definition: ED_anim_api.h:92
short datatype
Definition: ED_anim_api.h:75
void * data
Definition: ED_anim_api.h:73
struct ReportList * reports
Definition: ED_anim_api.h:108
struct Main * bmain
Definition: ED_anim_api.h:95
struct SpaceLink * sl
Definition: ED_anim_api.h:87
struct bAnimListElem * next
Definition: ED_anim_api.h:135
struct AnimData * adt
Definition: ED_anim_api.h:170
struct bAnimListElem * prev
Definition: ED_anim_api.h:135
struct ID * id
Definition: ED_anim_api.h:168
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
float max
const EnumPropertyItem rna_enum_transform_mode_types[]
uint len
void WM_main_add_notifier(unsigned int type, void *reference)
int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_operator_smooth_viewtx_get(const wmOperator *op)
Definition: wm_operators.c:944
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))