Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-04-15 05:10:36 +0400
committerJoshua Leung <aligorith@gmail.com>2009-04-15 05:10:36 +0400
commit2dbf73f6a032ab44539cfd8c05f5743fbaf33902 (patch)
tree2a3093dfa8b561213db1c58bf2583cb05f6b2ed5 /source
parent5b3d7bfdf6305e880f89d58cbe852a8d2ba7b241 (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')
-rw-r--r--source/blender/blenkernel/BKE_animsys.h21
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c28
-rw-r--r--source/blender/editors/animation/anim_intern.h22
-rw-r--r--source/blender/editors/animation/keyframes_edit.c30
-rw-r--r--source/blender/editors/animation/keyframing.c64
-rw-r--r--source/blender/editors/animation/keyingsets.c36
-rw-r--r--source/blender/editors/armature/poselib.c195
-rw-r--r--source/blender/editors/include/ED_keyframes_edit.h5
-rw-r--r--source/blender/editors/include/ED_keyframing.h82
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/transform/transform_conversions.c92
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);
}
}
}