static int act_new_exec(bContext *C, wmOperator *op) { bAction *action; PointerRNA ptr, idptr; PropertyRNA *prop; // XXX need to restore behaviour to copy old actions... action= add_empty_action("Action"); /* hook into UI */ uiIDContextProperty(C, &ptr, &prop); if(prop) { /* when creating new ID blocks, use is already 1, but RNA * pointer se also increases user, so this compensates it */ action->id.us--; 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_EDIT, NULL); return OPERATOR_FINISHED; }
int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) { ID *newid = NULL; PointerRNA idptr; if (id) { /* if property isn't editable, we're going to have an extra block hanging around until we save */ if (RNA_property_editable(ptr, prop)) { if (id_copy(id, &newid, 0) && newid) { /* copy animation actions too */ BKE_copy_animdata_id_action(id); /* us is 1 by convention, but RNA_property_pointer_set will also incremement it, so set it to zero */ newid->us= 0; /* assign copy */ RNA_id_pointer_create(newid, &idptr); RNA_property_pointer_set(ptr, prop, idptr); RNA_property_update(C, ptr, prop); return 1; } } } return 0; }
/* sets the ID, returns success */ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id) { PointerRNA ptr_value; RNA_id_pointer_create(id, &ptr_value); RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value); RNA_property_update(C, &ddr->ptr, ddr->prop); ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop); return (ptr_value.id.data == id); }
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 act_new_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr, idptr; PropertyRNA *prop; /* hook into UI */ uiIDContextProperty(C, &ptr, &prop); if (prop) { bAction *action = NULL, *oldact = NULL; PointerRNA oldptr; /* create action - the way to do this depends on whether we've got an * existing one there already, in which case we make a copy of it * (which is useful for "versioning" actions within the same file) */ oldptr = RNA_property_pointer_get(&ptr, prop); oldact = (bAction *)oldptr.id.data; if (oldact && GS(oldact->id.name) == ID_AC) { /* make a copy of the existing action */ action = BKE_action_copy(oldact); } else { Main *bmain = CTX_data_main(C); /* just make a new (empty) action */ action = add_empty_action(bmain, "Action"); } /* when creating new ID blocks, use is already 1 (fake user), * but RNA pointer use also increases user, so this compensates it */ action->id.us--; 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_EDITED, NULL); return OPERATOR_FINISHED; }
/* Change the active action used by the action editor */ static void actedit_change_action(bContext *C, bAction *act) { bScreen *screen = CTX_wm_screen(C); SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); PointerRNA ptr, idptr; PropertyRNA *prop; /* create RNA pointers and get the property */ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr); prop = RNA_struct_find_property(&ptr, "action"); /* NOTE: act may be NULL here, so better to just use a cast here */ RNA_id_pointer_create((ID *)act, &idptr); /* set the new pointer, and force a refresh */ RNA_property_pointer_set(&ptr, prop, idptr); RNA_property_update(C, &ptr, prop); }
static int open_exec(bContext *C, wmOperator *op) { SpaceClip *sc = CTX_wm_space_clip(C); bScreen *screen = CTX_wm_screen(C); Main *bmain = CTX_data_main(C); PropertyPointerRNA *pprop; PointerRNA idptr; MovieClip *clip = NULL; char str[FILE_MAX]; if (RNA_collection_length(op->ptr, "files")) { PointerRNA fileptr; PropertyRNA *prop; char dir_only[FILE_MAX], file_only[FILE_MAX]; int relative = RNA_boolean_get(op->ptr, "relative_path"); RNA_string_get(op->ptr, "directory", dir_only); if (relative) BLI_path_rel(dir_only, G.main->name); prop = RNA_struct_find_property(op->ptr, "files"); RNA_property_collection_lookup_int(op->ptr, prop, 0, &fileptr); RNA_string_get(&fileptr, "name", file_only); BLI_join_dirfile(str, sizeof(str), dir_only, file_only); } else { BKE_report(op->reports, RPT_ERROR, "No files selected to be opened"); return OPERATOR_CANCELLED; } /* default to frame 1 if there's no scene in context */ errno = 0; clip = BKE_movieclip_file_add(bmain, str); if (!clip) { if (op->customdata) MEM_freeN(op->customdata); BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", str, errno ? strerror(errno) : TIP_("unsupported movie clip format")); return OPERATOR_CANCELLED; } if (!op->customdata) open_init(C, op); /* hook into UI */ pprop = op->customdata; if (pprop->prop) { /* when creating new ID blocks, use is already 1, but RNA * pointer se also increases user, so this compensates it */ clip->id.us--; RNA_id_pointer_create(&clip->id, &idptr); RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (sc) { ED_space_clip_set_clip(C, screen, sc, clip); } WM_event_add_notifier(C, NC_MOVIECLIP | NA_ADDED, clip); MEM_freeN(op->customdata); 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); } } }
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; }