/* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions * 2) The associated AnimData block must not be in tweakmode */ static int action_stash_create_poll(bContext *C) { if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */ if (adt) { if (!(adt->flag & ADT_NLA_EDIT_ON)) return true; } else { /* There may not be any action/animdata yet, so, just fallback to the global setting * (which may not be totally valid yet if the action editor was used and things are * now in an inconsistent state) */ SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); Scene *scene = CTX_data_scene(C); if (!(scene->flag & SCE_NLA_EDIT_ON)) { /* For now, actions are only for the active object, and on object and shapekey levels... */ return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY); } } } /* something failed... */ return false; }
static int action_layer_prev_poll(bContext *C) { /* Action Editor's action editing modes only */ if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { if (adt->flag & ADT_NLA_EDIT_ON) { /* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */ if (adt->nla_tracks.first) { NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first; /* Since the first disabled track is the track being tweaked/edited, * we can simplify things by only checking the first track: * - If it is disabled, this is the track being tweaked, * so there can't be anything below it * - Otherwise, there is at least 1 track below the tweaking * track that we can descend to */ if ((nlt->flag & NLATRACK_DISABLED) == 0) { /* not disabled = there are actions below the one being tweaked */ return true; } } } else { /* Normal Mode: If there are any tracks, we can try moving to those */ return (adt->nla_tracks.first != NULL); } } } /* something failed... */ return false; }
static int action_layer_next_poll(bContext *C) { /* Action Editor's action editing modes only */ if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { /* only allow if we're in tweakmode, and there's something above us... */ if (adt->flag & ADT_NLA_EDIT_ON) { /* We need to check if there are any tracks above the active one * since the track the action comes from is not stored in AnimData */ if (adt->nla_tracks.last) { NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last; if (nlt->flag & NLATRACK_DISABLED) { /* A disabled track will either be the track itself, * or one of the ones above it. * * If this is the top-most one, there is the possibility * that there is no active action. For now, we let this * case return true too, so that there is a natural way * to "move to an empty layer", even though this means * that we won't actually have an action. */ // return (adt->tmpact != NULL); return true; } } } } } /* something failed... */ return false; }
static int action_pushdown_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); AnimData *adt = ED_actedit_animdata_from_context(C); /* Do the deed... */ if (adt) { /* Perform the pushdown operation * - This will deal with all the AnimData-side usercounts */ if (action_has_motion(adt->action) == 0) { /* action may not be suitable... */ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); return OPERATOR_CANCELLED; } else { /* action can be safely added */ BKE_nla_action_pushdown(adt); } /* Stop displaying this action in this editor * NOTE: The editor itself doesn't set a user... */ saction->action = NULL; } /* Send notifiers that stuff has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); return OPERATOR_FINISHED; }
static int action_layer_next_exec(bContext *C, wmOperator *op) { AnimData *adt = ED_actedit_animdata_from_context(C); NlaTrack *act_track; Scene *scene = CTX_data_scene(C); float ctime = BKE_scene_frame_get(scene); /* Get active track */ act_track = BKE_nlatrack_find_tweaked(adt); if (act_track == NULL) { BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track"); return OPERATOR_CANCELLED; } /* Find next action, and hook it up */ if (act_track->next) { NlaTrack *nlt; /* Find next action to use */ for (nlt = act_track->next; nlt; nlt = nlt->next) { NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime); if (strip) { action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip); break; } } } else { /* No more actions (strips) - Go back to editing the original active action * NOTE: This will mean exiting tweakmode... */ BKE_nla_tweakmode_exit(adt); /* Deal with solo flags... * Assume: Solo Track == NLA Muting */ if (adt->flag & ADT_NLA_SOLO_TRACK) { /* turn off solo flags on tracks */ act_track->flag &= ~NLATRACK_SOLO; adt->flag &= ~ADT_NLA_SOLO_TRACK; /* turn on NLA muting (to keep same effect) */ adt->flag |= ADT_NLA_EVAL_OFF; // TODO: Needs restpose flushing (when we get reference track) } } /* Update the action that this editor now uses * NOTE: The calls above have already handled the usercount/animdata side of things */ actedit_change_action(C, adt->action); return OPERATOR_FINISHED; }
static int action_unlink_exec(bContext *C, wmOperator *op) { AnimData *adt = ED_actedit_animdata_from_context(C); if (adt && adt->action) { ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports); } return OPERATOR_FINISHED; }
static int action_unlink_exec(bContext *C, wmOperator *op) { AnimData *adt = ED_actedit_animdata_from_context(C); bool force_delete = RNA_boolean_get(op->ptr, "force_delete"); if (adt && adt->action) { ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete); } return OPERATOR_FINISHED; }
static int action_unlink_poll(bContext *C) { if (ED_operator_action_active(C)) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); AnimData *adt = ED_actedit_animdata_from_context(C); /* Only when there's an active action, in the right modes... */ if (saction->action && adt) return true; } /* something failed... */ return false; }
static int action_stash_create_exec(bContext *C, wmOperator *op) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); AnimData *adt = ED_actedit_animdata_from_context(C); /* Check for no action... */ if (saction->action == NULL) { /* just create a new action */ bAction *action = action_create_new(C, NULL); actedit_change_action(C, action); } else if (adt) { /* Perform stashing operation */ if (action_has_motion(adt->action) == 0) { /* don't do anything if this action is empty... */ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); return OPERATOR_CANCELLED; } else { /* stash the action */ if (BKE_nla_action_stash(adt)) { bAction *new_action = NULL; /* create new action not based on the old one (since the "new" operator already does that) */ new_action = action_create_new(C, NULL); /* The stash operation will remove the user already, * so the flushing step later shouldn't double up * the usercount fixes. Hence, we must unset this ref * first before setting the new action. */ saction->action = NULL; actedit_change_action(C, new_action); } else { /* action has already been added - simply warn about this, and clear */ BKE_report(op->reports, RPT_ERROR, "Action has already been stashed"); actedit_change_action(C, NULL); } } } /* Send notifiers that stuff has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); return OPERATOR_FINISHED; }
static int action_layer_prev_exec(bContext *C, wmOperator *op) { AnimData *adt = ED_actedit_animdata_from_context(C); NlaTrack *act_track; NlaTrack *nlt; Scene *scene = CTX_data_scene(C); float ctime = BKE_scene_frame_get(scene); /* Sanity Check */ if (adt == NULL) { BKE_report(op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use"); return OPERATOR_CANCELLED; } /* Get active track */ act_track = BKE_nlatrack_find_tweaked(adt); /* If there is no active track, that means we are using the active action... */ if (act_track) { /* Active Track - Start from the one below it */ nlt = act_track->prev; } else { /* Active Action - Use the top-most track */ nlt = adt->nla_tracks.last; } /* Find previous action and hook it up */ for (; nlt; nlt = nlt->prev) { NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime); if (strip) { action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip); break; } } /* Update the action that this editor now uses * NOTE: The calls above have already handled the usercount/animdata side of things */ actedit_change_action(C, adt->action); return OPERATOR_FINISHED; }
/* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions * 2) There must be an action active * 3) The associated AnimData block must not be in tweakmode */ static int action_pushdown_poll(bContext *C) { if (ED_operator_action_active(C)) { SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); AnimData *adt = ED_actedit_animdata_from_context(C); /* Check for AnimData, Actions, and that tweakmode is off */ if (adt && saction->action) { /* NOTE: We check this for the AnimData block in question and not the global flag, * as the global flag may be left dirty by some of the browsing ops here. */ if (!(adt->flag & ADT_NLA_EDIT_ON)) return true; } } /* something failed... */ return false; }
static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr, idptr; PropertyRNA *prop; /* hook into UI */ UI_context_active_but_prop_get_templateID(C, &ptr, &prop); if (prop) { bAction *action = NULL, *oldact = NULL; AnimData *adt = NULL; PointerRNA oldptr; oldptr = RNA_property_pointer_get(&ptr, prop); oldact = (bAction *)oldptr.id.data; /* stash the old action to prevent it from being lost */ if (ptr.type == &RNA_AnimData) { adt = ptr.data; } else if (ptr.type == &RNA_SpaceDopeSheetEditor) { adt = ED_actedit_animdata_from_context(C); } /* Perform stashing operation - But only if there is an action */ if (adt && oldact) { /* stash the action */ if (BKE_nla_action_stash(adt)) { /* The stash operation will remove the user already * (and unlink the action from the AnimData action slot). * Hence, we must unset the ref to the action in the * action editor too (if this is where we're being called from) * first before setting the new action once it is created, * or else the user gets decremented twice! */ if (ptr.type == &RNA_SpaceDopeSheetEditor) { SpaceAction *saction = (SpaceAction *)ptr.data; saction->action = NULL; } } else { //printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name); } } /* create action */ action = action_create_new(C, oldact); /* set this new action * NOTE: we can't use actedit_change_action, as this function is also called from the NLA */ RNA_id_pointer_create(&action->id, &idptr); RNA_property_pointer_set(&ptr, prop, idptr); RNA_property_update(C, &ptr, prop); } /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL); return OPERATOR_FINISHED; }