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