Blender  V3.3
nla_edit.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation, Joshua Leung. All rights reserved. */
3 
8 #include <math.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include "DNA_anim_types.h"
13 #include "DNA_object_types.h"
14 #include "DNA_scene_types.h"
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include "BLI_blenlib.h"
19 #include "BLI_math.h"
20 #include "BLI_utildefines.h"
21 
22 #include "BLT_translation.h"
23 
24 #include "BKE_action.h"
25 #include "BKE_context.h"
26 #include "BKE_fcurve.h"
27 #include "BKE_lib_id.h"
28 #include "BKE_main.h"
29 #include "BKE_nla.h"
30 #include "BKE_report.h"
31 #include "BKE_screen.h"
32 
33 #include "ED_anim_api.h"
34 #include "ED_keyframes_edit.h"
35 #include "ED_markers.h"
36 #include "ED_screen.h"
37 #include "ED_transform.h"
38 
39 #include "RNA_access.h"
40 #include "RNA_define.h"
41 #include "RNA_enum_types.h"
42 #include "RNA_prototypes.h"
43 
44 #include "WM_api.h"
45 #include "WM_types.h"
46 
47 #include "DEG_depsgraph_build.h"
48 
49 #include "UI_interface.h"
50 #include "UI_view2d.h"
51 
52 #include "nla_intern.h" /* own include */
53 #include "nla_private.h" /* FIXME: maybe this shouldn't be included? */
54 
55 /* -------------------------------------------------------------------- */
60 {
61  ListBase anim_data = {NULL, NULL};
62  bAnimListElem *ale;
65 
66  /* get blocks to work on */
67  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
68 
69  for (ale = anim_data.first; ale; ale = ale->next) {
70  /* performing auto-blending, extend-mode validation, etc. */
72 
73  ale->update |= ANIM_UPDATE_DEPS;
74  }
75 
76  /* free temp memory */
77  ANIM_animdata_update(ac, &anim_data);
78  ANIM_animdata_freelist(&anim_data);
79 }
80 
83 /* 'Special' Editing */
84 
85 /* 'Tweak mode' allows the action referenced by the active NLA-strip to be edited
86  * as if it were the normal Active-Action of its AnimData block.
87  */
88 
89 /* -------------------------------------------------------------------- */
94 {
95  bAnimContext ac;
96 
97  ListBase anim_data = {NULL, NULL};
98  bAnimListElem *ale;
99  int filter;
100 
101  const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
102  const bool use_upper_stack_evaluation = RNA_boolean_get(op->ptr, "use_upper_stack_evaluation");
103  bool ok = false;
104 
105  /* get editor data */
106  if (ANIM_animdata_get_context(C, &ac) == 0) {
107  return OPERATOR_CANCELLED;
108  }
109 
110  /* get a list of the AnimData blocks being shown in the NLA */
112  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
113 
114  /* if no blocks, popup error? */
115  if (BLI_listbase_is_empty(&anim_data)) {
116  BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for");
117  return OPERATOR_CANCELLED;
118  }
119 
120  /* for each AnimData block with NLA-data, try setting it in tweak-mode */
121  for (ale = anim_data.first; ale; ale = ale->next) {
122  AnimData *adt = ale->data;
123 
124  if (use_upper_stack_evaluation) {
126  }
127  else {
129  }
130 
131  /* Try entering tweak-mode if valid. */
132  ok |= BKE_nla_tweakmode_enter(adt);
133 
134  /* mark the active track as being "solo"? */
135  if (do_solo && adt->actstrip) {
137 
138  if (nlt && !(nlt->flag & NLATRACK_SOLO)) {
139  BKE_nlatrack_solo_toggle(adt, nlt);
140  }
141  }
142 
143  ale->update |= ANIM_UPDATE_DEPS;
144  }
145 
146  /* free temp data */
147  ANIM_animdata_update(&ac, &anim_data);
148  ANIM_animdata_freelist(&anim_data);
149 
150  /* If we managed to enter tweak-mode on at least one AnimData block,
151  * set the flag for this in the active scene and send notifiers. */
152  if (ac.scene && ok) {
153  /* set editing flag */
154  ac.scene->flag |= SCE_NLA_EDIT_ON;
155 
156  /* set notifier that things have changed */
158  }
159  else {
160  BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on");
161  return OPERATOR_CANCELLED;
162  }
163 
164  /* done */
165  return OPERATOR_FINISHED;
166 }
167 
169 {
170  PropertyRNA *prop;
171 
172  /* identifiers */
173  ot->name = "Enter Tweak Mode";
174  ot->idname = "NLA_OT_tweakmode_enter";
175  ot->description =
176  "Enter tweaking mode for the action referenced by the active strip to edit its keyframes";
177 
178  /* api callbacks */
181 
182  /* flags */
184 
185  /* properties */
186  prop = RNA_def_boolean(ot->srna,
187  "isolate_action",
188  0,
189  "Isolate Action",
190  "Enable 'solo' on the NLA Track containing the active strip, "
191  "to edit it without seeing the effects of the NLA stack");
193 
194  prop = RNA_def_boolean(ot->srna,
195  "use_upper_stack_evaluation",
196  false,
197  "Evaluate Upper Stack",
198  "In tweak mode, display the effects of the tracks above the tweak strip");
200 }
201 
204 /* -------------------------------------------------------------------- */
209 {
210  ListBase anim_data = {NULL, NULL};
211  bAnimListElem *ale;
212  int filter;
213 
214  /* get a list of the AnimData blocks being shown in the NLA */
216  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
217 
218  /* if no blocks, popup error? */
219  if (BLI_listbase_is_empty(&anim_data)) {
220  BKE_report(ac->reports, RPT_ERROR, "No AnimData blocks in tweak mode to exit from");
221  return false;
222  }
223 
224  /* For each AnimData block with NLA-data, try exiting tweak-mode. */
225  for (ale = anim_data.first; ale; ale = ale->next) {
226  AnimData *adt = ale->data;
227 
228  /* clear solo flags */
229  if ((do_solo) & (adt->flag & ADT_NLA_SOLO_TRACK) && (adt->flag & ADT_NLA_EDIT_ON)) {
231  }
232 
233  /* To be sure that we're doing everything right, just exit tweak-mode. */
235 
236  ale->update |= ANIM_UPDATE_DEPS;
237  }
238 
239  /* free temp data */
240  ANIM_animdata_update(ac, &anim_data);
241  ANIM_animdata_freelist(&anim_data);
242 
243  /* Clear the tweak-mode flag in the active scene and send notifiers. */
244  if (ac->scene) {
245  /* clear editing flag */
246  ac->scene->flag &= ~SCE_NLA_EDIT_ON;
247 
248  /* set notifier that things have changed */
250  }
251 
252  /* done */
253  return true;
254 }
255 
256 /* Exit tweak-mode operator callback. */
258 {
259  bAnimContext ac;
260 
261  const bool do_solo = RNA_boolean_get(op->ptr, "isolate_action");
262  bool ok = false;
263 
264  /* get editor data */
265  if (ANIM_animdata_get_context(C, &ac) == 0) {
266  return OPERATOR_CANCELLED;
267  }
268 
269  /* perform operation */
270  ok = nlaedit_disable_tweakmode(&ac, do_solo);
271 
272  /* success? */
273  if (ok) {
274  return OPERATOR_FINISHED;
275  }
276  return OPERATOR_CANCELLED;
277 }
278 
280 {
281  PropertyRNA *prop;
282 
283  /* identifiers */
284  ot->name = "Exit Tweak Mode";
285  ot->idname = "NLA_OT_tweakmode_exit";
286  ot->description = "Exit tweaking mode for the action referenced by the active strip";
287 
288  /* api callbacks */
291 
292  /* flags */
294 
295  /* properties */
296  prop = RNA_def_boolean(ot->srna,
297  "isolate_action",
298  0,
299  "Isolate Action",
300  "Disable 'solo' on any of the NLA Tracks after exiting tweak mode "
301  "to get things back to normal");
303 }
304 
307 /* NLA Strips Range Stuff */
308 
309 /* -------------------------------------------------------------------- */
313 /* Get the min/max strip extents */
314 static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const bool only_sel)
315 {
316  ListBase anim_data = {NULL, NULL};
317  bAnimListElem *ale;
318  int filter;
319  bool found_bounds = false;
320 
321  /* get data to filter */
324  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
325 
326  /* set large values to try to override */
327  *min = 999999999.0f;
328  *max = -999999999.0f;
329 
330  /* check if any channels to set range with */
331  if (anim_data.first) {
332  /* go through channels, finding max extents */
333  for (ale = anim_data.first; ale; ale = ale->next) {
334  NlaTrack *nlt = (NlaTrack *)ale->data;
335  NlaStrip *strip;
336 
337  for (strip = nlt->strips.first; strip; strip = strip->next) {
338  /* only consider selected strips? */
339  if ((only_sel == false) || (strip->flag & NLASTRIP_FLAG_SELECT)) {
340  /* extend range if appropriate */
341  *min = min_ff(*min, strip->start);
342  *max = max_ff(*max, strip->end);
343 
344  found_bounds = true;
345  }
346  }
347  }
348 
349  /* free memory */
350  ANIM_animdata_freelist(&anim_data);
351  }
352 
353  /* set default range if nothing happened */
354  if (found_bounds == false) {
355  if (ac->scene) {
356  *min = (float)ac->scene->r.sfra;
357  *max = (float)ac->scene->r.efra;
358  }
359  else {
360  *min = -5;
361  *max = 100;
362  }
363  }
364 }
365 
368 /* -------------------------------------------------------------------- */
373 {
374  bAnimContext ac;
375  Scene *scene;
376  float min, max;
377 
378  /* get editor data */
379  if (ANIM_animdata_get_context(C, &ac) == 0) {
380  return OPERATOR_CANCELLED;
381  }
382 
383  if (ac.scene == NULL) {
384  return OPERATOR_CANCELLED;
385  }
386 
387  scene = ac.scene;
388 
389  /* set the range directly */
390  get_nlastrip_extents(&ac, &min, &max, true);
394 
395  /* set notifier that things have changed */
396  /* XXX err... there's nothing for frame ranges yet, but this should do fine too */
398 
399  return OPERATOR_FINISHED;
400 }
401 
403 {
404  /* identifiers */
405  ot->name = "Set Preview Range to Selected";
406  ot->idname = "NLA_OT_previewrange_set";
407  ot->description = "Set Preview Range based on extends of selected strips";
408 
409  /* api callbacks */
412 
413  /* flags */
415 }
416 
419 /* -------------------------------------------------------------------- */
430 static bool nla_channels_get_selected_extents(bAnimContext *ac, float *r_min, float *r_max)
431 {
432  ListBase anim_data = {NULL, NULL};
433  bAnimListElem *ale;
434  int filter;
435 
436  SpaceNla *snla = (SpaceNla *)ac->sl;
437  /* NOTE: not bool, since we want prioritize individual channels over expanders. */
438  short found = 0;
439 
440  /* get all items - we need to do it this way */
443  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
444 
445  /* loop through all channels, finding the first one that's selected */
446  float ymax = NLACHANNEL_FIRST_TOP(ac);
447 
448  for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
450 
451  /* must be selected... */
452  if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
454  /* update best estimate */
455  *r_min = ymax - NLACHANNEL_HEIGHT(snla);
456  *r_max = ymax;
457 
458  /* is this high enough priority yet? */
459  found = acf->channel_role;
460 
461  /* only stop our search when we've found an actual channel
462  * - data-block expanders get less priority so that we don't abort prematurely
463  */
464  if (found == ACHANNEL_ROLE_CHANNEL) {
465  break;
466  }
467  }
468  }
469 
470  /* free all temp data */
471  ANIM_animdata_freelist(&anim_data);
472 
473  return (found != 0);
474 }
475 
476 static int nlaedit_viewall(bContext *C, const bool only_sel)
477 {
478  bAnimContext ac;
479  View2D *v2d;
480  float extra;
481 
482  /* get editor data */
483  if (ANIM_animdata_get_context(C, &ac) == 0) {
484  return OPERATOR_CANCELLED;
485  }
486  v2d = &ac.region->v2d;
487 
488  /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
489  get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel);
490 
491  extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
492  v2d->cur.xmin -= extra;
493  v2d->cur.xmax += extra;
494 
495  /* set vertical range */
496  if (only_sel == false) {
497  /* view all -> the summary channel is usually the shows everything,
498  * and resides right at the top... */
499  v2d->cur.ymax = 0.0f;
500  v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
501  }
502  else {
503  /* locate first selected channel (or the active one), and frame those */
504  float ymin = v2d->cur.ymin;
505  float ymax = v2d->cur.ymax;
506 
507  if (nla_channels_get_selected_extents(&ac, &ymin, &ymax)) {
508  /* recenter the view so that this range is in the middle */
509  float ymid = (ymax - ymin) / 2.0f + ymin;
510  float x_center;
511 
512  UI_view2d_center_get(v2d, &x_center, NULL);
513  UI_view2d_center_set(v2d, x_center, ymid);
514  }
515  }
516 
517  /* do View2D syncing */
519 
520  /* just redraw this view */
522 
523  return OPERATOR_FINISHED;
524 }
525 
526 /* ......... */
527 
529 {
530  /* whole range */
531  return nlaedit_viewall(C, false);
532 }
533 
535 {
536  /* only selected */
537  return nlaedit_viewall(C, true);
538 }
539 
541 {
542  /* identifiers */
543  ot->name = "Frame All";
544  ot->idname = "NLA_OT_view_all";
545  ot->description = "Reset viewable area to show full strips range";
546 
547  /* api callbacks */
550 
551  /* flags */
552  ot->flag = 0;
553 }
554 
556 {
557  /* identifiers */
558  ot->name = "Frame Selected";
559  ot->idname = "NLA_OT_view_selected";
560  ot->description = "Reset viewable area to show selected strips range";
561 
562  /* api callbacks */
565 
566  /* flags */
567  ot->flag = 0;
568 }
569 
572 /* -------------------------------------------------------------------- */
577 {
578  const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
579  ANIM_center_frame(C, smooth_viewtx);
580  return OPERATOR_FINISHED;
581 }
582 
584 {
585  /* identifiers */
586  ot->name = "Go to Current Frame";
587  ot->idname = "NLA_OT_view_frame";
588  ot->description = "Move the view to the current frame";
589 
590  /* api callbacks */
593 
594  /* flags */
595  ot->flag = 0;
596 }
597 
600 /* NLA Editing Operations (Constructive/Destructive) */
601 
602 /* -------------------------------------------------------------------- */
609 /* add the specified action as new strip */
611 {
612  Main *bmain = CTX_data_main(C);
613  bAnimContext ac;
614  Scene *scene;
615 
616  ListBase anim_data = {NULL, NULL};
617  bAnimListElem *ale;
618  size_t items;
619  int filter;
620 
621  bAction *act;
622 
623  float cfra;
624 
625  /* get editor data */
626  if (ANIM_animdata_get_context(C, &ac) == 0) {
627  return OPERATOR_CANCELLED;
628  }
629 
630  scene = ac.scene;
631  cfra = (float)scene->r.cfra;
632 
633  /* get action to use */
634  act = BLI_findlink(&bmain->actions, RNA_enum_get(op->ptr, "action"));
635 
636  if (act == NULL) {
637  BKE_report(op->reports, RPT_ERROR, "No valid action to add");
638  // printf("Add strip - actname = '%s'\n", actname);
639  return OPERATOR_CANCELLED;
640  }
641  if (act->idroot == 0) {
642  /* hopefully in this case (i.e. library of userless actions),
643  * the user knows what they're doing... */
644  BKE_reportf(op->reports,
645  RPT_WARNING,
646  "Action '%s' does not specify what data-blocks it can be used on "
647  "(try setting the 'ID Root Type' setting from the data-blocks editor "
648  "for this action to avoid future problems)",
649  act->id.name + 2);
650  }
651 
652  /* add tracks to empty but selected animdata blocks so that strips can be added to those directly
653  * without having to manually add tracks first
654  */
656 
657  /* get a list of the editable tracks being shown in the NLA
658  * - this is limited to active ones for now, but could be expanded to
659  */
662  items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
663 
664  if (items == 0) {
665  BKE_report(op->reports,
666  RPT_ERROR,
667  "No active track(s) to add strip to, select an existing track or add one before "
668  "trying again");
669  return OPERATOR_CANCELLED;
670  }
671 
672  /* for every active track,
673  * try to add strip to free space in track or to the top of the stack if no space */
674  for (ale = anim_data.first; ale; ale = ale->next) {
675  NlaTrack *nlt = (NlaTrack *)ale->data;
676  AnimData *adt = ale->adt;
677  NlaStrip *strip = NULL;
678  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
679 
680  /* Sanity check: only apply actions of the right type for this ID.
681  * NOTE: in the case that this hasn't been set,
682  * we've already warned the user about this already
683  */
684  if ((act->idroot) && (act->idroot != GS(ale->id->name))) {
685  BKE_reportf(
686  op->reports,
687  RPT_ERROR,
688  "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'",
689  act->id.name + 2,
690  ale->id->name);
691  continue;
692  }
693 
694  /* create a new strip, and offset it to start on the current frame */
695  strip = BKE_nlastrip_new(act);
696 
697  strip->end += (cfra - strip->start);
698  strip->start = cfra;
699 
700  /* firstly try adding strip to our current track, but if that fails, add to a new track */
701  if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
702  /* trying to add to the current failed (no space),
703  * so add a new track to the stack, and add to that...
704  */
705  nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
706  BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
707  }
708 
709  /* auto-name it */
710  BKE_nlastrip_validate_name(adt, strip);
711  }
712 
713  /* free temp data */
714  ANIM_animdata_freelist(&anim_data);
715 
716  /* refresh auto strip properties */
718 
720 
721  /* set notifier that things have changed */
723 
724  /* done */
725  return OPERATOR_FINISHED;
726 }
727 
729 {
730  PropertyRNA *prop;
731 
732  /* identifiers */
733  ot->name = "Add Action Strip";
734  ot->idname = "NLA_OT_actionclip_add";
735  ot->description =
736  "Add an Action-Clip strip (i.e. an NLA Strip referencing an Action) to the active track";
737 
738  /* api callbacks */
742 
743  /* flags */
745 
746  /* props */
747  /* TODO: this would be nicer as an ID-pointer. */
748  prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
751  ot->prop = prop;
752 }
753 
756 /* -------------------------------------------------------------------- */
763 {
764  bAnimContext ac;
765 
766  ListBase anim_data = {NULL, NULL};
767  bAnimListElem *ale;
768  int filter;
769 
770  bool done = false;
771 
772  /* get editor data */
773  if (ANIM_animdata_get_context(C, &ac) == 0) {
774  return OPERATOR_CANCELLED;
775  }
776 
777  /* 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 = scene->r.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 */
1004  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1005 
1006  /* for each track, find pairs of strips to add transitions to */
1007  for (ale = anim_data.first; ale; ale = ale->next) {
1008  NlaTrack *nlt = (NlaTrack *)ale->data;
1009  AnimData *adt = ale->adt;
1010  NlaStrip *strip;
1011 
1013  /* No making meta-strips in non-local tracks of override data. */
1014  continue;
1015  }
1016 
1017  /* create meta-strips from the continuous chains of selected strips */
1018  BKE_nlastrips_make_metas(&nlt->strips, 0);
1019 
1020  /* name the metas */
1021  for (strip = nlt->strips.first; strip; strip = strip->next) {
1022  /* auto-name this strip if selected (that means it is a meta) */
1023  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1024  BKE_nlastrip_validate_name(adt, strip);
1025  }
1026  }
1027 
1028  ale->update |= ANIM_UPDATE_DEPS;
1029  }
1030 
1031  /* free temp data */
1032  ANIM_animdata_update(&ac, &anim_data);
1033  ANIM_animdata_freelist(&anim_data);
1034 
1035  /* set notifier that things have changed */
1037 
1038  /* done */
1039  return OPERATOR_FINISHED;
1040 }
1041 
1043 {
1044  /* identifiers */
1045  ot->name = "Add Meta-Strips";
1046  ot->idname = "NLA_OT_meta_add";
1047  ot->description = "Add new meta-strips incorporating the selected strips";
1048 
1049  /* api callbacks */
1052 
1053  /* flags */
1055 }
1056 
1059 /* -------------------------------------------------------------------- */
1066 {
1067  bAnimContext ac;
1068 
1069  ListBase anim_data = {NULL, NULL};
1070  bAnimListElem *ale;
1071  int filter;
1072 
1073  /* get editor data */
1074  if (ANIM_animdata_get_context(C, &ac) == 0) {
1075  return OPERATOR_CANCELLED;
1076  }
1077 
1078  /* get a list of the editable tracks being shown in the NLA */
1081  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1082 
1083  /* for each track, find pairs of strips to add transitions to */
1084  for (ale = anim_data.first; ale; ale = ale->next) {
1085  NlaTrack *nlt = (NlaTrack *)ale->data;
1086 
1088  /* No removing meta-strips from non-local tracks of override data. */
1089  continue;
1090  }
1091 
1092  /* clear all selected meta-strips, regardless of whether they are temporary or not */
1093  BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
1094 
1095  ale->update |= ANIM_UPDATE_DEPS;
1096  }
1097 
1098  /* free temp data */
1099  ANIM_animdata_update(&ac, &anim_data);
1100  ANIM_animdata_freelist(&anim_data);
1101 
1102  /* set notifier that things have changed */
1104 
1105  /* done */
1106  return OPERATOR_FINISHED;
1107 }
1108 
1110 {
1111  /* identifiers */
1112  ot->name = "Remove Meta-Strips";
1113  ot->idname = "NLA_OT_meta_remove";
1114  ot->description = "Separate out the strips held by the selected meta-strips";
1115 
1116  /* api callbacks */
1119 
1120  /* flags */
1122 }
1123 
1126 /* -------------------------------------------------------------------- */
1134 {
1135  bAnimContext ac;
1136 
1137  ListBase anim_data = {NULL, NULL};
1138  bAnimListElem *ale;
1139  int filter;
1140 
1141  bool linked = RNA_boolean_get(op->ptr, "linked");
1142  bool done = false;
1143 
1144  /* get editor data */
1145  if (ANIM_animdata_get_context(C, &ac) == 0) {
1146  return OPERATOR_CANCELLED;
1147  }
1148 
1149  /* get a list of editable tracks being shown in the NLA */
1152  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1153 
1154  /* duplicate strips in tracks starting from the last one so that we're
1155  * less likely to duplicate strips we just duplicated...
1156  */
1157  for (ale = anim_data.last; ale; ale = ale->prev) {
1158  NlaTrack *nlt = (NlaTrack *)ale->data;
1159  AnimData *adt = ale->adt;
1160  NlaStrip *strip, *nstrip, *next;
1161  NlaTrack *track;
1162 
1163  /* NOTE: We allow this operator in override context because it is almost always (from possible
1164  * default user interactions) paired with the transform one, which will ensure that the new
1165  * strip ends up in a valid (local) track. */
1166 
1167  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1168  for (strip = nlt->strips.first; strip; strip = next) {
1169  next = strip->next;
1170 
1171  /* if selected, split the strip at its midpoint */
1172  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1173  /* make a copy (assume that this is possible) */
1174  nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0);
1175 
1176  /* in case there's no space in the track above,
1177  * or we haven't got a reference to it yet, try adding */
1178  if (BKE_nlatrack_add_strip(nlt->next, nstrip, is_liboverride) == 0) {
1179  /* need to add a new track above the one above the current one
1180  * - if the current one is the last one, nlt->next will be NULL, which defaults to adding
1181  * at the top of the stack anyway...
1182  */
1183  track = BKE_nlatrack_add(adt, nlt->next, is_liboverride);
1184  BKE_nlatrack_add_strip(track, nstrip, is_liboverride);
1185  }
1186 
1187  /* deselect the original and the active flag */
1189 
1190  /* auto-name newly created strip */
1191  BKE_nlastrip_validate_name(adt, nstrip);
1192 
1193  done = true;
1194  }
1195  }
1196  }
1197 
1198  /* free temp data */
1199  ANIM_animdata_freelist(&anim_data);
1200 
1201  if (done) {
1202  /* refresh auto strip properties */
1203  ED_nla_postop_refresh(&ac);
1204 
1205  if (!linked) {
1207  }
1208 
1209  /* set notifier that things have changed */
1211 
1212  /* done */
1213  return OPERATOR_FINISHED;
1214  }
1215 
1216  return OPERATOR_CANCELLED;
1217 }
1218 
1220 {
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 
1252 /* -------------------------------------------------------------------- */
1259 {
1260  bAnimContext ac;
1261 
1262  ListBase anim_data = {NULL, NULL};
1263  bAnimListElem *ale;
1264  int filter;
1265 
1266  /* get editor data */
1267  if (ANIM_animdata_get_context(C, &ac) == 0) {
1268  return OPERATOR_CANCELLED;
1269  }
1270 
1271  /* get a list of the editable tracks being shown in the NLA */
1274  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1275 
1276  /* for each NLA-Track, delete all selected strips */
1277  for (ale = anim_data.first; ale; ale = ale->next) {
1278  NlaTrack *nlt = (NlaTrack *)ale->data;
1279  NlaStrip *strip, *nstrip;
1280 
1282  /* No deletion of strips in non-local tracks of override data. */
1283  continue;
1284  }
1285 
1286  for (strip = nlt->strips.first; strip; strip = nstrip) {
1287  nstrip = strip->next;
1288 
1289  /* if selected, delete */
1290  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1291  /* Fix for #109430. Defensively exit tweak mode before deleting
1292  * the active strip. */
1293  if (ale->adt && ale->adt->actstrip == strip) {
1295  }
1296 
1297  /* if a strip either side of this was a transition, delete those too */
1298  if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
1299  BKE_nlastrip_free(&nlt->strips, strip->prev, true);
1300  }
1301  if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
1302  nstrip = nstrip->next;
1303  BKE_nlastrip_free(&nlt->strips, strip->next, true);
1304  }
1305 
1306  /* finally, delete this strip */
1307  BKE_nlastrip_free(&nlt->strips, strip, true);
1308  }
1309  }
1310  }
1311 
1312  /* free temp data */
1313  ANIM_animdata_freelist(&anim_data);
1314 
1315  /* refresh auto strip properties */
1316  ED_nla_postop_refresh(&ac);
1317 
1319 
1320  /* set notifier that things have changed */
1322 
1323  /* done */
1324  return OPERATOR_FINISHED;
1325 }
1326 
1328 {
1329  /* identifiers */
1330  ot->name = "Delete Strips";
1331  ot->idname = "NLA_OT_delete";
1332  ot->description = "Delete selected strips";
1333 
1334  /* api callbacks */
1337 
1338  /* flags */
1340 }
1341 
1344 /* -------------------------------------------------------------------- */
1354 /* split a given Action-Clip strip */
1356  Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
1357 {
1358  NlaStrip *nstrip;
1359  float splitframe, splitaframe;
1360 
1361  /* calculate the frames to do the splitting at
1362  * - use current frame if within extents of strip
1363  */
1364  if ((cfra > strip->start) && (cfra < strip->end)) {
1365  /* use the current frame */
1366  splitframe = cfra;
1367  splitaframe = nlastrip_get_frame(strip, cfra, NLATIME_CONVERT_UNMAP);
1368  }
1369  else {
1370  /* split in the middle */
1371  float len;
1372 
1373  /* strip extents */
1374  len = strip->end - strip->start;
1375  if (IS_EQF(len, 0.0f)) {
1376  return;
1377  }
1378 
1379  splitframe = strip->start + (len / 2.0f);
1380 
1381  /* action range */
1382  len = strip->actend - strip->actstart;
1383  if (IS_EQF(len, 0.0f)) {
1384  splitaframe = strip->actend;
1385  }
1386  else {
1387  splitaframe = strip->actstart + (len / 2.0f);
1388  }
1389  }
1390 
1391  /* make a copy (assume that this is possible) and append
1392  * it immediately after the current strip
1393  */
1394  nstrip = BKE_nlastrip_copy(bmain, strip, true, 0);
1395  BLI_insertlinkafter(&nlt->strips, strip, nstrip);
1396 
1397  /* Set the endpoint of the first strip and the start of the new strip
1398  * to the split-frame values calculated above.
1399  */
1400  strip->end = splitframe;
1401  nstrip->start = splitframe;
1402 
1403  if ((splitaframe > strip->actstart) && (splitaframe < strip->actend)) {
1404  /* only do this if we're splitting down the middle... */
1405  strip->actend = splitaframe;
1406  nstrip->actstart = splitaframe;
1407  }
1408 
1409  /* Make sure Sync Length is off. With that setting on, entering and exiting tweak mode would
1410  * effectively undo the split, because both the old and the new strip will be at the length of
1411  * the Action again. */
1412  strip->flag &= ~NLASTRIP_FLAG_SYNC_LENGTH;
1414 
1415  /* auto-name the new strip */
1416  BKE_nlastrip_validate_name(adt, nstrip);
1417 }
1418 
1419 /* split a given Meta strip */
1420 static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip)
1421 {
1422  /* simply ungroup it for now... */
1423  BKE_nlastrips_clear_metastrip(&nlt->strips, strip);
1424 }
1425 
1426 /* ----- */
1427 
1429 {
1430  bAnimContext ac;
1431 
1432  ListBase anim_data = {NULL, NULL};
1433  bAnimListElem *ale;
1434  int filter;
1435 
1436  /* get editor data */
1437  if (ANIM_animdata_get_context(C, &ac) == 0) {
1438  return OPERATOR_CANCELLED;
1439  }
1440 
1441  /* get a list of editable tracks being shown in the NLA */
1444  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1445 
1446  /* for each NLA-Track, split all selected strips into two strips */
1447  for (ale = anim_data.first; ale; ale = ale->next) {
1448  NlaTrack *nlt = (NlaTrack *)ale->data;
1449  AnimData *adt = ale->adt;
1450  NlaStrip *strip, *next;
1451 
1453  /* No splitting of strips in non-local tracks of override data. */
1454  continue;
1455  }
1456 
1457  for (strip = nlt->strips.first; strip; strip = next) {
1458  next = strip->next;
1459 
1460  /* if selected, split the strip at its midpoint */
1461  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1462  /* splitting method depends on the type of strip */
1463  switch (strip->type) {
1464  case NLASTRIP_TYPE_CLIP: /* action-clip */
1465  nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra);
1466  break;
1467 
1468  case NLASTRIP_TYPE_META: /* meta-strips need special handling */
1469  nlaedit_split_strip_meta(nlt, strip);
1470  break;
1471 
1472  default: /* for things like Transitions, do not split! */
1473  break;
1474  }
1475  }
1476  }
1477  }
1478 
1479  /* free temp data */
1480  ANIM_animdata_freelist(&anim_data);
1481 
1482  /* refresh auto strip properties */
1483  ED_nla_postop_refresh(&ac);
1484 
1485  /* set notifier that things have changed */
1487 
1488  /* done */
1489  return OPERATOR_FINISHED;
1490 }
1491 
1493 {
1494  /* identifiers */
1495  ot->name = "Split Strips";
1496  ot->idname = "NLA_OT_split";
1497  ot->description = "Split selected strips at their midpoints";
1498 
1499  /* api callbacks */
1502 
1503  /* flags */
1505 }
1506 
1509 /* NLA Editing Operations (Modifying) */
1510 
1511 /* -------------------------------------------------------------------- */
1518 {
1519  bAnimContext ac;
1520 
1521  ListBase anim_data = {NULL, NULL};
1522  bAnimListElem *ale;
1523  int filter;
1524 
1525  /* get editor data */
1526  if (ANIM_animdata_get_context(C, &ac) == 0) {
1527  return OPERATOR_CANCELLED;
1528  }
1529 
1530  /* get a list of the editable tracks being shown in the NLA */
1533  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1534 
1535  /* go over all selected strips */
1536  for (ale = anim_data.first; ale; ale = ale->next) {
1537  NlaTrack *nlt = (NlaTrack *)ale->data;
1538  NlaStrip *strip;
1539 
1540  /* For every selected strip, toggle muting. */
1541  for (strip = nlt->strips.first; strip; strip = strip->next) {
1542  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1543  /* just flip the mute flag for now */
1544  /* TODO: have a pre-pass to check if mute all or unmute all? */
1545  strip->flag ^= NLASTRIP_FLAG_MUTED;
1546 
1547  /* tag AnimData to get recalculated */
1548  ale->update |= ANIM_UPDATE_DEPS;
1549  }
1550  }
1551  }
1552 
1553  /* cleanup */
1554  ANIM_animdata_update(&ac, &anim_data);
1555  ANIM_animdata_freelist(&anim_data);
1556 
1557  /* set notifier that things have changed */
1559 
1560  /* done */
1561  return OPERATOR_FINISHED;
1562 }
1563 
1565 {
1566  /* identifiers */
1567  ot->name = "Toggle Muting";
1568  ot->idname = "NLA_OT_mute_toggle";
1569  ot->description = "Mute or un-mute selected strips";
1570 
1571  /* api callbacks */
1574 
1575  /* flags */
1577 }
1578 
1581 /* -------------------------------------------------------------------- */
1588 {
1589  bAnimContext ac;
1590 
1591  ListBase anim_data = {NULL, NULL};
1592  bAnimListElem *ale;
1593  int filter;
1594 
1595  /* get editor data */
1596  if (ANIM_animdata_get_context(C, &ac) == 0) {
1597  return OPERATOR_CANCELLED;
1598  }
1599 
1600  /* get a list of the editable tracks being shown in the NLA */
1603  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1604 
1605  /* consider each track in turn */
1606  for (ale = anim_data.first; ale; ale = ale->next) {
1607  NlaTrack *nlt = (NlaTrack *)ale->data;
1608 
1609  NlaStrip *strip, *stripN = NULL;
1610  NlaStrip *area = NULL, *sb = NULL;
1611  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1612 
1614  /* No re-ordering of strips within non-local tracks of override data. */
1615  continue;
1616  }
1617 
1618  /* Make temporary meta-strips so that entire islands of selections can be moved around. */
1619  BKE_nlastrips_make_metas(&nlt->strips, 1);
1620 
1621  /* special case: if there is only 1 island
1622  * (i.e. temp meta BUT NOT unselected/normal/normal-meta strips) left after this,
1623  * and this island has two strips inside it, then we should be able to just swap these still...
1624  */
1625  if (BLI_listbase_is_empty(&nlt->strips) == false) {
1626  NlaStrip *mstrip = (NlaStrip *)nlt->strips.first;
1627 
1628  if ((mstrip->flag & NLASTRIP_FLAG_TEMP_META) &&
1629  (BLI_listbase_count_at_most(&mstrip->strips, 3) == 2)) {
1630  /* remove this temp meta, so that we can see the strips inside */
1631  BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
1632  }
1633  }
1634 
1635  /* get two selected strips only (these will be metas due to prev step) to operate on
1636  * - only allow swapping 2, as with more the context becomes unclear
1637  */
1638  for (strip = nlt->strips.first; strip; strip = stripN) {
1639  stripN = strip->next;
1640 
1641  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1642  /* first or second strip? */
1643  if (area == NULL) {
1644  /* store as first */
1645  area = strip;
1646  }
1647  else if (sb == NULL) {
1648  /* store as second */
1649  sb = strip;
1650  }
1651  else {
1652  /* too many selected */
1653  break;
1654  }
1655  }
1656  }
1657 
1658  if (strip) {
1659  /* too many selected warning */
1660  BKE_reportf(
1661  op->reports,
1662  RPT_WARNING,
1663  "Too many clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
1664  nlt->name);
1665  }
1666  else if (area == NULL) {
1667  /* no warning as this is just a common case,
1668  * and it may get annoying when doing multiple tracks */
1669  }
1670  else if (sb == NULL) {
1671  /* too few selected warning */
1672  BKE_reportf(
1673  op->reports,
1674  RPT_WARNING,
1675  "Too few clusters of strips selected in NLA Track (%s): needs exactly 2 to be selected",
1676  nlt->name);
1677  }
1678  else {
1679  float nsa[2], nsb[2];
1680 
1681  /* remove these strips from the track,
1682  * so that we can test if they can fit in the proposed places */
1683  BLI_remlink(&nlt->strips, area);
1684  BLI_remlink(&nlt->strips, sb);
1685 
1686  /* calculate new extents for strips */
1687  /* a --> b */
1688  nsa[0] = sb->start;
1689  nsa[1] = sb->start + (area->end - area->start);
1690  /* b --> a */
1691  nsb[0] = area->start;
1692  nsb[1] = area->start + (sb->end - sb->start);
1693 
1694  /* check if the track has room for the strips to be swapped */
1695  if (BKE_nlastrips_has_space(&nlt->strips, nsa[0], nsa[1]) &&
1696  BKE_nlastrips_has_space(&nlt->strips, nsb[0], nsb[1])) {
1697  /* set new extents for strips then */
1698  area->start = nsa[0];
1699  area->end = nsa[1];
1701 
1702  sb->start = nsb[0];
1703  sb->end = nsb[1];
1705  }
1706  else {
1707  /* not enough room to swap, so show message */
1708  if ((area->flag & NLASTRIP_FLAG_TEMP_META) || (sb->flag & NLASTRIP_FLAG_TEMP_META)) {
1709  BKE_report(
1710  op->reports,
1711  RPT_WARNING,
1712  "Cannot swap selected strips as they will not be able to fit in their new places");
1713  }
1714  else {
1715  BKE_reportf(op->reports,
1716  RPT_WARNING,
1717  "Cannot swap '%s' and '%s' as one or both will not be able to fit in their "
1718  "new places",
1719  area->name,
1720  sb->name);
1721  }
1722  }
1723 
1724  /* add strips back to track now */
1725  BKE_nlatrack_add_strip(nlt, area, is_liboverride);
1726  BKE_nlatrack_add_strip(nlt, sb, is_liboverride);
1727  }
1728 
1729  /* Clear (temp) meta-strips. */
1730  BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
1731  }
1732 
1733  /* free temp data */
1734  ANIM_animdata_freelist(&anim_data);
1735 
1736  /* refresh auto strip properties */
1737  ED_nla_postop_refresh(&ac);
1738 
1739  /* set notifier that things have changed */
1742 
1743  /* done */
1744  return OPERATOR_FINISHED;
1745 }
1746 
1748 {
1749  /* identifiers */
1750  ot->name = "Swap Strips";
1751  ot->idname = "NLA_OT_swap";
1752  ot->description = "Swap order of selected strips within tracks";
1753 
1754  /* api callbacks */
1757 
1758  /* flags */
1760 }
1761 
1764 /* -------------------------------------------------------------------- */
1771 {
1772  bAnimContext ac;
1773 
1774  ListBase anim_data = {NULL, NULL};
1775  bAnimListElem *ale;
1776  int filter;
1777 
1778  /* get editor data */
1779  if (ANIM_animdata_get_context(C, &ac) == 0) {
1780  return OPERATOR_CANCELLED;
1781  }
1782 
1783  /* get a list of the editable tracks being shown in the NLA */
1786  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1787 
1788  /* since we're potentially moving strips from lower tracks to higher tracks, we should
1789  * loop over the tracks in reverse order to avoid moving earlier strips up multiple tracks
1790  */
1791  for (ale = anim_data.last; ale; ale = ale->prev) {
1792  NlaTrack *nlt = (NlaTrack *)ale->data;
1793  NlaTrack *nltn = nlt->next;
1794  NlaStrip *strip, *stripn;
1795 
1796  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1797 
1798  /* if this track has no tracks after it, skip for now... */
1799  if (nltn == NULL) {
1800  continue;
1801  }
1802 
1805  /* No moving of strips in non-local tracks of override data. */
1806  continue;
1807  }
1808 
1809  /* for every selected strip, try to move */
1810  for (strip = nlt->strips.first; strip; strip = stripn) {
1811  stripn = strip->next;
1812 
1813  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1814  /* check if the track above has room for this strip */
1815  if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
1816  /* remove from its current track, and add to the one above
1817  * (it 'should' work, so no need to worry) */
1818  BLI_remlink(&nlt->strips, strip);
1819  BKE_nlatrack_add_strip(nltn, strip, is_liboverride);
1820  }
1821  }
1822  }
1823  }
1824 
1825  /* free temp data */
1826  ANIM_animdata_freelist(&anim_data);
1827 
1828  /* refresh auto strip properties */
1829  ED_nla_postop_refresh(&ac);
1830 
1831  /* set notifier that things have changed */
1834 
1835  /* done */
1836  return OPERATOR_FINISHED;
1837 }
1838 
1840 {
1841  /* identifiers */
1842  ot->name = "Move Strips Up";
1843  ot->idname = "NLA_OT_move_up";
1844  ot->description = "Move selected strips up a track if there's room";
1845 
1846  /* api callbacks */
1849 
1850  /* flags */
1852 }
1853 
1856 /* -------------------------------------------------------------------- */
1863 {
1864  bAnimContext ac;
1865 
1866  ListBase anim_data = {NULL, NULL};
1867  bAnimListElem *ale;
1868  int filter;
1869 
1870  /* get editor data */
1871  if (ANIM_animdata_get_context(C, &ac) == 0) {
1872  return OPERATOR_CANCELLED;
1873  }
1874 
1875  /* get a list of the editable tracks being shown in the NLA */
1878  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1879 
1880  /* loop through the tracks in normal order, since we're pushing strips down,
1881  * strips won't get operated on twice
1882  */
1883  for (ale = anim_data.first; ale; ale = ale->next) {
1884  NlaTrack *nlt = (NlaTrack *)ale->data;
1885  NlaTrack *nltp = nlt->prev;
1886  NlaStrip *strip, *stripn;
1887 
1888  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
1889 
1890  /* if this track has no tracks before it, skip for now... */
1891  if (nltp == NULL) {
1892  continue;
1893  }
1894 
1897  /* No moving of strips in non-local tracks of override data. */
1898  continue;
1899  }
1900 
1901  /* for every selected strip, try to move */
1902  for (strip = nlt->strips.first; strip; strip = stripn) {
1903  stripn = strip->next;
1904 
1905  if (strip->flag & NLASTRIP_FLAG_SELECT) {
1906  /* check if the track below has room for this strip */
1907  if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
1908  /* remove from its current track, and add to the one above
1909  * (it 'should' work, so no need to worry) */
1910  BLI_remlink(&nlt->strips, strip);
1911  BKE_nlatrack_add_strip(nltp, strip, is_liboverride);
1912  }
1913  }
1914  }
1915  }
1916 
1917  /* free temp data */
1918  ANIM_animdata_freelist(&anim_data);
1919 
1920  /* refresh auto strip properties */
1921  ED_nla_postop_refresh(&ac);
1922 
1923  /* set notifier that things have changed */
1926 
1927  /* done */
1928  return OPERATOR_FINISHED;
1929 }
1930 
1932 {
1933  /* identifiers */
1934  ot->name = "Move Strips Down";
1935  ot->idname = "NLA_OT_move_down";
1936  ot->description = "Move selected strips down a track if there's room";
1937 
1938  /* api callbacks */
1941 
1942  /* flags */
1944 }
1945 
1948 /* -------------------------------------------------------------------- */
1955 {
1956  bAnimContext ac;
1957 
1958  ListBase anim_data = {NULL, NULL};
1959  bAnimListElem *ale;
1960  int filter;
1961  const bool active_only = RNA_boolean_get(op->ptr, "active");
1962 
1963  /* get editor data */
1964  if (ANIM_animdata_get_context(C, &ac) == 0) {
1965  return OPERATOR_CANCELLED;
1966  }
1967 
1968  /* get a list of the editable tracks being shown in the NLA */
1971  if (active_only) {
1973  }
1974  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1975 
1976  /* for each NLA-Track, apply scale of all selected strips */
1977  for (ale = anim_data.first; ale; ale = ale->next) {
1978  NlaTrack *nlt = (NlaTrack *)ale->data;
1979  NlaStrip *strip;
1980 
1981  for (strip = nlt->strips.first; strip; strip = strip->next) {
1982  /* strip selection/active status check */
1983  if (active_only) {
1984  if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
1985  continue;
1986  }
1987  }
1988  else {
1989  if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) {
1990  continue;
1991  }
1992  }
1993 
1994  /* must be action-clip only (transitions don't have scale) */
1995  if (strip->type == NLASTRIP_TYPE_CLIP) {
1996  if (strip->act == NULL) {
1997  continue;
1998  }
1999 
2001 
2002  ale->update |= ANIM_UPDATE_DEPS;
2003  }
2004  }
2005  }
2006 
2007  /* free temp data */
2008  ANIM_animdata_update(&ac, &anim_data);
2009  ANIM_animdata_freelist(&anim_data);
2010 
2011  /* set notifier that things have changed */
2013 
2014  /* done */
2015  return OPERATOR_FINISHED;
2016 }
2017 
2019 {
2020  /* identifiers */
2021  ot->name = "Sync Action Length";
2022  ot->idname = "NLA_OT_action_sync_length";
2023  ot->description =
2024  "Synchronize the length of the referenced Action with the length used in the strip";
2025 
2026  /* api callbacks */
2029 
2030  /* flags */
2032 
2033  /* properties */
2035  "active",
2036  1,
2037  "Active Strip Only",
2038  "Only sync the active length for the active strip");
2039 }
2040 
2043 /* -------------------------------------------------------------------- */
2050 {
2051  Main *bmain = CTX_data_main(C);
2052  bAnimContext ac;
2053 
2054  ListBase anim_data = {NULL, NULL};
2055  bAnimListElem *ale;
2056  int filter;
2057  bool copied = false;
2058 
2059  /* get editor data */
2060  if (ANIM_animdata_get_context(C, &ac) == 0) {
2061  return OPERATOR_CANCELLED;
2062  }
2063 
2064  /* get a list of the editable tracks being shown in the NLA */
2067  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2068 
2069  /* Ensure that each action used only has a single user
2070  * - This is done in reverse order so that the original strips are
2071  * likely to still get to keep their action
2072  */
2073  for (ale = anim_data.last; ale; ale = ale->prev) {
2074  NlaTrack *nlt = (NlaTrack *)ale->data;
2075  NlaStrip *strip;
2076 
2077  for (strip = nlt->strips.last; strip; strip = strip->prev) {
2078  /* must be action-clip only (as only these have actions) */
2079  if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
2080  if (strip->act == NULL) {
2081  continue;
2082  }
2083 
2084  /* multi-user? */
2085  if (ID_REAL_USERS(strip->act) > 1) {
2086  /* make a new copy of the action for us to use (it will have 1 user already) */
2087  bAction *new_action = (bAction *)BKE_id_copy(bmain, &strip->act->id);
2088 
2089  /* decrement user count of our existing action */
2090  id_us_min(&strip->act->id);
2091 
2092  /* switch to the new copy */
2093  strip->act = new_action;
2094 
2095  ale->update |= ANIM_UPDATE_DEPS;
2096  copied = true;
2097  }
2098  }
2099  }
2100  }
2101 
2102  /* free temp data */
2103  ANIM_animdata_update(&ac, &anim_data);
2104  ANIM_animdata_freelist(&anim_data);
2105 
2106  if (copied) {
2108  }
2109 
2110  /* set notifier that things have changed */
2112 
2113  /* done */
2114  return OPERATOR_FINISHED;
2115 }
2116 
2118 {
2119  /* identifiers */
2120  ot->name = "Make Single User";
2121  ot->idname = "NLA_OT_make_single_user";
2122  ot->description = "Ensure that each action is only used once in the set of strips selected";
2123 
2124  /* api callbacks */
2128 
2129  /* flags */
2131 }
2132 
2135 /* -------------------------------------------------------------------- */
2141 /* apply scaling to keyframe */
2143 {
2144  /* NLA-strip which has this scaling is stored in ked->data */
2145  NlaStrip *strip = (NlaStrip *)ked->data;
2146 
2147  /* adjust all the times */
2148  bezt->vec[0][0] = nlastrip_get_frame(strip, bezt->vec[0][0], NLATIME_CONVERT_MAP);
2149  bezt->vec[1][0] = nlastrip_get_frame(strip, bezt->vec[1][0], NLATIME_CONVERT_MAP);
2150  bezt->vec[2][0] = nlastrip_get_frame(strip, bezt->vec[2][0], NLATIME_CONVERT_MAP);
2151 
2152  /* nothing to return or else we exit */
2153  return 0;
2154 }
2155 
2157 {
2158  Main *bmain = CTX_data_main(C);
2159  bAnimContext ac;
2160 
2161  ListBase anim_data = {NULL, NULL};
2162  bAnimListElem *ale;
2163  int filter;
2164  bool copied = false;
2165 
2166  KeyframeEditData ked = {{NULL}};
2167 
2168  /* get editor data */
2169  if (ANIM_animdata_get_context(C, &ac) == 0) {
2170  return OPERATOR_CANCELLED;
2171  }
2172 
2173  /* get a list of the editable tracks being shown in the NLA */
2176  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2177 
2178  /* for each NLA-Track, apply scale of all selected strips */
2179  for (ale = anim_data.first; ale; ale = ale->next) {
2180  NlaTrack *nlt = (NlaTrack *)ale->data;
2181  NlaStrip *strip;
2182 
2183  for (strip = nlt->strips.first; strip; strip = strip->next) {
2184  /* strip must be selected, and must be action-clip only
2185  * (transitions don't have scale) */
2186  if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
2187  if (strip->act == NULL || ID_IS_OVERRIDE_LIBRARY(strip->act) || ID_IS_LINKED(strip->act)) {
2188  continue;
2189  }
2190  /* if the referenced action is used by other strips,
2191  * make this strip use its own copy */
2192  if (strip->act->id.us > 1) {
2193  /* make a copy of the Action to work on */
2194  bAction *act = (bAction *)BKE_id_copy(bmain, &strip->act->id);
2195 
2196  /* set this as the new referenced action,
2197  * decrementing the users of the old one */
2198  id_us_min(&strip->act->id);
2199  strip->act = act;
2200 
2201  copied = true;
2202  }
2203 
2204  /* setup iterator, and iterate over all the keyframes in the action,
2205  * applying this scaling */
2206  ked.data = strip;
2208  ac.ads,
2209  strip->act,
2210  ALE_ACT,
2211  NULL,
2214 
2215  /* clear scale of strip now that it has been applied,
2216  * and recalculate the extents of the action now that it has been scaled
2217  * but leave everything else alone
2218  */
2219  const float start = nlastrip_get_frame(strip, strip->actstart, NLATIME_CONVERT_MAP);
2220  const float end = nlastrip_get_frame(strip, strip->actend, NLATIME_CONVERT_MAP);
2221 
2222  if (strip->act->flag & ACT_FRAME_RANGE) {
2223  strip->act->frame_start = nlastrip_get_frame(
2224  strip, strip->act->frame_start, NLATIME_CONVERT_MAP);
2225  strip->act->frame_end = nlastrip_get_frame(
2226  strip, strip->act->frame_end, NLATIME_CONVERT_MAP);
2227  }
2228 
2229  strip->scale = 1.0f;
2230  strip->actstart = start;
2231  strip->actend = end;
2232 
2233  ale->update |= ANIM_UPDATE_DEPS;
2234  }
2235  }
2236  }
2237 
2238  /* free temp data */
2239  ANIM_animdata_update(&ac, &anim_data);
2240  ANIM_animdata_freelist(&anim_data);
2241 
2242  if (copied) {
2244  }
2245 
2246  /* set notifier that things have changed */
2248 
2249  /* done */
2250  return OPERATOR_FINISHED;
2251 }
2252 
2254 {
2255  /* identifiers */
2256  ot->name = "Apply Scale";
2257  ot->idname = "NLA_OT_apply_scale";
2258  ot->description = "Apply scaling of selected strips to their referenced Actions";
2259 
2260  /* api callbacks */
2263 
2264  /* flags */
2266 }
2267 
2270 /* -------------------------------------------------------------------- */
2277 {
2278  bAnimContext ac;
2279 
2280  ListBase anim_data = {NULL, NULL};
2281  bAnimListElem *ale;
2282  int filter;
2283 
2284  /* get editor data */
2285  if (ANIM_animdata_get_context(C, &ac) == 0) {
2286  return OPERATOR_CANCELLED;
2287  }
2288 
2289  /* get a list of the editable tracks being shown in the NLA */
2292  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2293 
2294  /* for each NLA-Track, reset scale of all selected strips */
2295  for (ale = anim_data.first; ale; ale = ale->next) {
2296  NlaTrack *nlt = (NlaTrack *)ale->data;
2297  NlaStrip *strip;
2298 
2299  for (strip = nlt->strips.first; strip; strip = strip->next) {
2300  /* strip must be selected, and must be action-clip only
2301  * (transitions don't have scale) */
2302  if ((strip->flag & NLASTRIP_FLAG_SELECT) && (strip->type == NLASTRIP_TYPE_CLIP)) {
2303  PointerRNA strip_ptr;
2304 
2305  RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
2306  RNA_float_set(&strip_ptr, "scale", 1.0f);
2307  }
2308  }
2309  }
2310 
2311  /* free temp data */
2312  ANIM_animdata_freelist(&anim_data);
2313 
2314  /* refresh auto strip properties */
2315  ED_nla_postop_refresh(&ac);
2316 
2317  /* set notifier that things have changed */
2319 
2320  /* done */
2321  return OPERATOR_FINISHED;
2322 }
2323 
2325 {
2326  /* identifiers */
2327  ot->name = "Clear Scale";
2328  ot->idname = "NLA_OT_clear_scale";
2329  ot->description = "Reset scaling of selected strips";
2330 
2331  /* api callbacks */
2334 
2335  /* flags */
2337 }
2338 
2341 /* -------------------------------------------------------------------- */
2347 /* defines for snap keyframes tool */
2349  {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Selection to Current Frame", ""},
2350  /* XXX as single entry? */
2351  {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Selection to Nearest Frame", ""},
2352  /* XXX as single entry? */
2353  {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Selection to Nearest Second", ""},
2354  {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Selection to Nearest Marker", ""},
2355  {0, NULL, 0, NULL, NULL},
2356 };
2357 
2359 {
2360  bAnimContext ac;
2361 
2362  ListBase anim_data = {NULL, NULL};
2363  bAnimListElem *ale;
2364  int filter;
2365 
2366  Scene *scene;
2367  int mode = RNA_enum_get(op->ptr, "type");
2368  float secf;
2369 
2370  /* get editor data */
2371  if (ANIM_animdata_get_context(C, &ac) == 0) {
2372  return OPERATOR_CANCELLED;
2373  }
2374 
2375  /* get a list of the editable tracks being shown in the NLA */
2378  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2379 
2380  /* get some necessary vars */
2381  scene = ac.scene;
2382  secf = (float)FPS;
2383 
2384  bool any_added = false;
2385 
2386  /* since we may add tracks, perform this in reverse order */
2387  for (ale = anim_data.last; ale; ale = ale->prev) {
2388  ListBase tmp_strips = {NULL, NULL};
2389  AnimData *adt = ale->adt;
2390  NlaTrack *nlt = (NlaTrack *)ale->data;
2391  NlaStrip *strip, *stripn;
2392  NlaTrack *track;
2393 
2394  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
2395 
2396  /* create meta-strips from the continuous chains of selected strips */
2397  BKE_nlastrips_make_metas(&nlt->strips, 1);
2398 
2399  /* apply the snapping to all the temp meta-strips, then put them in a separate list to be added
2400  * back to the original only if they still fit
2401  */
2402  for (strip = nlt->strips.first; strip; strip = stripn) {
2403  stripn = strip->next;
2404 
2405  if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
2406  float start, end;
2407 
2408  /* get the existing end-points */
2409  start = strip->start;
2410  end = strip->end;
2411 
2412  /* calculate new start position based on snapping mode */
2413  switch (mode) {
2414  case NLAEDIT_SNAP_CFRA: /* to current frame */
2415  strip->start = (float)scene->r.cfra;
2416  break;
2417  case NLAEDIT_SNAP_NEAREST_FRAME: /* to nearest frame */
2418  strip->start = floorf(start + 0.5f);
2419  break;
2420  case NLAEDIT_SNAP_NEAREST_SECOND: /* to nearest second */
2421  strip->start = floorf(start / secf + 0.5f) * secf;
2422  break;
2423  case NLAEDIT_SNAP_NEAREST_MARKER: /* to nearest marker */
2425  break;
2426  default: /* just in case... no snapping */
2427  strip->start = start;
2428  break;
2429  }
2430 
2431  /* get new endpoint based on start-point (and old length) */
2432  strip->end = strip->start + (end - start);
2433 
2434  /* apply transforms to meta-strip to its children */
2436 
2437  /* remove strip from track, and add to the temp buffer */
2438  BLI_remlink(&nlt->strips, strip);
2439  BLI_addtail(&tmp_strips, strip);
2440  }
2441  }
2442 
2443  /* try adding each meta-strip back to the track one at a time, to make sure they'll fit */
2444  for (strip = tmp_strips.first; strip; strip = stripn) {
2445  stripn = strip->next;
2446 
2447  /* remove from temp-strips list */
2448  BLI_remlink(&tmp_strips, strip);
2449 
2450  /* in case there's no space in the current track, try adding */
2451  if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
2452  /* need to add a new track above the current one */
2453  track = BKE_nlatrack_add(adt, nlt, is_liboverride);
2454  BKE_nlatrack_add_strip(track, strip, is_liboverride);
2455 
2456  /* clear temp meta-strips on this new track,
2457  * as we may not be able to get back to it */
2458  BKE_nlastrips_clear_metas(&track->strips, 0, 1);
2459 
2460  any_added = true;
2461  }
2462  }
2463 
2464  /* remove the meta-strips now that we're done */
2465  BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
2466 
2467  /* tag for recalculating the animation */
2468  ale->update |= ANIM_UPDATE_DEPS;
2469  }
2470 
2471  /* cleanup */
2472  ANIM_animdata_update(&ac, &anim_data);
2473  ANIM_animdata_freelist(&anim_data);
2474 
2475  /* refresh auto strip properties */
2476  ED_nla_postop_refresh(&ac);
2477 
2478  /* set notifier that things have changed */
2480  if (any_added) {
2482  }
2483 
2484  /* done */
2485  return OPERATOR_FINISHED;
2486 }
2487 
2489 {
2490  /* identifiers */
2491  ot->name = "Snap Strips";
2492  ot->idname = "NLA_OT_snap";
2493  ot->description = "Move start of strips to specified time";
2494 
2495  /* api callbacks */
2499 
2500  /* flags */
2502 
2503  /* properties */
2504  ot->prop = RNA_def_enum(ot->srna, "type", prop_nlaedit_snap_types, 0, "Type", "");
2505 }
2506 
2509 /* NLA Modifiers */
2510 
2511 /* -------------------------------------------------------------------- */
2516  PointerRNA *UNUSED(ptr),
2517  PropertyRNA *UNUSED(prop),
2518  bool *r_free)
2519 {
2520  EnumPropertyItem *item = NULL;
2521  int totitem = 0;
2522  int i = 0;
2523 
2524  if (C == NULL) {
2526  }
2527 
2528  /* start from 1 to skip the 'Invalid' modifier type */
2529  for (i = 1; i < FMODIFIER_NUM_TYPES; i++) {
2530  const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(i);
2531  int index;
2532 
2533  /* check if modifier is valid for this context */
2534  if (fmi == NULL) {
2535  continue;
2536  }
2537  if (i == FMODIFIER_TYPE_CYCLES) { /* we already have repeat... */
2538  continue;
2539  }
2540 
2542  if (index != -1) { /* Not all types are implemented yet... */
2543  RNA_enum_item_add(&item, &totitem, &rna_enum_fmodifier_type_items[index]);
2544  }
2545  }
2546 
2547  RNA_enum_item_end(&item, &totitem);
2548  *r_free = true;
2549 
2550  return item;
2551 }
2552 
2554 {
2555  bAnimContext ac;
2556 
2557  ListBase anim_data = {NULL, NULL};
2558  bAnimListElem *ale;
2559  int filter;
2560 
2561  FModifier *fcm;
2562  int type = RNA_enum_get(op->ptr, "type");
2563  const bool active_only = RNA_boolean_get(op->ptr, "only_active");
2564 
2565  /* get editor data */
2566  if (ANIM_animdata_get_context(C, &ac) == 0) {
2567  return OPERATOR_CANCELLED;
2568  }
2569 
2570  /* get a list of the editable tracks being shown in the NLA */
2573  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2574 
2575  /* for each NLA-Track, add the specified modifier to all selected strips */
2576  for (ale = anim_data.first; ale; ale = ale->next) {
2577  NlaTrack *nlt = (NlaTrack *)ale->data;
2578  NlaStrip *strip;
2579 
2581  /* No adding f-modifiers to strips in non-local tracks of override data. */
2582  continue;
2583  }
2584 
2585  for (strip = nlt->strips.first; strip; strip = strip->next) {
2586  /* can F-Modifier be added to the current strip? */
2587  if (active_only) {
2588  /* if not active, cannot add since we're only adding to active strip */
2589  if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
2590  continue;
2591  }
2592  }
2593  else {
2594  /* strip must be selected, since we're not just doing active */
2595  if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) {
2596  continue;
2597  }
2598  }
2599 
2600  /* sound clips are not affected by FModifiers */
2601  if (strip->type == NLASTRIP_TYPE_SOUND) {
2602  continue;
2603  }
2604 
2605  /* add F-Modifier of specified type to selected, and make it the active one */
2606  fcm = add_fmodifier(&strip->modifiers, type, NULL);
2607 
2608  if (fcm) {
2609  set_active_fmodifier(&strip->modifiers, fcm);
2610  ale->update |= ANIM_UPDATE_DEPS;
2611  }
2612  else {
2613  BKE_reportf(op->reports,
2614  RPT_ERROR,
2615  "Modifier could not be added to (%s : %s) (see console for details)",
2616  nlt->name,
2617  strip->name);
2618  }
2619  }
2620  }
2621 
2622  /* free temp data */
2623  ANIM_animdata_update(&ac, &anim_data);
2624  ANIM_animdata_freelist(&anim_data);
2625 
2626  /* set notifier that things have changed */
2628 
2629  /* done */
2630  return OPERATOR_FINISHED;
2631 }
2632 
2634 {
2635  /* identifiers */
2636  ot->name = "Add F-Modifier";
2637  ot->idname = "NLA_OT_fmodifier_add";
2638  ot->description = "Add F-Modifier to the active/selected NLA-Strips";
2639 
2640  /* api callbacks */
2644 
2645  /* flags */
2647 
2648  /* id-props */
2649  ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
2652 
2654  "only_active",
2655  true,
2656  "Only Active",
2657  "Only add a F-Modifier of the specified type to the active strip");
2658 }
2659 
2662 /* -------------------------------------------------------------------- */
2667 {
2668  bAnimContext ac;
2669  ListBase anim_data = {NULL, NULL};
2670  bAnimListElem *ale;
2671  int filter;
2672  bool ok = false;
2673 
2674  /* get editor data */
2675  if (ANIM_animdata_get_context(C, &ac) == 0) {
2676  return OPERATOR_CANCELLED;
2677  }
2678 
2679  /* clear buffer first */
2681 
2682  /* get a list of the editable tracks being shown in the NLA */
2685  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2686 
2687  /* for each NLA-Track, add the specified modifier to all selected strips */
2688  for (ale = anim_data.first; ale; ale = ale->next) {
2689  NlaTrack *nlt = (NlaTrack *)ale->data;
2690  NlaStrip *strip;
2691 
2692  for (strip = nlt->strips.first; strip; strip = strip->next) {
2693  /* only add F-Modifier if on active strip? */
2694  if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
2695  continue;
2696  }
2697 
2698  /* TODO: when 'active' vs 'all' boolean is added, change last param! */
2699  ok |= ANIM_fmodifiers_copy_to_buf(&strip->modifiers, 0);
2700  }
2701  }
2702 
2703  /* free temp data */
2704  ANIM_animdata_freelist(&anim_data);
2705 
2706  /* successful or not? */
2707  if (ok == 0) {
2708  BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied");
2709  return OPERATOR_CANCELLED;
2710  }
2711 
2712  /* no updates needed - copy is non-destructive operation */
2713  return OPERATOR_FINISHED;
2714 }
2715 
2717 {
2718  /* identifiers */
2719  ot->name = "Copy F-Modifiers";
2720  ot->idname = "NLA_OT_fmodifier_copy";
2721  ot->description = "Copy the F-Modifier(s) of the active NLA-Strip";
2722 
2723  /* api callbacks */
2726 
2727  /* flags */
2729 
2730  /* id-props */
2731 #if 0
2733  "all",
2734  1,
2735  "All F-Modifiers",
2736  "Copy all the F-Modifiers, instead of just the active one");
2737 #endif
2738 }
2739 
2742 /* -------------------------------------------------------------------- */
2747 {
2748  bAnimContext ac;
2749  ListBase anim_data = {NULL, NULL};
2750  bAnimListElem *ale;
2751  int filter, ok = 0;
2752 
2753  const bool active_only = RNA_boolean_get(op->ptr, "only_active");
2754  const bool replace = RNA_boolean_get(op->ptr, "replace");
2755 
2756  /* get editor data */
2757  if (ANIM_animdata_get_context(C, &ac) == 0) {
2758  return OPERATOR_CANCELLED;
2759  }
2760 
2761  /* get a list of the editable tracks being shown in the NLA */
2764  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2765 
2766  /* for each NLA-Track, add the specified modifier to all selected strips */
2767  for (ale = anim_data.first; ale; ale = ale->next) {
2768  NlaTrack *nlt = (NlaTrack *)ale->data;
2769  NlaStrip *strip;
2770 
2772  /* No pasting in non-local tracks of override data. */
2773  continue;
2774  }
2775 
2776  for (strip = nlt->strips.first; strip; strip = strip->next) {
2777  /* can F-Modifier be added to the current strip? */
2778  if (active_only) {
2779  /* if not active, cannot add since we're only adding to active strip */
2780  if ((strip->flag & NLASTRIP_FLAG_ACTIVE) == 0) {
2781  continue;
2782  }
2783  }
2784  else {
2785  /* strip must be selected, since we're not just doing active */
2786  if ((strip->flag & NLASTRIP_FLAG_SELECT) == 0) {
2787  continue;
2788  }
2789  }
2790 
2791  /* paste FModifiers from buffer */
2792  ok += ANIM_fmodifiers_paste_from_buf(&strip->modifiers, replace, NULL);
2793  ale->update |= ANIM_UPDATE_DEPS;
2794  }
2795  }
2796 
2797  /* clean up */
2798  ANIM_animdata_update(&ac, &anim_data);
2799  ANIM_animdata_freelist(&anim_data);
2800 
2801  /* successful or not? */
2802  if (ok) {
2804  return OPERATOR_FINISHED;
2805  }
2806 
2807  BKE_report(op->reports, RPT_ERROR, "No F-Modifiers to paste");
2808  return OPERATOR_CANCELLED;
2809 }
2810 
2812 {
2813  /* identifiers */
2814  ot->name = "Paste F-Modifiers";
2815  ot->idname = "NLA_OT_fmodifier_paste";
2816  ot->description = "Add copied F-Modifiers to the selected NLA-Strips";
2817 
2818  /* api callbacks */
2821 
2822  /* flags */
2824 
2825  /* properties */
2827  ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
2829  ot->srna,
2830  "replace",
2831  false,
2832  "Replace Existing",
2833  "Replace existing F-Modifiers, instead of just appending to the end of the existing list");
2834 }
2835 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
const FModifierTypeInfo * get_fmodifier_typeinfo(int type)
Definition: fmodifier.c:1052
void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm)
Definition: fmodifier.c:1266
void BKE_fcurve_handles_recalc(struct FCurve *fcu)
Definition: fcurve.c:1303
struct FModifier * add_fmodifier(ListBase *modifiers, int type, struct FCurve *owner_fcu)
Definition: fmodifier.c:1087
struct ID * BKE_id_copy(struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
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:855
bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end)
Definition: nla.c:1137
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip)
Definition: nla.c:1625
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
Definition: nla.c:877
void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip)
Definition: nla.c:950
bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride)
Definition: nla.c:1168
struct NlaStrip * BKE_nla_add_soundstrip(struct Main *bmain, struct Scene *scene, struct Speaker *speaker)
Definition: nla.c:477
@ NLATIME_CONVERT_MAP
Definition: BKE_nla.h:360
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:357
bool BKE_nlastrips_has_space(ListBase *strips, float start, float end)
Definition: nla.c:690
void BKE_nla_validate_state(struct AnimData *adt)
Definition: nla.c:1798
struct NlaStrip * BKE_nlastrip_new(struct bAction *act)
Definition: nla.c:396
struct NlaStrip * BKE_nlastrip_copy(struct Main *bmain, struct NlaStrip *strip, bool use_same_action, int flag)
Definition: nla.c:148
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt)
Definition: nla.c:1083
bool BKE_nla_tweakmode_enter(struct AnimData *adt)
Definition: nla.c:2019
struct NlaTrack * BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev, bool is_liboverride)
Definition: nla.c:353
void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip)
Definition: nla.c:1435
void BKE_nla_tweakmode_exit(struct AnimData *adt)
Definition: nla.c:2092
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user)
Definition: nla.c:64
void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp)
Definition: nla.c:802
struct NlaTrack * BKE_nlatrack_find_tweaked(struct AnimData *adt)
Definition: nla.c:1052
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:301
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
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:190
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
#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:566
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:553
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_OB
Definition: DNA_ID_enums.h:47
@ ACT_FRAME_RANGE
@ NLASTRIP_FLAG_ACTIVE
@ NLASTRIP_FLAG_TEMP_META
@ NLASTRIP_FLAG_AUTO_BLENDS
@ NLASTRIP_FLAG_MUTED
@ NLASTRIP_FLAG_SELECT
@ NLASTRIP_FLAG_SYNC_LENGTH
@ ADT_NLA_SOLO_TRACK
@ ADT_NLA_EVAL_UPPER_TRACKS
@ 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 SCER_PRV_RANGE
#define FPS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define NLACHANNEL_STEP(snla)
Definition: ED_anim_api.h:466
@ ACHANNEL_ROLE_CHANNEL
Definition: ED_anim_api.h:544
@ ALE_ACT
Definition: ED_anim_api.h:258
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:268
#define NLACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:460
@ ACHANNEL_SETTING_SELECT
Definition: ED_anim_api.h:561
#define NLACHANNEL_HEIGHT(snla)
Definition: ED_anim_api.h:462
@ ANIMFILTER_ACTIVE
Definition: ED_anim_api.h:303
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:312
@ ANIMFILTER_ANIMDATA
Definition: ED_anim_api.h:322
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:292
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:300
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:325
@ ANIMFILTER_FCURVESONLY
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:308
void ED_area_tag_redraw(ScrArea *area)
Definition: area.c:729
bool ED_operator_nla_active(struct bContext *C)
Definition: screen_ops.c:349
_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.
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:294
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
void UI_view2d_center_set(struct View2D *v2d, float x, float y)
Definition: view2d.cc:1946
#define V2D_LOCK_COPY
Definition: UI_view2d.h:82
void UI_view2d_sync(struct bScreen *screen, struct ScrArea *area, struct View2D *v2dcur, int flag)
Definition: view2d.cc:851
void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y)
Definition: view2d.cc:1936
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_NLA_ACTCHANGE
Definition: WM_types.h:446
#define NC_ANIMATION
Definition: WM_types.h:338
#define NC_SCENE
Definition: WM_types.h:328
#define NA_ADDED
Definition: WM_types.h:525
#define NA_EDITED
Definition: WM_types.h:523
#define ND_FRAME
Definition: WM_types.h:382
#define NA_REMOVED
Definition: WM_types.h:526
#define ND_NLA_ORDER
Definition: WM_types.h:448
#define ND_NLA
Definition: WM_types.h:445
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:397
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:302
void ANIM_center_frame(struct bContext *C, int smooth_viewtx)
Definition: anim_draw.c:619
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:379
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3447
int ED_markers_find_nearest_marker_time(ListBase *markers, float x)
Definition: anim_markers.c:163
Scene scene
int len
Definition: draw_manager.c:108
bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *curve)
Definition: fmodifier_ui.c:989
void ANIM_fmodifiers_copybuf_free(void)
Definition: fmodifier_ui.c:954
bool ANIM_fmodifiers_copy_to_buf(ListBase *modifiers, bool active)
Definition: fmodifier_ui.c:960
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
#define GS(x)
Definition: iris.c:225
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:31
static ulong * next
#define floorf(x)
Definition: metal/compat.h:224
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:628
bool nlaedit_add_tracks_empty(bAnimContext *ac)
Definition: nla_channels.c:604
void NLA_OT_view_frame(wmOperatorType *ot)
Definition: nla_edit.c:583
static int nlaedit_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:372
static int nlaedit_snap_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2358
static int nlaedit_add_transition_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:762
void NLA_OT_view_all(wmOperatorType *ot)
Definition: nla_edit.c:540
void NLA_OT_fmodifier_add(wmOperatorType *ot)
Definition: nla_edit.c:2633
static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:1954
static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1770
void NLA_OT_split(wmOperatorType *ot)
Definition: nla_edit.c:1492
void NLA_OT_tweakmode_exit(wmOperatorType *ot)
Definition: nla_edit.c:279
static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2553
void ED_nla_postop_refresh(bAnimContext *ac)
Definition: nla_edit.c:59
static int nlaedit_viewall(bContext *C, const bool only_sel)
Definition: nla_edit.c:476
static int nlaedit_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:2276
void NLA_OT_soundclip_add(wmOperatorType *ot)
Definition: nla_edit.c:964
void NLA_OT_tweakmode_enter(wmOperatorType *ot)
Definition: nla_edit.c:168
void NLA_OT_clear_scale(wmOperatorType *ot)
Definition: nla_edit.c:2324
void NLA_OT_make_single_user(wmOperatorType *ot)
Definition: nla_edit.c:2117
static int nlaedit_viewall_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:528
void NLA_OT_meta_add(wmOperatorType *ot)
Definition: nla_edit.c:1042
static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const bool only_sel)
Definition: nla_edit.c:314
static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2746
void NLA_OT_meta_remove(wmOperatorType *ot)
Definition: nla_edit.c:1109
void NLA_OT_snap(wmOperatorType *ot)
Definition: nla_edit.c:2488
static const EnumPropertyItem * nla_fmodifier_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: nla_edit.c:2515
static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:257
static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1428
void NLA_OT_swap(wmOperatorType *ot)
Definition: nla_edit.c:1747
void NLA_OT_mute_toggle(wmOperatorType *ot)
Definition: nla_edit.c:1564
void NLA_OT_move_up(wmOperatorType *ot)
Definition: nla_edit.c:1839
static void nlaedit_split_strip_meta(NlaTrack *nlt, NlaStrip *strip)
Definition: nla_edit.c:1420
void NLA_OT_delete(wmOperatorType *ot)
Definition: nla_edit.c:1327
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:2049
void NLA_OT_previewrange_set(wmOperatorType *ot)
Definition: nla_edit.c:402
void NLA_OT_fmodifier_copy(wmOperatorType *ot)
Definition: nla_edit.c:2716
void NLA_OT_move_down(wmOperatorType *ot)
Definition: nla_edit.c:1931
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:576
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:534
static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:1133
void NLA_OT_view_selected(wmOperatorType *ot)
Definition: nla_edit.c:555
static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:93
static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1258
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:1355
bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
Definition: nla_edit.c:208
static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1862
static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:610
void NLA_OT_actionclip_add(wmOperatorType *ot)
Definition: nla_edit.c:728
void NLA_OT_fmodifier_paste(wmOperatorType *ot)
Definition: nla_edit.c:2811
static bool nla_channels_get_selected_extents(bAnimContext *ac, float *r_min, float *r_max)
Definition: nla_edit.c:430
void NLA_OT_action_sync_length(wmOperatorType *ot)
Definition: nla_edit.c:2018
static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:2666
static int nlaedit_swap_exec(bContext *C, wmOperator *op)
Definition: nla_edit.c:1587
static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1065
void NLA_OT_apply_scale(wmOperatorType *ot)
Definition: nla_edit.c:2253
static int nlaedit_toggle_mute_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:1517
static const EnumPropertyItem prop_nlaedit_snap_types[]
Definition: nla_edit.c:2348
static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_edit.c:2156
static short bezt_apply_nlamapping(KeyframeEditData *ked, BezTriple *bezt)
Definition: nla_edit.c:2142
static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: nla_edit.c:1219
bool nlaop_poll_tweakmode_on(bContext *C)
Definition: nla_ops.c:50
bool nlaop_poll_tweakmode_off(bContext *C)
Definition: nla_ops.c:28
@ NLAEDIT_SNAP_NEAREST_MARKER
Definition: nla_intern.h:57
@ NLAEDIT_SNAP_NEAREST_SECOND
Definition: nla_intern.h:56
@ NLAEDIT_SNAP_NEAREST_FRAME
Definition: nla_intern.h:55
@ NLAEDIT_SNAP_CFRA
Definition: nla_intern.h:54
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
Definition: rna_access.c:1736
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
Definition: rna_define.c:2848
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
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:3783
const EnumPropertyItem rna_enum_fmodifier_type_items[]
Definition: rna_fcurve.c:31
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:26
#define min(a, b)
Definition: sort.c:35
NlaStrip * actstrip
float vec[3][3]
char name[66]
Definition: DNA_ID.h:378
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase actions
Definition: BKE_main.h:191
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:604
eAnimChannel_Role channel_role
Definition: ED_anim_api.h:583
ListBase * markers
Definition: ED_anim_api.h:92
struct ARegion * region
Definition: ED_anim_api.h:76
struct Scene * scene
Definition: ED_anim_api.h:84
struct bDopeSheet * ads
Definition: ED_anim_api.h:79
short datatype
Definition: ED_anim_api.h:62
void * data
Definition: ED_anim_api.h:60
struct ReportList * reports
Definition: ED_anim_api.h:95
struct Main * bmain
Definition: ED_anim_api.h:82
struct SpaceLink * sl
Definition: ED_anim_api.h:74
struct bAnimListElem * next
Definition: ED_anim_api.h:127
struct AnimData * adt
Definition: ED_anim_api.h:162
struct bAnimListElem * prev
Definition: ED_anim_api.h:127
struct ID * id
Definition: ED_anim_api.h:160
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
float max
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_operator_smooth_viewtx_get(const wmOperator *op)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))