Blender  V2.93
nla_channels.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
17  * All rights reserved.
18  */
19 
24 #include <math.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "DNA_anim_types.h"
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32 
33 #include "BLI_blenlib.h"
34 #include "BLI_utildefines.h"
35 
36 #include "BKE_anim_data.h"
37 #include "BKE_context.h"
38 #include "BKE_global.h"
39 #include "BKE_nla.h"
40 #include "BKE_report.h"
41 #include "BKE_scene.h"
42 #include "BKE_screen.h"
43 
44 #include "ED_anim_api.h"
45 #include "ED_keyframes_edit.h"
46 #include "ED_object.h"
47 #include "ED_screen.h"
48 
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51 
52 #include "WM_api.h"
53 #include "WM_types.h"
54 
55 #include "UI_interface.h"
56 
57 #include "DEG_depsgraph.h"
58 #include "DEG_depsgraph_build.h"
59 
60 #include "UI_view2d.h"
61 
62 #include "nla_intern.h" /* own include */
63 
64 /* *********************************************** */
65 /* Operators for NLA channels-list which need to be different
66  * from the standard Animation Editor ones */
67 
68 /* ******************** Mouse-Click Operator *********************** */
69 /* Depending on the channel that was clicked on, the mouse click will activate whichever
70  * part of the channel is relevant.
71  *
72  * NOTE: eventually,
73  * this should probably be phased out when many of these things are replaced with buttons
74  * --> Most channels are now selection only.
75  */
76 
77 static int mouse_nla_channels(
78  bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode)
79 {
80  ListBase anim_data = {NULL, NULL};
81  bAnimListElem *ale;
82  int filter;
83 
84  View2D *v2d = &ac->region->v2d;
85  int notifierFlags = 0;
86 
87  /* get the channel that was clicked on */
88  /* filter channels */
90  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
91 
92  /* get channel from index */
93  ale = BLI_findlink(&anim_data, channel_index);
94  if (ale == NULL) {
95  /* channel not found */
96  if (G.debug & G_DEBUG) {
97  printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n",
98  channel_index);
99  }
100 
101  ANIM_animdata_freelist(&anim_data);
102  return 0;
103  }
104 
105  /* action to take depends on what channel we've got */
106  /* WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c */
107  switch (ale->type) {
108  case ANIMTYPE_SCENE: {
109  Scene *sce = (Scene *)ale->data;
110  AnimData *adt = sce->adt;
111 
112  /* set selection status */
113  if (selectmode == SELECT_INVERT) {
114  /* swap select */
115  sce->flag ^= SCE_DS_SELECTED;
116  if (adt) {
117  adt->flag ^= ADT_UI_SELECTED;
118  }
119  }
120  else {
121  sce->flag |= SCE_DS_SELECTED;
122  if (adt) {
123  adt->flag |= ADT_UI_SELECTED;
124  }
125  }
126 
127  notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
128  break;
129  }
130  case ANIMTYPE_OBJECT: {
131  ViewLayer *view_layer = ac->view_layer;
132  Base *base = (Base *)ale->data;
133  Object *ob = base->object;
134  AnimData *adt = ob->adt;
135 
136  if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) {
137  /* set selection status */
138  if (selectmode == SELECT_INVERT) {
139  /* swap select */
141 
142  if (adt) {
143  adt->flag ^= ADT_UI_SELECTED;
144  }
145  }
146  else {
147  /* deselect all */
148  /* TODO: should this deselect all other types of channels too? */
149  LISTBASE_FOREACH (Base *, b, &view_layer->object_bases) {
151  if (b->object->adt) {
152  b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
153  }
154  }
155 
156  /* select object now */
158  if (adt) {
159  adt->flag |= ADT_UI_SELECTED;
160  }
161  }
162 
163  /* change active object - regardless of whether it is now selected [T37883] */
164  ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */
165 
166  if ((adt) && (adt->flag & ADT_UI_SELECTED)) {
167  adt->flag |= ADT_UI_ACTIVE;
168  }
169 
170  /* notifiers - channel was selected */
171  notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
172  }
173  break;
174  }
175  case ANIMTYPE_FILLACTD: /* Action Expander */
176  case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
177  case ANIMTYPE_DSLAM:
178  case ANIMTYPE_DSCAM:
180  case ANIMTYPE_DSCUR:
181  case ANIMTYPE_DSSKEY:
182  case ANIMTYPE_DSWOR:
183  case ANIMTYPE_DSNTREE:
184  case ANIMTYPE_DSPART:
185  case ANIMTYPE_DSMBALL:
186  case ANIMTYPE_DSARM:
187  case ANIMTYPE_DSMESH:
188  case ANIMTYPE_DSTEX:
189  case ANIMTYPE_DSLAT:
191  case ANIMTYPE_DSSPK:
192  case ANIMTYPE_DSGPENCIL:
193  case ANIMTYPE_PALETTE:
194  case ANIMTYPE_DSHAIR:
196  case ANIMTYPE_DSVOLUME:
197  case ANIMTYPE_DSSIMULATION: {
198  /* sanity checking... */
199  if (ale->adt) {
200  /* select/deselect */
201  if (selectmode == SELECT_INVERT) {
202  /* inverse selection status of this AnimData block only */
203  ale->adt->flag ^= ADT_UI_SELECTED;
204  }
205  else {
206  /* select AnimData block by itself */
208  ale->adt->flag |= ADT_UI_SELECTED;
209  }
210 
211  /* set active? */
212  if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
213  ale->adt->flag |= ADT_UI_ACTIVE;
214  }
215  }
216 
217  notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
218  break;
219  }
220  case ANIMTYPE_NLATRACK: {
221  NlaTrack *nlt = (NlaTrack *)ale->data;
222  AnimData *adt = ale->adt;
223  short offset;
224 
225  /* offset for start of channel (on LHS of channel-list) */
226  if (ale->id) {
227  /* special exception for materials and particles */
228  if (ELEM(GS(ale->id->name), ID_MA, ID_PA)) {
229  offset = 21 + NLACHANNEL_BUTTON_WIDTH;
230  }
231  else {
232  offset = 14;
233  }
234  }
235  else {
236  offset = 0;
237  }
238 
239  if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
240  /* toggle protection (only if there's a toggle there) */
241  nlt->flag ^= NLATRACK_PROTECTED;
242 
243  /* notifier flags - channel was edited */
244  notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
245  }
246  else if (x >= (v2d->cur.xmax - 2 * NLACHANNEL_BUTTON_WIDTH)) {
247  /* toggle mute */
248  nlt->flag ^= NLATRACK_MUTED;
249 
250  /* notifier flags - channel was edited */
251  notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
252  ale->update |= ANIM_UPDATE_DEPS;
253  }
254  else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) {
255  /* toggle 'solo' */
256  BKE_nlatrack_solo_toggle(adt, nlt);
257 
258  /* notifier flags - channel was edited */
259  notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
260  ale->update |= ANIM_UPDATE_DEPS;
261  }
262  else if (nlaedit_is_tweakmode_on(ac) == 0) {
263  /* set selection */
264  if (selectmode == SELECT_INVERT) {
265  /* inverse selection status of this F-Curve only */
266  nlt->flag ^= NLATRACK_SELECTED;
267  }
268  else {
269  /* select F-Curve by itself */
271  nlt->flag |= NLATRACK_SELECTED;
272  }
273 
274  /* if NLA-Track is selected now,
275  * make NLA-Track the 'active' one in the visible list */
276  if (nlt->flag & NLATRACK_SELECTED) {
278  }
279 
280  /* notifier flags - channel was selected */
281  notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
282  }
283  break;
284  }
285  case ANIMTYPE_NLAACTION: {
286  AnimData *adt = BKE_animdata_from_id(ale->id);
287 
288  /* button region... */
289  if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) {
290  if (nlaedit_is_tweakmode_on(ac) == 0) {
291  /* 'push-down' action - only usable when not in TweakMode */
292  /* TODO: make this use the operator instead of calling the function directly
293  * however, calling the operator requires that we supply the args,
294  * and that works with proper buttons only */
296  }
297  else {
298  /* when in tweakmode, this button becomes the toggle for mapped editing */
299  adt->flag ^= ADT_NLA_EDIT_NOMAP;
300  }
301 
302  /* changes to NLA-Action occurred */
303  notifierFlags |= ND_NLA_ACTCHANGE;
304  ale->update |= ANIM_UPDATE_DEPS;
305  }
306  /* OR rest of name... */
307  else {
308  /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
309  * - this is useful when there's no clear divider, and makes more sense in
310  * the case of users trying to use this to change actions
311  * - in tweakmode, clicking here gets us out of tweakmode, as changing selection
312  * while in tweakmode is really evil!
313  * - we disable "solo" flags too, to make it easier to work with stashed actions
314  * with less trouble
315  */
316  if (nlaedit_is_tweakmode_on(ac)) {
317  /* exit tweakmode immediately */
318  nlaedit_disable_tweakmode(ac, true);
319 
320  /* changes to NLA-Action occurred */
321  notifierFlags |= ND_NLA_ACTCHANGE;
322  ale->update |= ANIM_UPDATE_DEPS;
323  }
324  else {
325  /* select/deselect */
326  if (selectmode == SELECT_INVERT) {
327  /* inverse selection status of this AnimData block only */
328  adt->flag ^= ADT_UI_SELECTED;
329  }
330  else {
331  /* select AnimData block by itself */
333  adt->flag |= ADT_UI_SELECTED;
334  }
335 
336  /* set active? */
337  if (adt->flag & ADT_UI_SELECTED) {
338  adt->flag |= ADT_UI_ACTIVE;
339  }
340 
341  notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
342  }
343  }
344  break;
345  }
346  default:
347  if (G.debug & G_DEBUG) {
348  printf("Error: Invalid channel type in mouse_nla_channels()\n");
349  }
350  break;
351  }
352 
353  /* free channels */
354  ANIM_animdata_update(ac, &anim_data);
355  ANIM_animdata_freelist(&anim_data);
356 
357  /* return the notifier-flags set */
358  return notifierFlags;
359 }
360 
361 /* ------------------- */
362 
363 /* handle clicking */
365 {
366  bAnimContext ac;
367  SpaceNla *snla;
368  ARegion *region;
369  View2D *v2d;
370  int channel_index;
371  int notifierFlags = 0;
372  short selectmode;
373  float x, y;
374 
375  /* get editor data */
376  if (ANIM_animdata_get_context(C, &ac) == 0) {
377  return OPERATOR_CANCELLED;
378  }
379 
380  /* get useful pointers from animation context data */
381  snla = (SpaceNla *)ac.sl;
382  region = ac.region;
383  v2d = &region->v2d;
384 
385  /* select mode is either replace (deselect all, then add) or add/extend */
386  if (RNA_boolean_get(op->ptr, "extend")) {
387  selectmode = SELECT_INVERT;
388  }
389  else {
390  selectmode = SELECT_REPLACE;
391  }
392 
393  /* Figure out which channel user clicked in. */
394  UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
396  NLACHANNEL_STEP(snla),
397  0,
399  x,
400  y,
401  NULL,
402  &channel_index);
403 
404  /* handle mouse-click in the relevant channel then */
405  notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode);
406 
407  /* set notifier that things have changed */
408  WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
409 
410  return OPERATOR_FINISHED;
411 }
412 
414 {
415  PropertyRNA *prop;
416 
417  /* identifiers */
418  ot->name = "Mouse Click on NLA Channels";
419  ot->idname = "NLA_OT_channels_click";
420  ot->description = "Handle clicks to select NLA channels";
421 
422  /* api callbacks */
425 
426  /* flags */
427  ot->flag = OPTYPE_UNDO;
428 
429  /* props */
430  prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); /* SHIFTKEY */
432 }
433 
434 /* *********************************************** */
435 /* Special Operators */
436 
437 /* ******************** Action Push Down ******************************** */
438 
440 {
441  bAnimContext ac;
442  ID *id = NULL;
443  AnimData *adt = NULL;
444  int channel_index = RNA_int_get(op->ptr, "channel_index");
445 
446  /* get editor data */
447  if (ANIM_animdata_get_context(C, &ac) == 0) {
448  return OPERATOR_CANCELLED;
449  }
450 
451  /* get anim-channel to use (or more specifically, the animdata block behind it) */
452  if (channel_index == -1) {
453  PointerRNA adt_ptr = {NULL};
454 
455  /* active animdata block */
456  if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) {
457  BKE_report(op->reports,
458  RPT_ERROR,
459  "No active AnimData block to use "
460  "(select a data-block expander first or set the appropriate flags on an AnimData "
461  "block)");
462  return OPERATOR_CANCELLED;
463  }
464 
465  id = adt_ptr.owner_id;
466  adt = adt_ptr.data;
467  }
468  else {
469  /* indexed channel */
470  ListBase anim_data = {NULL, NULL};
471  bAnimListElem *ale;
472  int filter;
473 
474  /* filter channels */
476  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
477 
478  /* get channel from index */
479  ale = BLI_findlink(&anim_data, channel_index);
480  if (ale == NULL) {
481  BKE_reportf(op->reports, RPT_ERROR, "No animation channel found at index %d", channel_index);
482  ANIM_animdata_freelist(&anim_data);
483  return OPERATOR_CANCELLED;
484  }
485  if (ale->type != ANIMTYPE_NLAACTION) {
486  BKE_reportf(op->reports,
487  RPT_ERROR,
488  "Animation channel at index %d is not a NLA 'Active Action' channel",
489  channel_index);
490  ANIM_animdata_freelist(&anim_data);
491  return OPERATOR_CANCELLED;
492  }
493 
494  /* grab AnimData from the channel */
495  adt = ale->adt;
496  id = ale->id;
497 
498  /* we don't need anything here anymore, so free it all */
499  ANIM_animdata_freelist(&anim_data);
500  }
501 
502  /* double-check that we are free to push down here... */
503  if (adt == NULL) {
504  BKE_report(op->reports, RPT_WARNING, "Internal Error - AnimData block is not valid");
505  return OPERATOR_CANCELLED;
506  }
507  if (nlaedit_is_tweakmode_on(&ac)) {
508  BKE_report(op->reports,
509  RPT_WARNING,
510  "Cannot push down actions while tweaking a strip's action, exit tweak mode first");
511  return OPERATOR_CANCELLED;
512  }
513  if (adt->action == NULL) {
514  BKE_report(op->reports, RPT_WARNING, "No active action to push down");
515  return OPERATOR_CANCELLED;
516  }
517 
518  /* 'push-down' action - only usable when not in TweakMode */
520 
521  struct Main *bmain = CTX_data_main(C);
523 
524  /* The action needs updating too, as FCurve modifiers are to be reevaluated. They won't extend
525  * beyond the NLA strip after pushing down to the NLA. */
527 
528  /* set notifier that things have changed */
530  return OPERATOR_FINISHED;
531 }
532 
534 {
535  /* identifiers */
536  ot->name = "Push Down Action";
537  ot->idname = "NLA_OT_action_pushdown";
538  ot->description = "Push action down onto the top of the NLA stack as a new strip";
539 
540  /* callbacks */
543 
544  /* flags */
546 
547  /* properties */
548  ot->prop = RNA_def_int(ot->srna,
549  "channel_index",
550  -1,
551  -1,
552  INT_MAX,
553  "Channel Index",
554  "Index of NLA action channel to perform pushdown operation on",
555  0,
556  INT_MAX);
558 }
559 
560 /* ******************** Action Unlink ******************************** */
561 
563 {
564  if (ED_operator_nla_active(C)) {
565  PointerRNA adt_ptr;
566  return (nla_panel_context(C, &adt_ptr, NULL, NULL) && (adt_ptr.data != NULL));
567  }
568 
569  /* something failed... */
570  return false;
571 }
572 
574 {
575  PointerRNA adt_ptr;
576  AnimData *adt;
577 
578  /* check context and also validity of pointer */
579  if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) {
580  return OPERATOR_CANCELLED;
581  }
582 
583  /* get animdata */
584  adt = adt_ptr.data;
585  if (adt == NULL) {
586  return OPERATOR_CANCELLED;
587  }
588 
589  /* do unlinking */
590  if (adt->action) {
591  bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
592  ED_animedit_unlink_action(C, adt_ptr.owner_id, adt, adt->action, op->reports, force_delete);
593  }
594 
595  return OPERATOR_FINISHED;
596 }
597 
598 static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
599 {
600  /* NOTE: this is hardcoded to match the behavior for the unlink button
601  * (in interface_templates.c) */
602  RNA_boolean_set(op->ptr, "force_delete", event->shift != 0);
603  return nla_action_unlink_exec(C, op);
604 }
605 
607 {
608  PropertyRNA *prop;
609 
610  /* identifiers */
611  ot->name = "Unlink Action";
612  ot->idname = "NLA_OT_action_unlink";
613  ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
614 
615  /* callbacks */
619 
620  /* properties */
621  prop = RNA_def_boolean(ot->srna,
622  "force_delete",
623  false,
624  "Force Delete",
625  "Clear Fake User and remove copy stashed in this data-block's NLA stack");
627 }
628 
629 /* ******************** Add Tracks Operator ***************************** */
630 /* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
631 
632 /* helper - add NLA Tracks alongside existing ones */
633 bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
634 {
635  ListBase anim_data = {NULL, NULL};
636  bAnimListElem *ale;
637  int filter;
638  AnimData *lastAdt = NULL;
639  bool added = false;
640 
641  /* get a list of the (selected) NLA Tracks being shown in the NLA */
644  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
645 
646  /* add tracks... */
647  for (ale = anim_data.first; ale; ale = ale->next) {
648  if (ale->type == ANIMTYPE_NLATRACK) {
649  NlaTrack *nlt = (NlaTrack *)ale->data;
650  AnimData *adt = ale->adt;
651 
652  const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
653 
654  /* check if just adding a new track above this one,
655  * or whether we're adding a new one to the top of the stack that this one belongs to
656  */
657  if (above_sel) {
658  /* just add a new one above this one */
659  BKE_nlatrack_add(adt, nlt, is_liboverride);
660  ale->update = ANIM_UPDATE_DEPS;
661  added = true;
662  }
663  else if ((lastAdt == NULL) || (adt != lastAdt)) {
664  /* add one track to the top of the owning AnimData's stack,
665  * then don't add anymore to this stack */
666  BKE_nlatrack_add(adt, NULL, is_liboverride);
667  lastAdt = adt;
668  ale->update = ANIM_UPDATE_DEPS;
669  added = true;
670  }
671  }
672  }
673 
674  /* free temp data */
675  ANIM_animdata_update(ac, &anim_data);
676  ANIM_animdata_freelist(&anim_data);
677 
678  return added;
679 }
680 
681 /* helper - add NLA Tracks to empty (and selected) AnimData blocks */
683 {
684  ListBase anim_data = {NULL, NULL};
685  bAnimListElem *ale;
686  int filter;
687  bool added = false;
688 
689  /* get a list of the selected AnimData blocks in the NLA */
692  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
693 
694  /* check if selected AnimData blocks are empty, and add tracks if so... */
695  for (ale = anim_data.first; ale; ale = ale->next) {
696  AnimData *adt = ale->adt;
697 
698  /* sanity check */
700 
701  /* ensure it is empty */
702  if (BLI_listbase_is_empty(&adt->nla_tracks)) {
703  /* add new track to this AnimData block then */
705  ale->update = ANIM_UPDATE_DEPS;
706  added = true;
707  }
708  }
709 
710  /* cleanup */
711  ANIM_animdata_update(ac, &anim_data);
712  ANIM_animdata_freelist(&anim_data);
713 
714  return added;
715 }
716 
717 /* ----- */
718 
720 {
721  bAnimContext ac;
722  bool above_sel = RNA_boolean_get(op->ptr, "above_selected");
723  bool op_done = false;
724 
725  /* get editor data */
726  if (ANIM_animdata_get_context(C, &ac) == 0) {
727  return OPERATOR_CANCELLED;
728  }
729 
730  /* perform adding in two passes - existing first so that we don't double up for empty */
731  op_done |= nlaedit_add_tracks_existing(&ac, above_sel);
732  op_done |= nlaedit_add_tracks_empty(&ac);
733 
734  /* done? */
735  if (op_done) {
737 
738  /* set notifier that things have changed */
740 
741  /* done */
742  return OPERATOR_FINISHED;
743  }
744 
745  /* failed to add any tracks */
746  BKE_report(
747  op->reports, RPT_WARNING, "Select an existing NLA Track or an empty action line first");
748 
749  /* not done */
750  return OPERATOR_CANCELLED;
751 }
752 
754 {
755  /* identifiers */
756  ot->name = "Add Tracks";
757  ot->idname = "NLA_OT_tracks_add";
758  ot->description = "Add NLA-Tracks above/after the selected tracks";
759 
760  /* api callbacks */
763 
764  /* flags */
766 
767  /* properties */
769  "above_selected",
770  0,
771  "Above Selected",
772  "Add a new NLA Track above every existing selected one");
773 }
774 
775 /* ******************** Delete Tracks Operator ***************************** */
776 /* Delete selected NLA Tracks */
777 
779 {
780  bAnimContext ac;
781 
782  ListBase anim_data = {NULL, NULL};
783  bAnimListElem *ale;
784  int filter;
785 
786  /* get editor data */
787  if (ANIM_animdata_get_context(C, &ac) == 0) {
788  return OPERATOR_CANCELLED;
789  }
790 
791  /* get a list of the AnimData blocks being shown in the NLA */
794  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
795 
796  /* delete tracks */
797  for (ale = anim_data.first; ale; ale = ale->next) {
798  if (ale->type == ANIMTYPE_NLATRACK) {
799  NlaTrack *nlt = (NlaTrack *)ale->data;
800  AnimData *adt = ale->adt;
801 
803  /* No deletion of non-local tracks of override data. */
804  continue;
805  }
806 
807  /* if track is currently 'solo', then AnimData should have its
808  * 'has solo' flag disabled
809  */
810  if (nlt->flag & NLATRACK_SOLO) {
811  adt->flag &= ~ADT_NLA_SOLO_TRACK;
812  }
813 
814  /* call delete on this track - deletes all strips too */
815  BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
816  ale->update = ANIM_UPDATE_DEPS;
817  }
818  }
819 
820  /* free temp data */
821  ANIM_animdata_update(&ac, &anim_data);
822  ANIM_animdata_freelist(&anim_data);
823 
825 
826  /* set notifier that things have changed */
828 
829  /* done */
830  return OPERATOR_FINISHED;
831 }
832 
834 {
835  /* identifiers */
836  ot->name = "Delete Tracks";
837  ot->idname = "NLA_OT_tracks_delete";
838  ot->description = "Delete selected NLA-Tracks and the strips they contain";
839 
840  /* api callbacks */
843 
844  /* flags */
846 }
847 
848 /* *********************************************** */
849 /* AnimData Related Operators */
850 
851 /* ******************** Include Objects Operator ***************************** */
852 /* Include selected objects in NLA Editor, by giving them AnimData blocks
853  * NOTE: This doesn't help for non-object AnimData, where we do not have any effective
854  * selection mechanism in place. Unfortunately, this means that non-object AnimData
855  * once again becomes a second-class citizen here. However, at least for the most
856  * common use case, we now have a nice shortcut again.
857  */
858 
860 {
861  bAnimContext ac;
862  SpaceNla *snla;
863 
864  /* get editor data */
865  if (ANIM_animdata_get_context(C, &ac) == 0) {
866  return OPERATOR_CANCELLED;
867  }
868 
869  /* ensure that filters are set so that the effect will be immediately visible */
870  snla = (SpaceNla *)ac.sl;
871  if (snla && snla->ads) {
873  }
874 
875  /* operate on selected objects... */
876  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
877  /* ensure that object has AnimData... that's all */
878  BKE_animdata_add_id(&ob->id);
879  }
880  CTX_DATA_END;
881 
882  /* set notifier that things have changed */
884 
885  /* done */
886  return OPERATOR_FINISHED;
887 }
888 
890 {
891  /* identifiers */
892  ot->name = "Include Selected Objects";
893  ot->idname = "NLA_OT_selected_objects_add";
894  ot->description = "Make selected objects appear in NLA Editor by adding Animation Data";
895 
896  /* api callbacks */
899 
900  /* flags */
902 }
903 
904 /* *********************************************** */
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
struct AnimData * BKE_animdata_add_id(struct ID *id)
Definition: anim_data.c:113
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
@ G_DEBUG
Definition: BKE_global.h:133
bool BKE_nlatrack_is_nonlocal_in_liboverride(const struct ID *id, const struct NlaTrack *nlt)
void BKE_nla_action_pushdown(struct AnimData *adt, const bool is_liboverride)
Definition: nla.c:1957
void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt)
Definition: nla.c:1054
struct NlaTrack * BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev, bool is_liboverride)
Definition: nla.c:283
void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user)
Definition: nla.c:114
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define UNUSED(x)
#define ELEM(...)
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:614
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:445
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_PA
Definition: DNA_ID_enums.h:82
@ ADS_FILTER_NLA_NOACT
@ ADT_NLA_SOLO_TRACK
@ ADT_UI_ACTIVE
@ ADT_NLA_EDIT_NOMAP
@ ADT_UI_SELECTED
@ NLATRACK_SOLO
@ NLATRACK_MUTED
@ NLATRACK_SELECTED
@ NLATRACK_PROTECTED
@ BASE_SELECTABLE
Object is a sort of wrapper for general info.
#define SCE_DS_SELECTED
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_animedit_unlink_action(struct bContext *C, struct ID *id, struct AnimData *adt, struct bAction *act, struct ReportList *reports, bool force_delete)
Definition: action_data.c:548
@ ACHANNEL_SETFLAG_CLEAR
Definition: ED_anim_api.h:508
#define NLACHANNEL_BUTTON_WIDTH
Definition: ED_anim_api.h:460
@ ANIMTYPE_DSSPK
Definition: ED_anim_api.h:230
@ ANIMTYPE_DSTEX
Definition: ED_anim_api.h:227
@ ANIMTYPE_DSNTREE
Definition: ED_anim_api.h:222
@ ANIMTYPE_DSMBALL
Definition: ED_anim_api.h:224
@ ANIMTYPE_DSCAM
Definition: ED_anim_api.h:217
@ ANIMTYPE_DSPOINTCLOUD
Definition: ED_anim_api.h:234
@ ANIMTYPE_DSPART
Definition: ED_anim_api.h:223
@ ANIMTYPE_DSLINESTYLE
Definition: ED_anim_api.h:229
@ ANIMTYPE_DSCUR
Definition: ED_anim_api.h:219
@ ANIMTYPE_SCENE
Definition: ED_anim_api.h:204
@ ANIMTYPE_DSARM
Definition: ED_anim_api.h:225
@ ANIMTYPE_DSSIMULATION
Definition: ED_anim_api.h:236
@ ANIMTYPE_DSGPENCIL
Definition: ED_anim_api.h:231
@ ANIMTYPE_DSLAT
Definition: ED_anim_api.h:228
@ ANIMTYPE_NLAACTION
Definition: ED_anim_api.h:247
@ ANIMTYPE_DSMAT
Definition: ED_anim_api.h:215
@ ANIMTYPE_DSCACHEFILE
Definition: ED_anim_api.h:218
@ ANIMTYPE_DSVOLUME
Definition: ED_anim_api.h:235
@ ANIMTYPE_DSLAM
Definition: ED_anim_api.h:216
@ ANIMTYPE_PALETTE
Definition: ED_anim_api.h:249
@ ANIMTYPE_FILLACTD
Definition: ED_anim_api.h:212
@ ANIMTYPE_OBJECT
Definition: ED_anim_api.h:205
@ ANIMTYPE_DSMESH
Definition: ED_anim_api.h:226
@ ANIMTYPE_NLATRACK
Definition: ED_anim_api.h:246
@ ANIMTYPE_DSWOR
Definition: ED_anim_api.h:221
@ ANIMTYPE_DSSKEY
Definition: ED_anim_api.h:220
@ ANIMTYPE_DSHAIR
Definition: ED_anim_api.h:233
#define NLACHANNEL_STEP(snla)
Definition: ED_anim_api.h:451
#define NLACHANNEL_NAMEWIDTH
Definition: ED_anim_api.h:457
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:275
#define NLACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:445
@ ANIMFILTER_ANIMDATA
Definition: ED_anim_api.h:325
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:298
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:303
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:311
@ SELECT_INVERT
@ SELECT_REPLACE
void ED_object_base_activate_with_mode_exit_if_needed(struct bContext *C, struct Base *base)
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode)
Definition: object_select.c:98
@ BA_DESELECT
Definition: ED_object.h:146
@ BA_INVERT
Definition: ED_object.h:148
@ BA_SELECT
Definition: ED_object.h:147
bool ED_operator_nla_active(struct bContext *C)
Definition: screen_ops.c:334
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
void UI_view2d_listview_view_to_cell(float columnwidth, float rowheight, float startx, float starty, float viewx, float viewy, int *column, int *row)
Definition: view2d.c:1623
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
#define ND_NLA_ACTCHANGE
Definition: WM_types.h:398
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NC_ANIMATION
Definition: WM_types.h:289
#define NA_ADDED
Definition: WM_types.h:464
#define NA_EDITED
Definition: WM_types.h:462
#define NA_REMOVED
Definition: WM_types.h:465
#define ND_NLA
Definition: WM_types.h:397
#define ND_ANIMCHAN
Definition: WM_types.h:396
#define NA_SELECTED
Definition: WM_types.h:467
void ANIM_anim_channels_select_set(bAnimContext *ac, eAnimChannels_SetFlag sel)
void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datatype, eAnimFilter_Flags filter, void *channel_data, eAnim_ChannelType channel_type)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:425
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:330
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:405
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3442
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
#define GS(x)
Definition: iris.c:241
bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_ptr, PointerRNA *strip_ptr)
Definition: nla_buttons.c:74
static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: nla_channels.c:364
static int nla_action_unlink_exec(bContext *C, wmOperator *op)
Definition: nla_channels.c:573
void NLA_OT_selected_objects_add(wmOperatorType *ot)
Definition: nla_channels.c:889
void NLA_OT_tracks_delete(wmOperatorType *ot)
Definition: nla_channels.c:833
void NLA_OT_tracks_add(wmOperatorType *ot)
Definition: nla_channels.c:753
static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_channels.c:778
static bool nla_action_unlink_poll(bContext *C)
Definition: nla_channels.c:562
static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: nla_channels.c:598
void NLA_OT_action_unlink(wmOperatorType *ot)
Definition: nla_channels.c:606
void NLA_OT_channels_click(wmOperatorType *ot)
Definition: nla_channels.c:413
void NLA_OT_action_pushdown(wmOperatorType *ot)
Definition: nla_channels.c:533
static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
Definition: nla_channels.c:439
bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
Definition: nla_channels.c:633
static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channel_index, short selectmode)
Definition: nla_channels.c:77
bool nlaedit_add_tracks_empty(bAnimContext *ac)
Definition: nla_channels.c:682
static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
Definition: nla_channels.c:719
static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op))
Definition: nla_channels.c:859
bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
Definition: nla_edit.c:210
bool nlaedit_is_tweakmode_on(bAnimContext *ac)
Definition: nla_ops.c:91
bool nlaop_poll_tweakmode_off(bContext *C)
Definition: nla_ops.c:43
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
bAction * action
ListBase nla_tracks
short flag
struct Object * object
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
short flag
struct AnimData * adt
struct bDopeSheet * ads
ListBase object_bases
struct ARegion * region
Definition: ED_anim_api.h:89
short datatype
Definition: ED_anim_api.h:75
void * data
Definition: ED_anim_api.h:73
struct ViewLayer * view_layer
Definition: ED_anim_api.h:99
struct Main * bmain
Definition: ED_anim_api.h:95
struct SpaceLink * sl
Definition: ED_anim_api.h:87
struct bAnimListElem * next
Definition: ED_anim_api.h:135
struct AnimData * adt
Definition: ED_anim_api.h:170
struct ID * id
Definition: ED_anim_api.h:168
float xmax
Definition: DNA_vec_types.h:85
short shift
Definition: WM_types.h:618
int mval[2]
Definition: WM_types.h:583
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
#define G(x, y, z)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156