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