diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-04-15 05:10:36 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-04-15 05:10:36 +0400 |
commit | 2dbf73f6a032ab44539cfd8c05f5743fbaf33902 (patch) | |
tree | 2a3093dfa8b561213db1c58bf2583cb05f6b2ed5 /source/blender | |
parent | 5b3d7bfdf6305e880f89d58cbe852a8d2ba7b241 (diff) |
2.5 PoseLib - First steps to get PoseLib to work in 2.5
* Cleaned up Keyframing API to get eliminate some of the problems faced during the original implementation of PoseLib, thus reducing code redundancy.
* Added new Animato evaluation functions specifically for use by PoseLib.
* Replaced parts of PoseLib code which relied on old animation system to the equivalent code for Animato. Notice the much cleaner + saner + compact code!
Next step is to operatorfy the PoseLib tools (while maintaining possibility for an API to some things) :)
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_animsys.h | 21 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim_sys.c | 28 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_intern.h | 22 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_edit.c | 30 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 64 | ||||
-rw-r--r-- | source/blender/editors/animation/keyingsets.c | 36 | ||||
-rw-r--r-- | source/blender/editors/armature/poselib.c | 195 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframes_edit.h | 5 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframing.h | 82 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit.c | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 92 |
11 files changed, 348 insertions, 229 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 44c8d827e8c..70a0cd34a6c 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -12,6 +12,10 @@ struct AnimData; struct KeyingSet; struct KS_Path; +struct PointerRNA; +struct bAction; +struct AnimMapper; + /* ************************************* */ /* AnimData API */ @@ -50,6 +54,9 @@ void BKE_keyingsets_free(struct ListBase *list); /* ************************************* */ /* Evaluation API */ +/* ------------- Main API -------------------- */ +/* In general, these ones should be called to do all animation evaluation */ + /* Evaluation loop for evaluating animation data */ void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ctime, short recalc); @@ -57,6 +64,20 @@ void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ct void BKE_animsys_evaluate_all_animation(struct Main *main, float ctime); +/* ------------ Specialised API --------------- */ +/* There are a few special tools which require these following functions. They are NOT to be used + * for standard animation evaluation UNDER ANY CIRCUMSTANCES! + * + * i.e. Pose Library (PoseLib) uses some of these for selectively applying poses, but + * Particles/Sequencer performing funky time manipulation is not ok. + */ + +/* Evaluate Action (F-Curve Bag) */ +void animsys_evaluate_action(struct PointerRNA *ptr, struct bAction *act, struct AnimMapper *remap, float ctime); + +/* Evaluate Action Group */ +void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, struct bActionGroup *agrp, struct AnimMapper *remap, float ctime); + /* ************************************* */ #endif /* BKE_ANIM_SYS_H*/ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index ebced7837ae..c8b2ff71612 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -504,8 +504,29 @@ static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctim /* ***************************************** */ /* Actions Evaluation */ +/* Evaluate Action Group */ +void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup *agrp, AnimMapper *remap, float ctime) +{ + FCurve *fcu; + + /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ + if ELEM(NULL, act, agrp) return; + if ((remap) && (remap->target != act)) remap= NULL; + + /* calculate then execute each curve */ + for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) + { + /* check if this curve should be skipped */ + if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) + { + calculate_fcurve(fcu, ctime); + animsys_execute_fcurve(ptr, remap, fcu); + } + } +} + /* Evaluate Action (F-Curve Bag) */ -static void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) +void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) { /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ if (act == NULL) return; @@ -863,7 +884,10 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) // TODO... /* objects */ - EVAL_ANIM_IDS(main->object.first, ADT_RECALC_ANIM); + /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets + * this tagged by Depsgraph on framechange + */ + EVAL_ANIM_IDS(main->object.first, /*ADT_RECALC_ANIM*/0); /* worlds */ EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM); diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h index 6cbecab7832..e903007fbc0 100644 --- a/source/blender/editors/animation/anim_intern.h +++ b/source/blender/editors/animation/anim_intern.h @@ -5,36 +5,14 @@ #ifndef ANIM_INTERN_H #define ANIM_INTERN_H -/* ----------- Common Keyframe Destination Sources ------------ */ -/* (used as part of KeyingSets/Keyframing interface as separation from context) */ - -/* temporary struct to gather data combos to keyframe */ -typedef struct bCommonKeySrc { - struct bCommonKeySrc *next, *prev; - - /* general data/destination-source settings */ - ID *id; /* id-block this comes from */ - - /* specific cases */ - bPoseChannel *pchan; - bConstraint *con; -} bCommonKeySrc; /* KeyingSets/Keyframing Interface ------------- */ /* list of builtin KeyingSets (defined in keyingsets.c) */ extern ListBase builtin_keyingsets; -/* mode for modify_keyframes */ -enum { - MODIFYKEY_MODE_INSERT = 0, - MODIFYKEY_MODE_DELETE, -} eModifyKey_Modes; - short keyingset_context_ok_poll(bContext *C, KeyingSet *ks); short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks); -int modify_keyframes(bContext *C, ListBase *dsources, KeyingSet *ks, short mode, float cfra); - #endif // ANIM_INTERN_H diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 8b83022507d..bef44448829 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -239,6 +239,36 @@ short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, bAnimListElem *ale, B return 0; } +/* This function is used to apply operation to all keyframes, regardless of the type without needed an AnimListElem wrapper */ +short ANIM_animchanneldata_keys_bezier_loop(BeztEditData *bed, void *data, int keytype, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag) +{ + /* sanity checks */ + if (data == NULL) + return 0; + + /* method to use depends on the type of keyframe data */ + switch (keytype) { + /* direct keyframe data (these loops are exposed) */ + case ALE_FCURVE: /* F-Curve */ + return ANIM_fcurve_keys_bezier_loop(bed, data, bezt_ok, bezt_cb, fcu_cb); + + /* indirect 'summaries' (these are not exposed directly) + * NOTE: must keep this code in sync with the drawing code and also the filtering code! + */ + case ALE_GROUP: /* action group */ + return agrp_keys_bezier_loop(bed, (bActionGroup *)data, bezt_ok, bezt_cb, fcu_cb); + case ALE_ACT: /* action */ + return act_keys_bezier_loop(bed, (bAction *)data, bezt_ok, bezt_cb, fcu_cb); + + case ALE_OB: /* object */ + return ob_keys_bezier_loop(bed, (Object *)data, bezt_ok, bezt_cb, fcu_cb, filterflag); + case ALE_SCE: /* scene */ + return scene_keys_bezier_loop(bed, (Scene *)data, bezt_ok, bezt_cb, fcu_cb, filterflag); + } + + return 0; +} + /* ************************************************************************** */ /* Keyframe Integrity Tools */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 26803f616e4..c09ac20f91b 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -55,19 +55,12 @@ /* ******************************************* */ /* Animation Data Validation */ -/* Get (or add relevant data to be able to do so) F-Curve from the Active Action, - * for the given Animation Data block. This assumes that all the destinations are valid. +/* Get (or add relevant data to be able to do so) the Active Action for the given + * Animation Data block, given an ID block where the Animation Data should reside. */ -FCurve *verify_fcurve (ID *id, const char group[], const char rna_path[], const int array_index, short add) +bAction *verify_adt_action (ID *id, short add) { AnimData *adt; - bAction *act; - bActionGroup *grp; - FCurve *fcu; - - /* sanity checks */ - if ELEM(NULL, id, rna_path) - return NULL; /* init animdata if none available yet */ adt= BKE_animdata_from_id(id); @@ -82,7 +75,22 @@ FCurve *verify_fcurve (ID *id, const char group[], const char rna_path[], const // TODO: need some wizardry to handle NLA stuff correct if ((adt->action == NULL) && (add)) adt->action= add_empty_action("Action"); - act= adt->action; + + /* return the action */ + return adt->action; +} + +/* Get (or add relevant data to be able to do so) F-Curve from the Active Action, + * for the given Animation Data block. This assumes that all the destinations are valid. + */ +FCurve *verify_fcurve (bAction *act, const char group[], const char rna_path[], const int array_index, short add) +{ + bActionGroup *grp; + FCurve *fcu; + + /* sanity checks */ + if ELEM(NULL, act, rna_path) + return NULL; /* try to find f-curve matching for this setting * - add if not found and allowed to add one @@ -695,7 +703,7 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, * and extra keyframe filtering. */ -short insertkey (ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag) +short insert_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) { PointerRNA id_ptr, ptr; PropertyRNA *prop; @@ -708,8 +716,10 @@ short insertkey (ID *id, const char group[], const char rna_path[], int array_in return 0; } - /* get F-Curve */ - fcu= verify_fcurve(id, group, rna_path, array_index, 1); + /* get F-Curve - if no action is provided, keyframe to the default one attached to this ID-block */ + if (act == NULL) + act= verify_adt_action(id, 1); + fcu= verify_fcurve(act, group, rna_path, array_index, 1); /* only continue if we have an F-Curve to add keyframe to */ if (fcu) { @@ -797,22 +807,24 @@ short insertkey (ID *id, const char group[], const char rna_path[], int array_in * The flag argument is used for special settings that alter the behaviour of * the keyframe deletion. These include the quick refresh options. */ -short deletekey (ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag) +short delete_keyframe (ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) { - AnimData *adt; - FCurve *fcu; + FCurve *fcu = NULL; /* get F-Curve * Note: here is one of the places where we don't want new Action + F-Curve added! * so 'add' var must be 0 */ + if (act == NULL) { + /* if no action is provided, use the default one attached to this ID-block */ + AnimData *adt= BKE_animdata_from_id(id); + act= adt->action; + } /* we don't check the validity of the path here yet, but it should be ok... */ - fcu= verify_fcurve(id, group, rna_path, array_index, 0); - adt= BKE_animdata_from_id(id); + fcu= verify_fcurve(act, group, rna_path, array_index, 0); /* only continue if we have an F-Curve to remove keyframes from */ - if (adt && adt->action && fcu) { - bAction *act= adt->action; + if (act && fcu) { short found = -1; int i; @@ -926,7 +938,7 @@ static int insert_key_exec (bContext *C, wmOperator *op) } /* try to insert keyframes for the channels specified by KeyingSet */ - success= modify_keyframes(C, &dsources, ks, MODIFYKEY_MODE_INSERT, cfra); + success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); printf("KeyingSet '%s' - Successfully added %d Keyframes \n", ks->name, success); /* report failure? */ @@ -1069,7 +1081,7 @@ static int delete_key_exec (bContext *C, wmOperator *op) } /* try to insert keyframes for the channels specified by KeyingSet */ - success= modify_keyframes(C, &dsources, ks, MODIFYKEY_MODE_DELETE, cfra); + success= modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_DELETE, cfra); printf("KeyingSet '%s' - Successfully removed %d Keyframes \n", ks->name, success); /* report failure? */ @@ -1138,7 +1150,7 @@ static int delete_key_old_exec (bContext *C, wmOperator *op) for (fcu= act->curves.first; fcu; fcu= fcn) { fcn= fcu->next; - success+= deletekey(id, NULL, fcu->rna_path, fcu->array_index, cfra, 0); + success+= delete_keyframe(id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); } } @@ -1203,7 +1215,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op) length= 1; for(a=0; a<length; a++) - success+= insertkey(ptr.id.data, NULL, path, index+a, cfra, 0); + success+= insert_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0); MEM_freeN(path); } @@ -1267,7 +1279,7 @@ static int delete_key_button_exec (bContext *C, wmOperator *op) length= 1; for(a=0; a<length; a++) - success+= deletekey(ptr.id.data, NULL, path, index+a, cfra, 0); + success+= delete_keyframe(ptr.id.data, NULL, NULL, path, index+a, cfra, 0); MEM_freeN(path); } diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 63bab10aef3..e36b3b8a6b1 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -814,6 +814,32 @@ void init_builtin_keyingsets (void) } } + +/* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */ +KeyingSet *ANIM_builtin_keyingset_get_named (KeyingSet *prevKS, char name[]) +{ + KeyingSet *ks, *first=NULL; + + /* sanity checks - any name to check? */ + if (name[0] == 0) + return NULL; + + /* get first KeyingSet to use */ + if (prevKS && prevKS->next) + first= prevKS->next; + else + first= builtin_keyingsets.first; + + /* loop over KeyingSets checking names */ + for (ks= first; ks; ks= ks->next) { + if (strcmp(name, ks->name) == 0) + return ks; + } + + /* no matches found */ + return NULL; +} + /* ******************************************* */ /* KEYFRAME MODIFICATION */ @@ -957,7 +983,7 @@ short modifykey_get_context_data (bContext *C, ListBase *dsources, KeyingSet *ks * by the KeyingSet. This takes into account many of the different combinations of using KeyingSets. * Returns the number of channels that keyframes were added to */ -int modify_keyframes (bContext *C, ListBase *dsources, KeyingSet *ks, short mode, float cfra) +int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra) { KS_Path *ksp; int kflag=0, success= 0; @@ -1014,9 +1040,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, KeyingSet *ks, short mode for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) - success+= insertkey(ksp->id, groupname, ksp->rna_path, i, cfra, kflag); + success+= insert_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag); else if (mode == MODIFYKEY_MODE_DELETE) - success+= deletekey(ksp->id, groupname, ksp->rna_path, i, cfra, kflag); + success+= delete_keyframe(ksp->id, act, groupname, ksp->rna_path, i, cfra, kflag); } /* send notifiers and set recalc-flags */ @@ -1105,9 +1131,9 @@ int modify_keyframes (bContext *C, ListBase *dsources, KeyingSet *ks, short mode for (; i < arraylen; i++) { /* action to take depends on mode */ if (mode == MODIFYKEY_MODE_INSERT) - success+= insertkey(cks->id, groupname, path, i, cfra, kflag); + success+= insert_keyframe(cks->id, act, groupname, path, i, cfra, kflag); else if (mode == MODIFYKEY_MODE_DELETE) - success+= deletekey(cks->id, groupname, path, i, cfra, kflag); + success+= delete_keyframe(cks->id, act, groupname, path, i, cfra, kflag); } /* free the path */ diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index f27bec81d7a..ca754ed426f 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -39,6 +39,7 @@ #include "BLI_dynstr.h" #include "DNA_listBase.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_curve_types.h" @@ -48,10 +49,10 @@ #include "DNA_scene_types.h" #include "DNA_userdef_types.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_depsgraph.h" -#include "BKE_ipo.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -60,6 +61,9 @@ #include "PIL_time.h" /* sleep */ +#include "RNA_access.h" +#include "RNA_types.h" + #include "WM_types.h" #include "ED_anim_api.h" @@ -272,33 +276,31 @@ void poselib_validate_act (bAction *act) } /* ************************************************************* */ -#if 0 // XXX old animation system -/* This function adds an ipo-curve of the right type where it's needed */ -static IpoCurve *poselib_verify_icu (Ipo *ipo, int adrcode) +/* Pointers to the builtin KeyingSets that we want to use */ +static KeyingSet *poselib_ks_locrotscale = NULL; /* quaternion rotations */ +static KeyingSet *poselib_ks_locrotscale2 = NULL; /* euler rotations */ // XXX FIXME... +static short poselib_ks_need_init= 1; /* have the above been obtained yet? */ + +/* Make sure the builtin KeyingSets are initialised properly + * (only gets called on first run of poselib_add_current_pose). + */ +static void poselib_get_builtin_keyingsets (void) { - IpoCurve *icu; - - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->adrcode==adrcode) break; - } - if (icu==NULL) { - icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); + /* only if we haven't got these yet */ + // FIXME: this assumes that we will always get the builtin sets... + if (poselib_ks_need_init) { + /* LocRotScale (quaternions) */ + poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale"); - icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ; - if (ipo->curve.first==NULL) icu->flag |= IPO_ACTIVE; /* first one added active */ + /* LocRotScale (euler) */ + //ks_locrotscale2= ANIM_builtin_keyingset_get_named(ks_locrotscale, "LocRotScale"); + poselib_ks_locrotscale2= poselib_ks_locrotscale; // FIXME: for now, just use the same one... - icu->blocktype= ID_PO; - icu->adrcode= adrcode; - - set_icu_vars(icu); - - BLI_addtail(&ipo->curve, icu); + /* clear flag requesting init */ + poselib_ks_need_init= 0; } - - return icu; } -#endif // XXX old animation system /* This tool adds the current pose to the poselib * Note: Standard insertkey cannot be used for this due to its limitations @@ -310,11 +312,13 @@ void poselib_add_current_pose (Scene *scene, Object *ob, int val) bPoseChannel *pchan; TimeMarker *marker; bAction *act; - // bActionChannel *achan; - // IpoCurve *icu; int frame; char name[64]; + bCommonKeySrc cks; + ListBase dsources = {&cks, &cks}; + + /* sanity check */ if (ELEM3(NULL, ob, arm, pose)) return; @@ -382,37 +386,26 @@ void poselib_add_current_pose (Scene *scene, Object *ob, int val) BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); } + /* make sure we've got KeyingSets to use */ + poselib_get_builtin_keyingsets(); + + /* init common-key-source for use by KeyingSets */ + memset(&cks, 0, sizeof(bCommonKeySrc)); + cks.id= &ob->id; + /* loop through selected posechannels, keying their pose to the action */ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { /* check if available */ if ((pchan->bone) && (arm->layer & pchan->bone->layer)) { if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) { -#if 0 // XXX old animation system - /* make action-channel if needed (action groups are also created) */ - achan= verify_action_channel(act, pchan->name); - verify_pchan2achan_grouping(act, pose, pchan->name); + /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ + cks.pchan= pchan; - /* make ipo if needed... */ - if (achan->ipo == NULL) - achan->ipo= add_ipo(scene, achan->name, ID_PO); - - /* add missing ipo-curves and insert keys */ - #define INSERT_KEY_ICU(adrcode, data) {\ - icu= poselib_verify_icu(achan->ipo, adrcode); \ - insert_vert_icu(icu, (float)frame, data, 1); \ - } - - INSERT_KEY_ICU(AC_LOC_X, pchan->loc[0]) - INSERT_KEY_ICU(AC_LOC_Y, pchan->loc[1]) - INSERT_KEY_ICU(AC_LOC_Z, pchan->loc[2]) - INSERT_KEY_ICU(AC_SIZE_X, pchan->size[0]) - INSERT_KEY_ICU(AC_SIZE_Y, pchan->size[1]) - INSERT_KEY_ICU(AC_SIZE_Z, pchan->size[2]) - INSERT_KEY_ICU(AC_QUAT_W, pchan->quat[0]) - INSERT_KEY_ICU(AC_QUAT_X, pchan->quat[1]) - INSERT_KEY_ICU(AC_QUAT_Y, pchan->quat[2]) - INSERT_KEY_ICU(AC_QUAT_Z, pchan->quat[3]) -#endif // XXX old animation system + /* KeyingSet to use depends on rotation mode */ + if (pchan->rotmode) + modify_keyframes(/*C*/NULL, &dsources, act, poselib_ks_locrotscale2, MODIFYKEY_MODE_INSERT, (float)frame); + else + modify_keyframes(/*C*/NULL, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame); } } } @@ -429,7 +422,7 @@ void poselib_remove_pose (Object *ob, TimeMarker *marker) { bPose *pose= (ob) ? ob->pose : NULL; bAction *act= (ob) ? ob->poselib : NULL; - // bActionChannel *achan; + FCurve *fcu; char *menustr; int val; @@ -460,24 +453,20 @@ void poselib_remove_pose (Object *ob, TimeMarker *marker) } /* remove relevant keyframes */ -#if 0 // XXX old animation system - for (achan= act->chanbase.first; achan; achan= achan->next) { - Ipo *ipo= achan->ipo; - IpoCurve *icu; + for (fcu= act->curves.first; fcu; fcu= fcu->next) { BezTriple *bezt; int i; - for (icu= ipo->curve.first; icu; icu= icu->next) { - for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - /* check if remove... */ + if (fcu->bezt) { + for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) { + /* check if remove */ if (IS_EQ(bezt->vec[1][0], marker->frame)) { - delete_icu_key(icu, i, 1); + delete_fcurve_key(fcu, i, 1); break; } - } + } } } -#endif // XXX old animation system /* remove poselib from list */ BLI_freelinkN(&act->markers, marker); @@ -539,6 +528,7 @@ typedef struct tPoseLib_PreviewData { ListBase backups; /* tPoseLib_Backup structs for restoring poses */ ListBase searchp; /* LinkData structs storing list of poses which match the current search-string */ + PointerRNA *rna_ptr; /* RNA-Pointer to Object 'ob' */ Object *ob; /* object to work on */ bArmature *arm; /* object's armature data */ bPose *pose; /* object's pose */ @@ -641,74 +631,57 @@ static void poselib_backup_restore (tPoseLib_PreviewData *pld) */ static void poselib_apply_pose (tPoseLib_PreviewData *pld) { + PointerRNA *ptr= pld->rna_ptr; + bArmature *arm= pld->arm; bPose *pose= pld->pose; bPoseChannel *pchan; bAction *act= pld->act; - bActionChannel *achan; - IpoCurve *icu; + bActionGroup *agrp; + + BeztEditData bed; + BeztEditFunc group_ok_cb; int frame; + /* get the frame */ if (pld->marker) frame= pld->marker->frame; else return; + /* init settings for testing groups for keyframes */ + group_ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); + memset(&bed, 0, sizeof(BeztEditData)); + bed.f1= ((float)frame) - 0.5f; + bed.f2= ((float)frame) + 0.5f; + /* start applying - only those channels which have a key at this point in time! */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - short found= 0; - - /* apply this achan? */ - if (achan->ipo) { - /* find a keyframe at this frame - users may not have defined the pose on every channel, so this is necessary */ - // TODO: this may be bad for user-defined poses... - for (icu= achan->ipo->curve.first; icu; icu= icu->next) { - BezTriple *bezt; - int i; + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + /* check if group has any keyframes */ + if (ANIM_animchanneldata_keys_bezier_loop(&bed, agrp, ALE_GROUP, NULL, group_ok_cb, NULL, 0)) { + /* has keyframe on this frame, so try to get a PoseChannel with this name */ + pchan= get_pose_channel(pose, agrp->name); + + if (pchan) { + short ok= 0; - for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - if (IN_RANGE(bezt->vec[1][0], (frame-0.5f), (frame+0.5f))) { - found= 1; - break; - } + /* check if this bone should get any animation applied */ + if (pld->selcount == 0) { + /* if no bones are selected, then any bone is ok */ + ok= 1; + } + else if (pchan->bone) { + /* only ok if bone is visible and selected */ + if ( (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) && + (pchan->bone->flag & BONE_HIDDEN_P)==0 && + (pchan->bone->layer & arm->layer) ) + ok = 1; } - if (found) break; - } - - /* apply pose - only if posechannel selected? */ - if (found) { - pchan= get_pose_channel(pose, achan->name); - - if (pchan) { - short ok= 0; - - if (pchan->bone) { - if ( (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) && - (pchan->bone->flag & BONE_HIDDEN_P)==0 ) - ok = 1; - else if (pld->selcount == 0) - ok= 1; - } - else if (pld->selcount == 0) - ok= 1; - - if (ok) { -#if 0 // XXX old animation system - /* Evaluates and sets the internal ipo values */ - calc_ipo(achan->ipo, (float)frame); - /* This call also sets the pchan flags */ - execute_action_ipo(achan, pchan); -#endif // XXX old animation system - } + if (ok) { + animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame); } } } - - /* tag achan as having been used or not... */ - if (found) - achan->flag |= ACHAN_SELECTED; - else - achan->flag &= ~ACHAN_SELECTED; } } diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index b0dc565bfcc..44d4e26fea5 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -114,7 +114,10 @@ short ANIM_fcurve_keys_bezier_loop(BeztEditData *bed, struct FCurve *fcu, BeztEd * - filterflag is bDopeSheet->flag (DOPESHEET_FILTERFLAG) */ short ANIM_animchannel_keys_bezier_loop(BeztEditData *bed, struct bAnimListElem *ale, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag); - + /* same as above, except bAnimListElem wrapper is not needed... + * - keytype is eAnim_KeyType + */ +short ANIM_animchanneldata_keys_bezier_loop(BeztEditData *bed, void *data, int keytype, BeztEditFunc bezt_ok, BeztEditFunc bezt_cb, FcuEditFunc fcu_cb, int filterflag); /* functions for making sure all keyframes are in good order */ void ANIM_editkeyframes_refresh(struct bAnimContext *ac); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 98a44d3ef2b..fbb469f8d43 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -33,13 +33,30 @@ struct ID; struct KeyingSet; +struct bAction; struct FCurve; struct BezTriple; +struct bPoseChannel; +struct bConstraint; + +struct bContext; struct wmOperatorType; /* ************ Keyframing Management **************** */ +/* Get (or add relevant data to be able to do so) the Active Action for the given + * Animation Data block, given an ID block where the Animation Data should reside. + */ +struct bAction *verify_adt_action(struct ID *id, short add); + +/* Get (or add relevant data to be able to do so) F-Curve from the given Action. + * This assumes that all the destinations are valid. + */ +struct FCurve *verify_fcurve(struct bAction *act, const char group[], const char rna_path[], const int array_index, short add); + +/* -------- */ + /* Lesser Keyframing API call: * Use this when validation of necessary animation data isn't necessary as it already * exists, and there is a beztriple that can be directly copied into the array. @@ -58,26 +75,14 @@ void insert_vert_fcurve(struct FCurve *fcu, float x, float y, short flag); * Use this to create any necessary animation data, and then insert a keyframe * using the current value being keyframed, in the relevant place. Returns success. */ -short insertkey(struct ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag); +short insert_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag); /* Main Keyframing API call: * Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case. */ -short deletekey(struct ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag); - - -/* Generate menu of KeyingSets */ -char *ANIM_build_keyingsets_menu(struct ListBase *list, short for_edit); - -/* Initialise builtin KeyingSets on startup */ -void init_builtin_keyingsets(void); +short delete_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag); -/* KeyingSet Editing Operators: - * These can add a new KeyingSet and/or add 'destinations' to the KeyingSets, - * acting as a means by which they can be added outside the Outliner. - */ -void ANIM_OT_keyingset_add_new(struct wmOperatorType *ot); -void ANIM_OT_keyingset_add_destination(struct wmOperatorType *ot); +/* -------- */ /* Main Keyframe Management operators: * These handle keyframes management from various spaces. They only make use of @@ -98,6 +103,53 @@ void ANIM_OT_delete_keyframe_old(struct wmOperatorType *ot); // xxx rename and k void ANIM_OT_insert_keyframe_button(struct wmOperatorType *ot); void ANIM_OT_delete_keyframe_button(struct wmOperatorType *ot); +/* ************ Keying Sets ********************** */ + +/* temporary struct to gather data combos to keyframe + * (is used by modify_keyframes for 'relative' KeyingSets, provided via the dsources arg) + */ +typedef struct bCommonKeySrc { + struct bCommonKeySrc *next, *prev; + + /* general data/destination-source settings */ + struct ID *id; /* id-block this comes from */ + + /* specific cases */ + struct bPoseChannel *pchan; + struct bConstraint *con; +} bCommonKeySrc; + +/* -------- */ + +/* mode for modify_keyframes */ +enum { + MODIFYKEY_MODE_INSERT = 0, + MODIFYKEY_MODE_DELETE, +} eModifyKey_Modes; + +/* Keyframing Helper Call - use the provided Keying Set to Add/Remove Keyframes */ +int modify_keyframes(struct bContext *C, struct ListBase *dsources, struct bAction *act, struct KeyingSet *ks, short mode, float cfra); + +/* -------- */ + +/* Generate menu of KeyingSets */ +char *ANIM_build_keyingsets_menu(struct ListBase *list, short for_edit); + +/* Get the first builtin KeyingSet with the given name, which occurs after the given one (or start of list if none given) */ +struct KeyingSet *ANIM_builtin_keyingset_get_named(struct KeyingSet *prevKS, char name[]); + +/* Initialise builtin KeyingSets on startup */ +void init_builtin_keyingsets(void); + +/* -------- */ + +/* KeyingSet Editing Operators: + * These can add a new KeyingSet and/or add 'destinations' to the KeyingSets, + * acting as a means by which they can be added outside the Outliner. + */ +void ANIM_OT_keyingset_add_new(struct wmOperatorType *ot); +void ANIM_OT_keyingset_add_destination(struct wmOperatorType *ot); + /* ************ Drivers ********************** */ /* Main Driver Management API calls: diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 13dfd9754ab..9e679a5b722 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -410,7 +410,7 @@ static void insert_action_keys(bAnimContext *ac, short mode) /* if there's an id */ if (ale->id) - insertkey(ale->id, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + insert_keyframe(ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); else insert_vert_fcurve(fcu, cfra, fcu->curval, 0); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 56ae3a3e82c..6c7aa1ee49d 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4138,7 +4138,7 @@ void autokeyframe_ob_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode) if (adt && adt->action) { for (fcu= adt->action->curves.first; fcu; fcu= fcu->next) { fcu->flag &= ~FCURVE_SELECTED; - insertkey(id, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + insert_keyframe(id, adt->action, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); } } } @@ -4175,35 +4175,35 @@ void autokeyframe_ob_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode) // TODO: the group names here are temporary... // TODO: should this be made to use the builtin KeyingSets instead? if (doLoc) { - insertkey(id, "Object Transform", "location", 0, cfra, flag); - insertkey(id, "Object Transform", "location", 1, cfra, flag); - insertkey(id, "Object Transform", "location", 2, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "location", 0, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "location", 1, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "location", 2, cfra, flag); } if (doRot) { - insertkey(id, "Object Transform", "rotation", 0, cfra, flag); - insertkey(id, "Object Transform", "rotation", 1, cfra, flag); - insertkey(id, "Object Transform", "rotation", 2, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "rotation", 0, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "rotation", 1, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "rotation", 2, cfra, flag); } if (doScale) { - insertkey(id, "Object Transform", "scale", 0, cfra, flag); - insertkey(id, "Object Transform", "scale", 1, cfra, flag); - insertkey(id, "Object Transform", "scale", 2, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "scale", 0, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "scale", 1, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "scale", 2, cfra, flag); } } else { // TODO: the group names here are temporary... // TODO: should this be made to use the builtin KeyingSets instead? - insertkey(id, "Object Transform", "location", 0, cfra, flag); - insertkey(id, "Object Transform", "location", 1, cfra, flag); - insertkey(id, "Object Transform", "location", 2, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "location", 0, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "location", 1, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "location", 2, cfra, flag); - insertkey(id, "Object Transform", "rotation", 0, cfra, flag); - insertkey(id, "Object Transform", "rotation", 1, cfra, flag); - insertkey(id, "Object Transform", "rotation", 2, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "rotation", 0, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "rotation", 1, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "rotation", 2, cfra, flag); - insertkey(id, "Object Transform", "scale", 0, cfra, flag); - insertkey(id, "Object Transform", "scale", 1, cfra, flag); - insertkey(id, "Object Transform", "scale", 2, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "scale", 0, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "scale", 1, cfra, flag); + insert_keyframe(id, NULL, "Object Transform", "scale", 2, cfra, flag); } // XXX todo... find a way to send notifiers from here... @@ -4248,7 +4248,7 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode, if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { if (act) { for (fcu= act->curves.first; fcu; fcu= fcu->next) - insertkey(id, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + insert_keyframe(id, act, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag); } } /* only insert keyframe if needed? */ @@ -4279,57 +4279,57 @@ void autokeyframe_pose_cb_func(Scene *scene, View3D *v3d, Object *ob, int tmode, if (doLoc) { sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); } if (doRot) { if (pchan->rotmode == PCHAN_ROT_QUAT) { sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); - insertkey(id, pchan->name, buf, 3, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag); } else { sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); } } if (doScale) { sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); } } /* insert keyframe in any channel that's appropriate */ else { sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); if (pchan->rotmode == PCHAN_ROT_QUAT) { sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); - insertkey(id, pchan->name, buf, 3, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 3, cfra, flag); } else { sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); } sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name); - insertkey(id, pchan->name, buf, 0, cfra, flag); - insertkey(id, pchan->name, buf, 1, cfra, flag); - insertkey(id, pchan->name, buf, 2, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 0, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 1, cfra, flag); + insert_keyframe(id, NULL, pchan->name, buf, 2, cfra, flag); } } } |