2.5 PoseLib - First steps to get PoseLib to work in 2.5
authorJoshua Leung <aligorith@gmail.com>
Wed, 15 Apr 2009 01:10:36 +0000 (01:10 +0000)
committerJoshua Leung <aligorith@gmail.com>
Wed, 15 Apr 2009 01:10:36 +0000 (01:10 +0000)
* 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) :)

source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/intern/anim_sys.c
source/blender/editors/animation/anim_intern.h
source/blender/editors/animation/keyframes_edit.c
source/blender/editors/animation/keyframing.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/poselib.c
source/blender/editors/include/ED_keyframes_edit.h
source/blender/editors/include/ED_keyframing.h
source/blender/editors/space_action/action_edit.c
source/blender/editors/transform/transform_conversions.c

index 44c8d827e8c79b69c502bd25c5cd7cb5311de053..70a0cd34a6c71cae50465cfb26e77866161d6b5b 100644 (file)
@@ -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*/
index ebced7837ae2d133ccaa389003cd2262698bd539..c8b2ff716126d9c0fd51505cce2ad66e1ed284ae 100644 (file)
@@ -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);
index 6cbecab783225e2b9c7c85ebfbe5c2f287ab9cd5..e903007fbc039fe8f235d92f72290ead29c7b805 100644 (file)
@@ -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
index 8b83022507d2c39a709a5988ce18e69b7b36df08..bef44448829c038f973613f8356bd8e84bbb5911 100644 (file)
@@ -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 */
 
index 26803f616e4b798b99b01b377b57565d6d846865..c09ac20f91b1cc9d682fa74bb9e3915279c5f78b 100644 (file)
 /* ******************************************* */
 /* 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);
                }
index 63bab10aef3ce74b1c1ef12ef4b186cea111c0b6..e36b3b8a6b149f24a06d9244325a5043cb7ba5c4 100644 (file)
@@ -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 */
index f27bec81d7a16651f4b91e41ee4eba5a949bead3..ca754ed426f90aeb179ee76e5a1ba53dfd07ef1c 100644 (file)
@@ -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"
 #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;
        }
 }
 
index b0dc565bfcc3e58dac59d8f0016695f862d8ff88..44d4e26fea57c5154eb423fe57bcb0302873b5e4 100644 (file)
@@ -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);
index 98a44d3ef2befe36b6530d122fa3c8b2e591911d..fbb469f8d431c32a0a1a1517add25555a7a2d1c3 100644 (file)
@@ -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:
index 13dfd9754ab184daa696512cc14d3f839eb0a740..9e679a5b722abd425873159ae04ae078163e8285 100644 (file)
@@ -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);
        }
index 56ae3a3e82ca22f08e6de8187c9a849608c5153f..6c7aa1ee49d63b21f98b154e3bc3e82cc083e366 100644 (file)
@@ -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);
                                }
                        }
                }