/* can be called with C == NULL */ static EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) { Object *ob = get_poselib_object(C); bAction *act = (ob) ? ob->poselib : NULL; TimeMarker *marker; EnumPropertyItem *item= NULL, item_tmp= {0}; int totitem= 0; int i= 0; if (C == NULL) { return DummyRNA_DEFAULT_items; } /* check that the action exists */ if (act) { /* add each marker to the list */ for (marker=act->markers.first, i=0; marker; marker= marker->next, i++) { item_tmp.identifier= item_tmp.name= marker->name; item_tmp.icon= ICON_ARMATURE_DATA; item_tmp.value= i; RNA_enum_item_add(&item, &totitem, &item_tmp); } } RNA_enum_item_end(&item, &totitem); *free= 1; return item; }
static int poselib_rename_invoke (bContext *C, wmOperator *op, wmEvent *evt) { Object *ob= get_poselib_object(C); bAction *act= (ob) ? ob->poselib : NULL; TimeMarker *marker; /* check if valid poselib */ if (act == NULL) { BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data"); return OPERATOR_CANCELLED; } /* get index (and pointer) of pose to remove */ marker= BLI_findlink(&act->markers, act->active_marker-1); if (marker == NULL) { BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose"); return OPERATOR_CANCELLED; } else { /* use the existing name of the marker as the name, and use the active marker as the one to rename */ RNA_enum_set(op->ptr, "pose", act->active_marker-1); RNA_string_set(op->ptr, "name", marker->name); } /* part to sync with other similar operators... */ return WM_operator_props_popup(C, op, evt); }
static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) { Scene *scene= CTX_data_scene(C); Object *ob= get_poselib_object(C); bPose *pose= (ob) ? ob->pose : NULL; uiPopupMenu *pup; uiLayout *layout; /* sanity check */ if (ELEM(NULL, ob, pose)) return OPERATOR_CANCELLED; /* start building */ pup= uiPupMenuBegin(C, op->type->name, ICON_NONE); layout= uiPupMenuLayout(pup); uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); /* add new (adds to the first unoccupied frame) */ uiItemIntO(layout, IFACE_("Add New"), ICON_NONE, "POSELIB_OT_pose_add", "frame", poselib_get_free_index(ob->poselib)); /* check if we have any choices to add a new pose in any other way */ if ((ob->poselib) && (ob->poselib->markers.first)) { /* add new (on current frame) */ uiItemIntO(layout, IFACE_("Add New (Current Frame)"), ICON_NONE, "POSELIB_OT_pose_add", "frame", CFRA); /* replace existing - submenu */ uiItemMenuF(layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL); } uiPupMenuEnd(C, pup); /* this operator is only for a menu, not used further */ return OPERATOR_CANCELLED; }
static int poselib_remove_exec(bContext *C, wmOperator *op) { Object *ob = get_poselib_object(C); bAction *act = (ob) ? ob->poselib : NULL; TimeMarker *marker; int marker_index; FCurve *fcu; PropertyRNA *prop; /* check if valid poselib */ if (act == NULL) { BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data"); return OPERATOR_CANCELLED; } prop = RNA_struct_find_property(op->ptr, "pose"); if (RNA_property_is_set(op->ptr, prop)) { marker_index = RNA_property_enum_get(op->ptr, prop); } else { marker_index = act->active_marker - 1; } /* get index (and pointer) of pose to remove */ marker = BLI_findlink(&act->markers, marker_index); if (marker == NULL) { BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index); return OPERATOR_CANCELLED; } /* remove relevant keyframes */ for (fcu = act->curves.first; fcu; fcu = fcu->next) { BezTriple *bezt; unsigned int i; if (fcu->bezt) { for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* check if remove */ if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) { delete_fcurve_key(fcu, i, 1); break; } } } } /* remove poselib from list */ BLI_freelinkN(&act->markers, marker); /* fix active pose number */ act->active_marker = 0; /* send notifiers for this - using keyframe editing notifiers, since action * may be being shown in anim editors as active action */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); /* done */ return OPERATOR_FINISHED; }
static void poselib_add_menu_invoke__replacemenu (bContext *C, uiLayout *layout, void *UNUSED(arg)) { Object *ob= get_poselib_object(C); bAction *act= ob->poselib; /* never NULL */ TimeMarker *marker; wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1); BLI_assert(ot != NULL); /* set the operator execution context correctly */ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); /* add each marker to this menu */ for (marker= act->markers.first; marker; marker= marker->next) { PointerRNA props_ptr; props_ptr = uiItemFullO_ptr(layout, ot, marker->name, ICON_ARMATURE_DATA, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_int_set(&props_ptr, "frame", marker->frame); RNA_string_set(&props_ptr, "name", marker->name); } }
static int poselib_add_exec (bContext *C, wmOperator *op) { Object *ob= get_poselib_object(C); bAction *act = poselib_validate(ob); bPose *pose= (ob) ? ob->pose : NULL; TimeMarker *marker; KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_ID); /* this includes custom props :)*/ int frame= RNA_int_get(op->ptr, "frame"); char name[64]; /* sanity check (invoke should have checked this anyway) */ if (ELEM(NULL, ob, pose)) return OPERATOR_CANCELLED; /* get name to give to pose */ RNA_string_get(op->ptr, "name", name); /* add pose to poselib - replaces any existing pose there * - for the 'replace' option, this should end up finding the appropriate marker, * so no new one will be added */ for (marker= act->markers.first; marker; marker= marker->next) { if (marker->frame == frame) { BLI_strncpy(marker->name, name, sizeof(marker->name)); break; } } if (marker == NULL) { marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker"); BLI_strncpy(marker->name, name, sizeof(marker->name)); marker->frame= frame; BLI_addtail(&act->markers, marker); } /* validate name */ BLI_uniquename(&act->markers, marker, "Pose", '.', offsetof(TimeMarker, name), sizeof(marker->name)); /* use Keying Set to determine what to store for the pose */ // FIXME: in the past, the Keying Set respected selections (LocRotScale), but the current one doesn't (Whole Character) // so perhaps we need either a new Keying Set, or just to add overrides here... ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame); /* store new 'active' pose number */ act->active_marker= BLI_countlist(&act->markers); /* done */ return OPERATOR_FINISHED; }
static int poselib_new_exec (bContext *C, wmOperator *UNUSED(op)) { Object *ob = get_poselib_object(C); /* sanity checks */ if (ob == NULL) return OPERATOR_CANCELLED; /* new method here deals with the rest... */ poselib_init_new(ob); /* notifier here might evolve? */ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); return OPERATOR_FINISHED; }
static int poselib_unlink_exec (bContext *C, wmOperator *UNUSED(op)) { Object *ob = get_poselib_object(C); /* sanity checks */ if (ELEM(NULL, ob, ob->poselib)) return OPERATOR_CANCELLED; /* there should be a poselib (we just checked above!), so just lower its user count and remove */ id_us_min(&ob->poselib->id); ob->poselib = NULL; /* notifier here might evolve? */ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL); return OPERATOR_FINISHED; }
/* This tool automagically generates/validates poselib data so that it corresponds to the data * in the action. This is for use in making existing actions usable as poselibs. */ static int poselib_sanitise_exec (bContext *C, wmOperator *op) { Object *ob = get_poselib_object(C); bAction *act = (ob)? ob->poselib : NULL; DLRBT_Tree keys; ActKeyColumn *ak; TimeMarker *marker, *markern; /* validate action */ if (act == NULL) { BKE_report(op->reports, RPT_WARNING, "No Action to validate"); return OPERATOR_CANCELLED; } /* determine which frames have keys */ BLI_dlrbTree_init(&keys); action_to_keylist(NULL, act, &keys, NULL); BLI_dlrbTree_linkedlist_sync(&keys); /* for each key, make sure there is a corresponding pose */ for (ak= keys.first; ak; ak= ak->next) { /* check if any pose matches this */ // TODO: don't go looking through the list like this every time... for (marker= act->markers.first; marker; marker= marker->next) { if (IS_EQ(marker->frame, (double)ak->cfra)) { marker->flag = -1; break; } } /* add new if none found */ if (marker == NULL) { /* add pose to poselib */ marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker"); BLI_strncpy(marker->name, "Pose", sizeof(marker->name)); marker->frame= (int)ak->cfra; marker->flag= -1; BLI_addtail(&act->markers, marker); } } /* remove all untagged poses (unused), and remove all tags */ for (marker= act->markers.first; marker; marker= markern) { markern= marker->next; if (marker->flag != -1) BLI_freelinkN(&act->markers, marker); else marker->flag = 0; } /* free temp memory */ BLI_dlrbTree_free(&keys); /* send notifiers for this - using keyframe editing notifiers, since action * may be being shown in anim editors as active action */ WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); return OPERATOR_FINISHED; }
/* Poll callback for operators that require existing PoseLib data (with poses) to work */ static int has_poselib_pose_data_poll (bContext *C) { Object *ob = get_poselib_object(C); return (ob && ob->poselib); }
/* Init PoseLib Previewing data */ static void poselib_preview_init_data (bContext *C, wmOperator *op) { tPoseLib_PreviewData *pld; Object *ob= get_poselib_object(C); int pose_index = RNA_int_get(op->ptr, "pose_index"); /* set up preview state info */ op->customdata= pld= MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data"); /* get basic data */ pld->ob= ob; pld->arm= (ob) ? (ob->data) : NULL; pld->pose= (ob) ? (ob->pose) : NULL; pld->act= (ob) ? (ob->poselib) : NULL; pld->scene= CTX_data_scene(C); pld->sa= CTX_wm_area(C); /* get starting pose based on RNA-props for this operator */ if (pose_index == -1) pld->marker= poselib_get_active_pose(pld->act); else if (pose_index == -2) pld->flag |= PL_PREVIEW_SHOWORIGINAL; else pld->marker= (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL; /* check if valid poselib */ if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) { BKE_report(op->reports, RPT_ERROR, "PoseLib is only for Armatures in PoseMode"); pld->state= PL_PREVIEW_ERROR; return; } if (pld->act == NULL) { BKE_report(op->reports, RPT_ERROR, "Object doesn't have a valid PoseLib"); pld->state= PL_PREVIEW_ERROR; return; } if (pld->marker == NULL) { if (pld->act->markers.first) { /* just use first one then... */ pld->marker= pld->act->markers.first; if (pose_index > -2) BKE_report(op->reports, RPT_WARNING, "PoseLib had no active pose"); } else { BKE_report(op->reports, RPT_ERROR, "PoseLib has no poses to preview/apply"); pld->state= PL_PREVIEW_ERROR; return; } } /* get ID pointer for applying poses */ RNA_id_pointer_create(&ob->id, &pld->rna_ptr); /* make backups for restoring pose */ poselib_backup_posecopy(pld); /* set flags for running */ pld->state= PL_PREVIEW_RUNNING; pld->redraw= PL_PREVIEW_REDRAWALL; pld->flag |= PL_PREVIEW_FIRSTTIME; /* set depsgraph flags */ /* make sure the lock is set OK, unlock can be accidentally saved? */ pld->pose->flag |= POSE_LOCKED; pld->pose->flag &= ~POSE_DO_UNLOCK; /* clear strings + search */ pld->headerstr[0]= pld->searchstr[0]= pld->searchold[0]= '\0'; pld->search_cursor= 0; }