Blender  V3.3
action_data.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2015 Blender Foundation. */
3 
8 #include <float.h>
9 #include <math.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "BLI_utildefines.h"
14 
15 #include "BLT_translation.h"
16 
17 #include "DNA_anim_types.h"
18 #include "DNA_gpencil_types.h"
19 #include "DNA_key_types.h"
20 #include "DNA_mask_types.h"
21 #include "DNA_object_types.h"
22 #include "DNA_scene_types.h"
23 
24 #include "RNA_access.h"
25 #include "RNA_define.h"
26 #include "RNA_enum_types.h"
27 #include "RNA_prototypes.h"
28 
29 #include "BKE_action.h"
30 #include "BKE_context.h"
31 #include "BKE_fcurve.h"
32 #include "BKE_key.h"
33 #include "BKE_lib_id.h"
34 #include "BKE_nla.h"
35 #include "BKE_report.h"
36 #include "BKE_scene.h"
37 
38 #include "UI_view2d.h"
39 
40 #include "ED_anim_api.h"
41 #include "ED_gpencil.h"
42 #include "ED_keyframes_edit.h"
43 #include "ED_keyframing.h"
44 #include "ED_markers.h"
45 #include "ED_mask.h"
46 #include "ED_screen.h"
47 
48 #include "DEG_depsgraph.h"
49 
50 #include "WM_api.h"
51 #include "WM_types.h"
52 
53 #include "UI_interface.h"
54 
55 #include "action_intern.h"
56 
57 /* ************************************************************************** */
58 /* ACTION CREATION */
59 
61 {
64  AnimData *adt = NULL;
65 
66  /* Get AnimData block to use */
67  if (saction->mode == SACTCONT_ACTION) {
68  /* Currently, "Action Editor" means object-level only... */
69  if (ob) {
70  adt = ob->adt;
71  if (r_adt_id_owner) {
72  *r_adt_id_owner = &ob->id;
73  }
74  }
75  }
76  else if (saction->mode == SACTCONT_SHAPEKEY) {
77  Key *key = BKE_key_from_object(ob);
78  if (key) {
79  adt = key->adt;
80  if (r_adt_id_owner) {
81  *r_adt_id_owner = &key->id;
82  }
83  }
84  }
85 
86  return adt;
87 }
88 
89 /* -------------------------------------------------------------------- */
90 
91 /* Create new action */
93 {
95  bAction *action;
96 
97  /* create action - the way to do this depends on whether we've got an
98  * existing one there already, in which case we make a copy of it
99  * (which is useful for "versioning" actions within the same file)
100  */
101  if (oldact && GS(oldact->id.name) == ID_AC) {
102  /* make a copy of the existing action */
103  action = (bAction *)BKE_id_copy(CTX_data_main(C), &oldact->id);
104  }
105  else {
106  /* just make a new (empty) action */
107  action = BKE_action_add(CTX_data_main(C), "Action");
108  }
109 
110  /* when creating new ID blocks, there is already 1 user (as for all new datablocks),
111  * but the RNA pointer code will assign all the proper users instead, so we compensate
112  * for that here
113  */
114  BLI_assert(action->id.us == 1);
115  id_us_min(&action->id);
116 
117  /* set ID-Root type */
118  if (area->spacetype == SPACE_ACTION) {
119  SpaceAction *saction = (SpaceAction *)area->spacedata.first;
120 
121  if (saction->mode == SACTCONT_SHAPEKEY) {
122  action->idroot = ID_KE;
123  }
124  else {
125  action->idroot = ID_OB;
126  }
127  }
128 
129  return action;
130 }
131 
132 /* Change the active action used by the action editor */
134 {
135  bScreen *screen = CTX_wm_screen(C);
137 
138  PointerRNA ptr, idptr;
139  PropertyRNA *prop;
140 
141  /* create RNA pointers and get the property */
142  RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
143  prop = RNA_struct_find_property(&ptr, "action");
144 
145  /* NOTE: act may be NULL here, so better to just use a cast here */
146  RNA_id_pointer_create((ID *)act, &idptr);
147 
148  /* set the new pointer, and force a refresh */
149  RNA_property_pointer_set(&ptr, prop, idptr, NULL);
150  RNA_property_update(C, &ptr, prop);
151 }
152 
153 /* ******************** New Action Operator *********************** */
154 
155 /* Criteria:
156  * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
157  * OR
158  * The NLA Editor is active (i.e. Animation Data panel -> new action)
159  * 2) The associated AnimData block must not be in tweak-mode.
160  */
162 {
164 
165  /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
166  /* NOTE: unlike for pushdown,
167  * this operator needs to be run when creating an action from nothing... */
171 
172  /* For now, actions are only for the active object, and on object and shapekey levels... */
173  if (saction->mode == SACTCONT_ACTION) {
174  /* XXX: This assumes that actions are assigned to the active object in this mode */
175  if (ob) {
176  if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0) {
177  return true;
178  }
179  }
180  }
181  else if (saction->mode == SACTCONT_SHAPEKEY) {
182  Key *key = BKE_key_from_object(ob);
183  if (key) {
184  if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0) {
185  return true;
186  }
187  }
188  }
189  }
190  else if (ED_operator_nla_active(C)) {
191  if (!(scene->flag & SCE_NLA_EDIT_ON)) {
192  return true;
193  }
194  }
195 
196  /* something failed... */
197  return false;
198 }
199 
201 {
202  PointerRNA ptr, idptr;
203  PropertyRNA *prop;
204 
205  bAction *oldact = NULL;
206  AnimData *adt = NULL;
207  ID *adt_id_owner = NULL;
208  /* hook into UI */
210 
211  if (prop) {
212  /* The operator was called from a button. */
213  PointerRNA oldptr;
214 
215  oldptr = RNA_property_pointer_get(&ptr, prop);
216  oldact = (bAction *)oldptr.owner_id;
217 
218  /* stash the old action to prevent it from being lost */
219  if (ptr.type == &RNA_AnimData) {
220  adt = ptr.data;
221  adt_id_owner = ptr.owner_id;
222  }
223  else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
224  adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
225  }
226  }
227  else {
228  adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
229  oldact = adt->action;
230  }
231  {
232  bAction *action = NULL;
233 
234  /* Perform stashing operation - But only if there is an action */
235  if (adt && oldact) {
236  BLI_assert(adt_id_owner != NULL);
237  /* stash the action */
238  if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
239  /* The stash operation will remove the user already
240  * (and unlink the action from the AnimData action slot).
241  * Hence, we must unset the ref to the action in the
242  * action editor too (if this is where we're being called from)
243  * first before setting the new action once it is created,
244  * or else the user gets decremented twice!
245  */
246  if (ptr.type == &RNA_SpaceDopeSheetEditor) {
247  SpaceAction *saction = ptr.data;
248  saction->action = NULL;
249  }
250  }
251  else {
252 #if 0
253  printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n",
254  oldact->id.name);
255 #endif
256  }
257  }
258 
259  /* create action */
260  action = action_create_new(C, oldact);
261 
262  if (prop) {
263  /* set this new action
264  * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
265  */
266  RNA_id_pointer_create(&action->id, &idptr);
267  RNA_property_pointer_set(&ptr, prop, idptr, NULL);
268  RNA_property_update(C, &ptr, prop);
269  }
270  }
271 
272  /* set notifier that keyframes have changed */
274 
275  return OPERATOR_FINISHED;
276 }
277 
279 {
280  /* identifiers */
281  ot->name = "New Action";
282  ot->idname = "ACTION_OT_new";
283  ot->description = "Create new action";
284 
285  /* api callbacks */
288 
289  /* flags */
291 }
292 
293 /* ******************* Action Push-Down Operator ******************** */
294 
295 /* Criteria:
296  * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
297  * 2) There must be an action active
298  * 3) The associated AnimData block must not be in tweak-mode
299  */
301 {
305 
306  /* Check for AnimData, Actions, and that tweak-mode is off. */
307  if (adt && saction->action) {
308  /* NOTE: We check this for the AnimData block in question and not the global flag,
309  * as the global flag may be left dirty by some of the browsing ops here.
310  */
311  if (!(adt->flag & ADT_NLA_EDIT_ON)) {
312  return true;
313  }
314  }
315  }
316 
317  /* something failed... */
318  return false;
319 }
320 
322 {
324  ID *adt_id_owner = NULL;
325  AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
326 
327  /* Do the deed... */
328  if (adt) {
329  /* Perform the push-down operation
330  * - This will deal with all the AnimData-side user-counts. */
331  if (action_has_motion(adt->action) == 0) {
332  /* action may not be suitable... */
333  BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
334  return OPERATOR_CANCELLED;
335  }
336 
337  /* action can be safely added */
339 
340  struct Main *bmain = CTX_data_main(C);
341  DEG_id_tag_update_ex(bmain, adt_id_owner, ID_RECALC_ANIMATION);
342 
343  /* The action needs updating too, as FCurve modifiers are to be reevaluated. They won't extend
344  * beyond the NLA strip after pushing down to the NLA. */
346 
347  /* Stop displaying this action in this editor
348  * NOTE: The editor itself doesn't set a user...
349  */
350  saction->action = NULL;
351  }
352 
353  /* Send notifiers that stuff has changed */
355  return OPERATOR_FINISHED;
356 }
357 
359 {
360  /* identifiers */
361  ot->name = "Push Down Action";
362  ot->idname = "ACTION_OT_push_down";
363  ot->description = "Push action down on to the NLA stack as a new strip";
364 
365  /* callbacks */
368 
369  /* flags */
371 }
372 
373 /* ******************* Action Stash Operator ******************** */
374 
376 {
378  ID *adt_id_owner = NULL;
379  AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
380 
381  /* Perform stashing operation */
382  if (adt) {
383  /* don't do anything if this action is empty... */
384  if (action_has_motion(adt->action) == 0) {
385  /* action may not be suitable... */
386  BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
387  return OPERATOR_CANCELLED;
388  }
389 
390  /* stash the action */
391  if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
392  /* The stash operation will remove the user already,
393  * so the flushing step later shouldn't double up
394  * the user-count fixes. Hence, we must unset this ref
395  * first before setting the new action.
396  */
397  saction->action = NULL;
398  }
399  else {
400  /* action has already been added - simply warn about this, and clear */
401  BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
402  }
403 
404  /* clear action refs from editor, and then also the backing data (not necessary) */
406  }
407 
408  /* Send notifiers that stuff has changed */
410  return OPERATOR_FINISHED;
411 }
412 
414 {
415  /* identifiers */
416  ot->name = "Stash Action";
417  ot->idname = "ACTION_OT_stash";
418  ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
419 
420  /* callbacks */
423 
424  /* flags */
426 
427  /* properties */
429  "create_new",
430  true,
431  "Create New Action",
432  "Create a new action once the existing one has been safely stored");
433 }
434 
435 /* ----------------- */
436 
437 /* Criteria:
438  * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
439  * 2) The associated AnimData block must not be in tweak-mode
440  */
442 {
445 
446  /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
447  /* NOTE: unlike for pushdown,
448  * this operator needs to be run when creating an action from nothing... */
449  if (adt) {
450  if (!(adt->flag & ADT_NLA_EDIT_ON)) {
451  return true;
452  }
453  }
454  else {
455  /* There may not be any action/animdata yet, so, just fallback to the global setting
456  * (which may not be totally valid yet if the action editor was used and things are
457  * now in an inconsistent state)
458  */
461 
462  if (!(scene->flag & SCE_NLA_EDIT_ON)) {
463  /* For now, actions are only for the active object, and on object and shapekey levels... */
464  return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
465  }
466  }
467  }
468 
469  /* something failed... */
470  return false;
471 }
472 
474 {
476  ID *adt_id_owner = NULL;
477  AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
478 
479  /* Check for no action... */
480  if (saction->action == NULL) {
481  /* just create a new action */
482  bAction *action = action_create_new(C, NULL);
483  actedit_change_action(C, action);
484  }
485  else if (adt) {
486  /* Perform stashing operation */
487  if (action_has_motion(adt->action) == 0) {
488  /* don't do anything if this action is empty... */
489  BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
490  return OPERATOR_CANCELLED;
491  }
492 
493  /* stash the action */
494  if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
495  bAction *new_action = NULL;
496 
497  /* Create new action not based on the old one
498  * (since the "new" operator already does that). */
499  new_action = action_create_new(C, NULL);
500 
501  /* The stash operation will remove the user already,
502  * so the flushing step later shouldn't double up
503  * the user-count fixes. Hence, we must unset this ref
504  * first before setting the new action.
505  */
506  saction->action = NULL;
507  actedit_change_action(C, new_action);
508  }
509  else {
510  /* action has already been added - simply warn about this, and clear */
511  BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
513  }
514  }
515 
516  /* Send notifiers that stuff has changed */
518  return OPERATOR_FINISHED;
519 }
520 
522 {
523  /* identifiers */
524  ot->name = "Stash Action";
525  ot->idname = "ACTION_OT_stash_and_create";
526  ot->description =
527  "Store this action in the NLA stack as a non-contributing strip for later use, and create a "
528  "new action";
529 
530  /* callbacks */
533 
534  /* flags */
536 }
537 
538 /* ************************************************************************** */
539 /* ACTION UNLINK */
540 
541 /* ******************* Action Unlink Operator ******************** */
542 /* We use a custom unlink operator here, as there are some technicalities which need special care:
543  * 1) When in Tweak Mode, it shouldn't be possible to unlink the active action,
544  * or else, everything turns to custard.
545  * 2) If the Action doesn't have any other users, the user should at least get
546  * a warning that it is going to get lost.
547  * 3) We need a convenient way to exit Tweak Mode from the Action Editor
548  */
549 
551  bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
552 {
554 
555  /* If the old action only has a single user (that it's about to lose),
556  * warn user about it
557  *
558  * TODO: Maybe we should just save it for them? But then, there's the problem of
559  * trying to get rid of stuff that's actually unwanted!
560  */
561  if (act->id.us == 1) {
562  BKE_reportf(reports,
563  RPT_WARNING,
564  "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
565  act->id.name + 2);
566  }
567 
568  /* Clear Fake User and remove action stashing strip (if present) */
569  if (force_delete) {
570  /* Remove stashed strip binding this action to this datablock */
571  /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
572  * but GE users only seem to use/care about single-object binding for now so this
573  * should be fine
574  */
575  if (adt) {
576  NlaTrack *nlt, *nlt_next;
577  NlaStrip *strip, *nstrip;
578 
579  for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
580  nlt_next = nlt->next;
581 
582  if (strstr(nlt->name, DATA_("[Action Stash]"))) {
583  for (strip = nlt->strips.first; strip; strip = nstrip) {
584  nstrip = strip->next;
585 
586  if (strip->act == act) {
587  /* Remove this strip, and the track too if it doesn't have anything else */
588  BKE_nlastrip_free(&nlt->strips, strip, true);
589 
590  if (nlt->strips.first == NULL) {
591  BLI_assert(nstrip == NULL);
592  BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
593  }
594  }
595  }
596  }
597  }
598  }
599 
600  /* Clear Fake User */
601  id_fake_user_clear(&act->id);
602  }
603 
604  /* If in Tweak Mode, don't unlink. Instead, this becomes a shortcut to exit Tweak Mode. */
605  if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
607 
609  if (scene != NULL) {
611  }
612  }
613  else {
614  /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
615  if (area->spacetype == SPACE_ACTION) {
616  /* clear action editor -> action */
618  }
619  else {
620  /* clear AnimData -> action */
621  PointerRNA ptr;
622  PropertyRNA *prop;
623 
624  /* create AnimData RNA pointers */
625  RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
626  prop = RNA_struct_find_property(&ptr, "action");
627 
628  /* clear... */
630  RNA_property_update(C, &ptr, prop);
631  }
632  }
633 }
634 
635 /* -------------------------- */
636 
638 {
642 
643  /* Only when there's an active action, in the right modes... */
644  if (saction->action && adt) {
645  return true;
646  }
647  }
648 
649  /* something failed... */
650  return false;
651 }
652 
654 {
656  bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
657 
658  if (adt && adt->action) {
659  ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
660  }
661 
662  /* Unlink is also abused to exit NLA tweak mode. */
664 
665  return OPERATOR_FINISHED;
666 }
667 
668 static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
669 {
670  /* NOTE: this is hardcoded to match the behavior for the unlink button
671  * (in interface_templates.c). */
672  RNA_boolean_set(op->ptr, "force_delete", event->modifier & KM_SHIFT);
673  return action_unlink_exec(C, op);
674 }
675 
677 {
678  PropertyRNA *prop;
679 
680  /* identifiers */
681  ot->name = "Unlink Action";
682  ot->idname = "ACTION_OT_unlink";
683  ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
684 
685  /* callbacks */
689 
690  /* properties */
691  prop = RNA_def_boolean(ot->srna,
692  "force_delete",
693  false,
694  "Force Delete",
695  "Clear Fake User and remove "
696  "copy stashed in this data-block's NLA stack");
698 
699  /* flags */
701 }
702 
703 /* ************************************************************************** */
704 /* ACTION BROWSING */
705 
706 /* Try to find NLA Strip to use for action layer up/down tool */
707 static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
708 {
709  NlaStrip *strip;
710 
711  for (strip = strips->first; strip; strip = strip->next) {
712  /* Can we use this? */
713  if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
714  /* in range - use this one */
715  return strip;
716  }
717  if ((ctime < strip->start) && (strip->prev == NULL)) {
718  /* before first - use this one */
719  return strip;
720  }
721  if ((ctime > strip->end) && (strip->next == NULL)) {
722  /* after last - use this one */
723  return strip;
724  }
725  }
726 
727  /* nothing suitable found... */
728  return NULL;
729 }
730 
731 /* Switch NLA Strips/Actions. */
733  AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip)
734 {
735  /* Exit tweak-mode on old strip
736  * NOTE: We need to manually clear this stuff ourselves, as tweak-mode exit doesn't do it
737  */
739 
740  if (old_strip) {
742  }
743  if (old_track) {
744  old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
745  }
746 
747  /* Make this one the active one instead */
749  nlt->flag |= NLATRACK_ACTIVE;
750 
751  /* Copy over "solo" flag - This is useful for stashed actions... */
752  if (old_track) {
753  if (old_track->flag & NLATRACK_SOLO) {
754  old_track->flag &= ~NLATRACK_SOLO;
755  nlt->flag |= NLATRACK_SOLO;
756  }
757  }
758  else {
759  /* NLA muting <==> Solo Tracks */
760  if (adt->flag & ADT_NLA_EVAL_OFF) {
761  /* disable NLA muting */
762  adt->flag &= ~ADT_NLA_EVAL_OFF;
763 
764  /* mark this track as being solo */
765  adt->flag |= ADT_NLA_SOLO_TRACK;
766  nlt->flag |= NLATRACK_SOLO;
767 
768  /* TODO: Needs rest-pose flushing (when we get reference track) */
769  }
770  }
771 
772  /* Enter tweak-mode again - hopefully we're now "it" */
774  BLI_assert(adt->actstrip == strip);
775 }
776 
777 /* ********************** One Layer Up Operator ************************** */
778 
780 {
781  /* Action Editor's action editing modes only */
784  if (adt) {
785  /* only allow if we're in tweak-mode, and there's something above us... */
786  if (adt->flag & ADT_NLA_EDIT_ON) {
787  /* We need to check if there are any tracks above the active one
788  * since the track the action comes from is not stored in AnimData
789  */
790  if (adt->nla_tracks.last) {
791  NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
792 
793  if (nlt->flag & NLATRACK_DISABLED) {
794  /* A disabled track will either be the track itself,
795  * or one of the ones above it.
796  *
797  * If this is the top-most one, there is the possibility
798  * that there is no active action. For now, we let this
799  * case return true too, so that there is a natural way
800  * to "move to an empty layer", even though this means
801  * that we won't actually have an action.
802  */
803  // return (adt->tmpact != NULL);
804  return true;
805  }
806  }
807  }
808  }
809  }
810 
811  /* something failed... */
812  return false;
813 }
814 
816 {
818  NlaTrack *act_track;
819 
821  float ctime = BKE_scene_ctime_get(scene);
822 
823  /* Get active track */
824  act_track = BKE_nlatrack_find_tweaked(adt);
825 
826  if (act_track == NULL) {
827  BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
828  return OPERATOR_CANCELLED;
829  }
830 
831  /* Find next action, and hook it up */
832  if (act_track->next) {
833  NlaTrack *nlt;
834 
835  /* Find next action to use */
836  for (nlt = act_track->next; nlt; nlt = nlt->next) {
837  NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
838 
839  if (strip) {
840  action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
841  break;
842  }
843  }
844  }
845  else {
846  /* No more actions (strips) - Go back to editing the original active action
847  * NOTE: This will mean exiting tweak-mode...
848  */
850 
851  /* Deal with solo flags...
852  * Assume: Solo Track == NLA Muting
853  */
854  if (adt->flag & ADT_NLA_SOLO_TRACK) {
855  /* turn off solo flags on tracks */
856  act_track->flag &= ~NLATRACK_SOLO;
857  adt->flag &= ~ADT_NLA_SOLO_TRACK;
858 
859  /* turn on NLA muting (to keep same effect) */
860  adt->flag |= ADT_NLA_EVAL_OFF;
861 
862  /* TODO: Needs rest-pose flushing (when we get reference track) */
863  }
864  }
865 
866  /* Update the action that this editor now uses
867  * NOTE: The calls above have already handled the user-count/anim-data side of things. */
869  return OPERATOR_FINISHED;
870 }
871 
873 {
874  /* identifiers */
875  ot->name = "Next Layer";
876  ot->idname = "ACTION_OT_layer_next";
877  ot->description =
878  "Switch to editing action in animation layer above the current action in the NLA Stack";
879 
880  /* callbacks */
883 
884  /* flags */
886 }
887 
888 /* ********************* One Layer Down Operator ************************* */
889 
891 {
892  /* Action Editor's action editing modes only */
895  if (adt) {
896  if (adt->flag & ADT_NLA_EDIT_ON) {
897  /* Tweak Mode: We need to check if there are any tracks below the active one
898  * that we can move to */
899  if (adt->nla_tracks.first) {
900  NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
901 
902  /* Since the first disabled track is the track being tweaked/edited,
903  * we can simplify things by only checking the first track:
904  * - If it is disabled, this is the track being tweaked,
905  * so there can't be anything below it
906  * - Otherwise, there is at least 1 track below the tweaking
907  * track that we can descend to
908  */
909  if ((nlt->flag & NLATRACK_DISABLED) == 0) {
910  /* not disabled = there are actions below the one being tweaked */
911  return true;
912  }
913  }
914  }
915  else {
916  /* Normal Mode: If there are any tracks, we can try moving to those */
917  return (adt->nla_tracks.first != NULL);
918  }
919  }
920  }
921 
922  /* something failed... */
923  return false;
924 }
925 
927 {
929  NlaTrack *act_track;
930  NlaTrack *nlt;
931 
933  float ctime = BKE_scene_ctime_get(scene);
934 
935  /* Sanity Check */
936  if (adt == NULL) {
937  BKE_report(
938  op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
939  return OPERATOR_CANCELLED;
940  }
941 
942  /* Get active track */
943  act_track = BKE_nlatrack_find_tweaked(adt);
944 
945  /* If there is no active track, that means we are using the active action... */
946  if (act_track) {
947  /* Active Track - Start from the one below it */
948  nlt = act_track->prev;
949  }
950  else {
951  /* Active Action - Use the top-most track */
952  nlt = adt->nla_tracks.last;
953  }
954 
955  /* Find previous action and hook it up */
956  for (; nlt; nlt = nlt->prev) {
957  NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
958 
959  if (strip) {
960  action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
961  break;
962  }
963  }
964 
965  /* Update the action that this editor now uses
966  * NOTE: The calls above have already handled the user-count/animdata side of things. */
968  return OPERATOR_FINISHED;
969 }
970 
972 {
973  /* identifiers */
974  ot->name = "Previous Layer";
975  ot->idname = "ACTION_OT_layer_prev";
976  ot->description =
977  "Switch to editing action in animation layer below the current action in the NLA Stack";
978 
979  /* callbacks */
982 
983  /* flags */
985 }
986 
987 /* ************************************************************************** */
Blender kernel action and pose functionality.
bool action_has_motion(const struct bAction *act)
struct bAction * BKE_action_add(struct Main *bmain, const char name[])
Definition: action.c:332
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct SpaceLink * CTX_wm_space_data(const bContext *C)
Definition: context.c:743
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
struct ID * BKE_id_copy(struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void id_fake_user_clear(struct ID *id)
Definition: lib_id.c:351
void BKE_nla_action_pushdown(struct AnimData *adt, bool is_liboverride)
Definition: nla.c:1909
bool BKE_nla_action_stash(struct AnimData *adt, bool is_liboverride)
Definition: nla.c:1841
bool BKE_nla_tweakmode_enter(struct AnimData *adt)
Definition: nla.c:2019
void BKE_nla_tweakmode_exit(struct AnimData *adt)
Definition: nla.c:2092
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user)
Definition: nla.c:64
struct NlaTrack * BKE_nlatrack_find_tweaked(struct AnimData *adt)
Definition: nla.c:1052
void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user)
Definition: nla.c:103
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
float BKE_scene_ctime_get(const struct Scene *scene)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define UNUSED(x)
#define ELEM(...)
#define IN_RANGE_INCL(a, b, c)
#define DATA_(msgid)
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:794
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_KE
Definition: DNA_ID_enums.h:58
@ ID_AC
Definition: DNA_ID_enums.h:67
@ ID_OB
Definition: DNA_ID_enums.h:47
@ SACTCONT_ACTION
@ SACTCONT_SHAPEKEY
@ NLASTRIP_FLAG_ACTIVE
@ NLASTRIP_FLAG_SELECT
@ ADT_NLA_SOLO_TRACK
@ ADT_NLA_EVAL_OFF
@ ADT_NLA_EDIT_ON
@ NLATRACK_SOLO
@ NLATRACK_ACTIVE
@ NLATRACK_DISABLED
@ NLATRACK_SELECTED
Object is a sort of wrapper for general info.
#define SCE_NLA_EDIT_ON
@ SPACE_ACTION
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_operator_nla_active(struct bContext *C)
Definition: screen_ops.c:349
bool ED_operator_action_active(struct bContext *C)
Definition: screen_ops.c:297
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop)
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_NLA_ACTCHANGE
Definition: WM_types.h:446
#define NC_ANIMATION
Definition: WM_types.h:338
#define NA_ADDED
Definition: WM_types.h:525
@ KM_SHIFT
Definition: WM_types.h:238
#define ND_KEYFRAME
Definition: WM_types.h:442
static bool action_unlink_poll(bContext *C)
Definition: action_data.c:637
void ACTION_OT_layer_prev(wmOperatorType *ot)
Definition: action_data.c:971
void ACTION_OT_push_down(wmOperatorType *ot)
Definition: action_data.c:358
static bool action_new_poll(bContext *C)
Definition: action_data.c:161
static void actedit_change_action(bContext *C, bAction *act)
Definition: action_data.c:133
static bAction * action_create_new(bContext *C, bAction *oldact)
Definition: action_data.c:92
static int action_stash_exec(bContext *C, wmOperator *op)
Definition: action_data.c:375
void ACTION_OT_unlink(wmOperatorType *ot)
Definition: action_data.c:676
static bool action_layer_prev_poll(bContext *C)
Definition: action_data.c:890
AnimData * ED_actedit_animdata_from_context(const bContext *C, ID **r_adt_id_owner)
Definition: action_data.c:60
static bool action_stash_create_poll(bContext *C)
Definition: action_data.c:441
static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
Definition: action_data.c:200
void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
Definition: action_data.c:550
static bool action_pushdown_poll(bContext *C)
Definition: action_data.c:300
void ACTION_OT_stash_and_create(wmOperatorType *ot)
Definition: action_data.c:521
static int action_layer_next_exec(bContext *C, wmOperator *op)
Definition: action_data.c:815
void ACTION_OT_stash(wmOperatorType *ot)
Definition: action_data.c:413
static void action_layer_switch_strip(AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip)
Definition: action_data.c:732
static int action_unlink_exec(bContext *C, wmOperator *op)
Definition: action_data.c:653
static int action_stash_create_exec(bContext *C, wmOperator *op)
Definition: action_data.c:473
void ACTION_OT_new(wmOperatorType *ot)
Definition: action_data.c:278
void ACTION_OT_layer_next(wmOperatorType *ot)
Definition: action_data.c:872
static int action_pushdown_exec(bContext *C, wmOperator *op)
Definition: action_data.c:321
static int action_layer_prev_exec(bContext *C, wmOperator *op)
Definition: action_data.c:926
static bool action_layer_next_poll(bContext *C)
Definition: action_data.c:779
static NlaStrip * action_layer_get_nlastrip(ListBase *strips, float ctime)
Definition: action_data.c:707
static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: action_data.c:668
Scene scene
#define GS(x)
Definition: iris.c:225
static void area(int d1, int d2, int e1, int e2, float weights[2])
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
Definition: rna_access.c:3532
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:61
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3493
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2138
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
bAction * action
NlaStrip * actstrip
ListBase nla_tracks
Definition: DNA_ID.h:368
int us
Definition: DNA_ID.h:388
char name[66]
Definition: DNA_ID.h:378
ID id
Definition: DNA_key_types.h:63
struct AnimData * adt
Definition: DNA_key_types.h:65
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct NlaStrip * next
struct NlaStrip * prev
bAction * act
ListBase strips
struct NlaTrack * next
char name[64]
struct NlaTrack * prev
struct AnimData * adt
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
short flag
bAction * action
uint8_t modifier
Definition: WM_types.h:693
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479