void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports) { ScrArea *sa = CTX_wm_area(C); /* If the old action only has a single user (that it's about to lose), * warn user about it * * TODO: Maybe we should just save it for them? But then, there's the problem of * trying to get rid of stuff that's actually unwanted! */ if (act->id.us == 1) { BKE_reportf(reports, RPT_WARNING, "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", act->id.name + 2); } /* If in Tweak Mode, don't unlink. Instead, this * becomes a shortcut to exit Tweak Mode instead */ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { /* Exit Tweak Mode */ BKE_nla_tweakmode_exit(adt); /* Flush this to the Action Editor (if that's where this change was initiated) */ if (sa->spacetype == SPACE_ACTION) { actedit_change_action(C, NULL); } } else { /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */ if (sa->spacetype == SPACE_ACTION) { /* clear action editor -> action */ actedit_change_action(C, NULL); } else { /* clear AnimData -> action */ PointerRNA ptr; PropertyRNA *prop; /* create AnimData RNA pointers */ RNA_pointer_create(id, &RNA_AnimData, adt, &ptr); prop = RNA_struct_find_property(&ptr, "action"); /* clear... */ RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL); RNA_property_update(C, &ptr, prop); } } }
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_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_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; }
void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete) { ScrArea *sa = CTX_wm_area(C); /* If the old action only has a single user (that it's about to lose), * warn user about it * * TODO: Maybe we should just save it for them? But then, there's the problem of * trying to get rid of stuff that's actually unwanted! */ if (act->id.us == 1) { BKE_reportf(reports, RPT_WARNING, "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain", act->id.name + 2); } /* Clear Fake User and remove action stashing strip (if present) */ if (force_delete) { /* Remove stashed strip binding this action to this datablock */ /* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it, * but GE users only seem to use/care about single-object binding for now so this * should be fine */ if (adt) { NlaTrack *nlt, *nlt_next; NlaStrip *strip, *nstrip; for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) { nlt_next = nlt->next; if (strstr(nlt->name, DATA_("[Action Stash]"))) { for (strip = nlt->strips.first; strip; strip = nstrip) { nstrip = strip->next; if (strip->act == act) { /* Remove this strip, and the track too if it doesn't have anything else */ free_nlastrip(&nlt->strips, strip); if (nlt->strips.first == NULL) { BLI_assert(nstrip == NULL); free_nlatrack(&adt->nla_tracks, nlt); } } } } } } /* Clear Fake User */ id_fake_user_clear(&act->id); } /* If in Tweak Mode, don't unlink. Instead, this * becomes a shortcut to exit Tweak Mode instead */ if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) { /* Exit Tweak Mode */ BKE_nla_tweakmode_exit(adt); /* Flush this to the Action Editor (if that's where this change was initiated) */ if (sa->spacetype == SPACE_ACTION) { actedit_change_action(C, NULL); } } else { /* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */ if (sa->spacetype == SPACE_ACTION) { /* clear action editor -> action */ actedit_change_action(C, NULL); } else { /* clear AnimData -> action */ PointerRNA ptr; PropertyRNA *prop; /* create AnimData RNA pointers */ RNA_pointer_create(id, &RNA_AnimData, adt, &ptr); prop = RNA_struct_find_property(&ptr, "action"); /* clear... */ RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL); RNA_property_update(C, &ptr, prop); } } }