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