At last... this merge should finally do the trick!
[blender.git] / source / blender / editors / space_action / action_edit.c
index 4775a37e420a77126ad0415115a9483c1279ca24..61dbc41e7c8c2fd4cb8a1d70b2f7982bb7289215 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
-#include "DNA_listBase.h"
+#include "DNA_anim_types.h"
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
 #include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
 #include "DNA_object_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_scene_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
 
 #include "BKE_action.h"
 #include "BKE_depsgraph.h"
-#include "BKE_ipo.h"
+#include "BKE_fcurve.h"
 #include "BKE_key.h"
 #include "BKE_material.h"
+#include "BKE_nla.h"
 #include "BKE_object.h"
 #include "BKE_context.h"
+#include "BKE_report.h"
 #include "BKE_utildefines.h"
 
 #include "UI_view2d.h"
 
+#include "BIF_transform.h"
+
 #include "ED_anim_api.h"
 #include "ED_keyframing.h"
 #include "ED_keyframes_draw.h"
@@ -98,8 +102,8 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
        int filter;
        
        /* get data to filter, from Action or Dopesheet */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* set large values to try to override */
        *min= 999999999.0f;
@@ -107,18 +111,18 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
        
        /* check if any channels to set range with */
        if (anim_data.first) {
-               /* go through channels, finding max extents*/
+               /* go through channels, finding max extents */
                for (ale= anim_data.first; ale; ale= ale->next) {
-                       Object *nob= ANIM_nla_mapping_get(ac, ale);
-                       Ipo *ipo= (Ipo *)ale->key_data; 
+                       AnimData *adt= ANIM_nla_mapping_get(ac, ale);
+                       FCurve *fcu= (FCurve *)ale->key_data;
                        float tmin, tmax;
                        
                        /* get range and apply necessary scaling before */
-                       calc_ipo_range(ipo, &tmin, &tmax);
+                       calc_fcurve_range(fcu, &tmin, &tmax);
                        
-                       if (nob) {
-                               tmin= get_action_frame_inv(nob, tmin);
-                               tmax= get_action_frame_inv(nob, tmax);
+                       if (adt) {
+                               tmin= BKE_nla_tweakedit_remap(adt, tmin, 1);
+                               tmax= BKE_nla_tweakedit_remap(adt, tmax, 1);
                        }
                        
                        /* try to set cur using these values, if they're more extreme than previously set values */
@@ -163,24 +167,25 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *op)
        scene->r.psfra= (int)floor(min + 0.5f);
        scene->r.pefra= (int)floor(max + 0.5f);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       // XXX err... there's nothing for frame ranges yet, but this should do fine too
+       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene); 
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_set_previewrange (wmOperatorType *ot)
+void ACT_OT_previewrange_set (wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Auto-Set Preview Range";
-       ot->idname= "ACT_OT_set_previewrange";
+       ot->idname= "ACT_OT_previewrange_set";
        
        /* api callbacks */
        ot->exec= actkeys_previewrange_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* ****************** View-All Operator ****************** */
@@ -199,7 +204,7 @@ static int actkeys_viewall_exec(bContext *C, wmOperator *op)
        /* set the horizontal range, with an extra offset so that the extreme keys will be in view */
        get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax);
        
-       extra= 0.05f * (v2d->cur.xmax - v2d->cur.xmin);
+       extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin);
        v2d->cur.xmin -= extra;
        v2d->cur.xmax += extra;
        
@@ -210,8 +215,8 @@ static int actkeys_viewall_exec(bContext *C, wmOperator *op)
        /* do View2D syncing */
        UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ED_area_tag_redraw(CTX_wm_area(C));
        
        return OPERATOR_FINISHED;
 }
@@ -224,274 +229,56 @@ void ACT_OT_view_all (wmOperatorType *ot)
        
        /* api callbacks */
        ot->exec= actkeys_viewall_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* ************************************************************************** */
 /* GENERAL STUFF */
 
-// TODO:
-//     - insert key
-
 /* ******************** Copy/Paste Keyframes Operator ************************* */
-/* - The copy/paste buffer currently stores a set of Action Channels, with temporary
- *     IPO-blocks, and also temporary IpoCurves which only contain the selected keyframes.
- * - Only pastes between compatable data is possible (i.e. same achan->name, ipo-curve type, etc.)
- *     Unless there is only one element in the buffer, names are also tested to check for compatability.
- * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
- *     the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
- * - The earliest frame is calculated per copy operation.
- */
-
-/* globals for copy/paste data (like for other copy/paste buffers) */
-ListBase actcopybuf = {NULL, NULL};
-static float actcopy_firstframe= 999999999.0f;
-
-/* This function frees any MEM_calloc'ed copy/paste buffer data */
-// XXX find some header to put this in!
-void free_actcopybuf ()
-{
-       bActionChannel *achan, *anext;
-       bConstraintChannel *conchan, *cnext;
-       
-       for (achan= actcopybuf.first; achan; achan= anext) {
-               anext= achan->next;
-               
-               if (achan->ipo) {
-                       free_ipo(achan->ipo);
-                       MEM_freeN(achan->ipo);
-               }
-               
-               for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) {
-                       cnext= conchan->next;
-                       
-                       if (conchan->ipo) {
-                               free_ipo(conchan->ipo);
-                               MEM_freeN(conchan->ipo);
-                       }
-                       
-                       BLI_freelinkN(&achan->constraintChannels, conchan);
-               }
-               
-               BLI_freelinkN(&actcopybuf, achan);
-       }
-       
-       actcopybuf.first= actcopybuf.last= NULL;
-       actcopy_firstframe= 999999999.0f;
-}
+/* NOTE: the backend code for this is shared with the graph editor */
 
-/* ------------------- */
-
-/* This function adds data to the copy/paste buffer, freeing existing data first
- * Only the selected action channels gets their selected keyframes copied.
- */
 static short copy_action_keys (bAnimContext *ac)
-{
+{      
        ListBase anim_data = {NULL, NULL};
-       bAnimListElem *ale;
-       int filter;
+       int filter, ok=0;
        
        /* clear buffer first */
-       free_actcopybuf();
+       free_anim_copybuf();
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
-       
-       /* assume that each of these is an ipo-block */
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               bActionChannel *achan;
-               Ipo *ipo= ale->key_data;
-               Ipo *ipn;
-               IpoCurve *icu, *icn;
-               BezTriple *bezt;
-               int i;
-               
-               /* coerce an action-channel out of owner */
-               if (ale->ownertype == ANIMTYPE_ACHAN) {
-                       bActionChannel *achanO= ale->owner;
-                       achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
-                       strcpy(achan->name, achanO->name);
-               }
-               else if (ale->ownertype == ANIMTYPE_SHAPEKEY) {
-                       achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
-                       strcpy(achan->name, "#ACP_ShapeKey");
-               }
-               else
-                       continue;
-               BLI_addtail(&actcopybuf, achan);
-               
-               /* add constraint channel if needed, then add new ipo-block */
-               if (ale->type == ANIMTYPE_CONCHAN) {
-                       bConstraintChannel *conchanO= ale->data;
-                       bConstraintChannel *conchan;
-                       
-                       conchan= MEM_callocN(sizeof(bConstraintChannel), "ActCopyPasteConchan");
-                       strcpy(conchan->name, conchanO->name);
-                       BLI_addtail(&achan->constraintChannels, conchan);
-                       
-                       conchan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
-               }
-               else {
-                       achan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
-               }
-               ipn->blocktype = ipo->blocktype;
-               
-               /* now loop through curves, and only copy selected keyframes */
-               for (icu= ipo->curve.first; icu; icu= icu->next) {
-                       /* allocate a new curve */
-                       icn= MEM_callocN(sizeof(IpoCurve), "ActCopyPasteIcu");
-                       icn->blocktype = icu->blocktype;
-                       icn->adrcode = icu->adrcode;
-                       BLI_addtail(&ipn->curve, icn);
-                       
-                       /* find selected BezTriples to add to the buffer (and set first frame) */
-                       for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
-                               if (BEZSELECTED(bezt)) {
-                                       /* add to buffer ipo-curve */
-                                       insert_bezt_icu(icn, bezt);
-                                       
-                                       /* check if this is the earliest frame encountered so far */
-                                       if (bezt->vec[1][0] < actcopy_firstframe)
-                                               actcopy_firstframe= bezt->vec[1][0];
-                               }
-                       }
-               }
-       }
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
-       /* check if anything ended up in the buffer */
-       if (ELEM(NULL, actcopybuf.first, actcopybuf.last))
-       //      error("Nothing copied to buffer");
-               return -1;
+       /* copy keyframes */
+       ok= copy_animedit_keys(ac, &anim_data);
        
-       /* free temp memory */
+       /* clean up */
        BLI_freelistN(&anim_data);
-       
-       /* everything went fine */
-       return 0;
+
+       return ok;
 }
 
+
 static short paste_action_keys (bAnimContext *ac)
-{
+{      
        ListBase anim_data = {NULL, NULL};
-       bAnimListElem *ale;
-       int filter;
-       
-       const Scene *scene= (ac->scene);
-       const float offset = (float)(CFRA - actcopy_firstframe);
-       char *actname = NULL, *conname = NULL;
-       short no_name= 0;
-       
-       /* check if buffer is empty */
-       if (ELEM(NULL, actcopybuf.first, actcopybuf.last)) {
-               //error("No data in buffer to paste");
-               return -1;
-       }
-       /* check if single channel in buffer (disregard names if so)  */
-       if (actcopybuf.first == actcopybuf.last)
-               no_name= 1;
+       int filter, ok=0;
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
-       /* from selected channels */
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               Ipo *ipo_src = NULL;
-               bActionChannel *achan;
-               IpoCurve *ico, *icu;
-               BezTriple *bezt;
-               int i;
-               
-               /* find suitable IPO-block from buffer to paste from */
-               for (achan= actcopybuf.first; achan; achan= achan->next) {
-                       /* try to match data */
-                       if (ale->ownertype == ANIMTYPE_ACHAN) {
-                               bActionChannel *achant= ale->owner;
-                               
-                               /* check if we have a corresponding action channel */
-                               if ((no_name) || (strcmp(achan->name, achant->name)==0)) {
-                                       actname= achant->name;
-                                       
-                                       /* check if this is a constraint channel */
-                                       if (ale->type == ANIMTYPE_CONCHAN) {
-                                               bConstraintChannel *conchant= ale->data;
-                                               bConstraintChannel *conchan;
-                                               
-                                               for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
-                                                       if (strcmp(conchan->name, conchant->name)==0) {
-                                                               conname= conchant->name;
-                                                               ipo_src= conchan->ipo;
-                                                               break;
-                                                       }
-                                               }
-                                               if (ipo_src) break;
-                                       }
-                                       else {
-                                               ipo_src= achan->ipo;
-                                               break;
-                                       }
-                               }
-                       }
-                       else if (ale->ownertype == ANIMTYPE_SHAPEKEY) {
-                               /* check if this action channel is "#ACP_ShapeKey" */
-                               if ((no_name) || (strcmp(achan->name, "#ACP_ShapeKey")==0)) {
-                                       actname= NULL;
-                                       ipo_src= achan->ipo;
-                                       break;
-                               }
-                       }       
-               }
-               
-               /* this shouldn't happen, but it might */
-               if (ipo_src == NULL)
-                       continue;
-               
-               /* loop over curves, pasting keyframes */
-               for (ico= ipo_src->curve.first; ico; ico= ico->next) {
-                       /* get IPO-curve to paste to (IPO-curve might not exist for destination, so gets created) */
-                       icu= verify_ipocurve(ale->id, ico->blocktype, actname, conname, NULL, ico->adrcode, 1);
-                       
-                       if (icu) {
-                               /* just start pasting, with the the first keyframe on the current frame, and so on */
-                               for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) {                                              
-                                       /* temporarily apply offset to src beztriple while copying */
-                                       bezt->vec[0][0] += offset;
-                                       bezt->vec[1][0] += offset;
-                                       bezt->vec[2][0] += offset;
-                                       
-                                       /* insert the keyframe */
-                                       insert_bezt_icu(icu, bezt);
-                                       
-                                       /* un-apply offset from src beztriple after copying */
-                                       bezt->vec[0][0] -= offset;
-                                       bezt->vec[1][0] -= offset;
-                                       bezt->vec[2][0] -= offset;
-                               }
-                               
-                               /* recalculate channel's handles? */
-                               calchandles_ipocurve(icu);
-                       }
-               }
-       }
+       /* paste keyframes */
+       ok= paste_animedit_keys(ac, &anim_data);
        
-       /* free temp memory */
+       /* clean up */
        BLI_freelistN(&anim_data);
-       
-       /* do depsgraph updates (for 3d-view)? */
-#if 0
-       if ((ob) && (G.saction->pin==0)) {
-               if (ob->type == OB_ARMATURE)
-                       DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
-               else
-                       DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
-       }
-#endif
 
-       return 0;
+       return ok;
 }
 
 /* ------------------- */
@@ -510,29 +297,29 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
        }
        else {
                if (copy_action_keys(&ac)) {    
-                       // XXX errors - need a way to inform the user 
-                       printf("Action Copy: No keyframes copied to copy-paste buffer\n");
+                       BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
+                       return OPERATOR_CANCELLED;
                }
        }
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_copy (wmOperatorType *ot)
+void ACT_OT_copy (wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Copy Keyframes";
-       ot->idname= "ACT_OT_keyframes_copy";
+       ot->idname= "ACT_OT_copy";
        
        /* api callbacks */
        ot->exec= actkeys_copy_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 
@@ -551,32 +338,209 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
        }
        else {
                if (paste_action_keys(&ac)) {
-                       // XXX errors - need a way to inform the user 
-                       printf("Action Paste: Nothing to paste, as Copy-Paste buffer was empty.\n");
+                       BKE_report(op->reports, RPT_ERROR, "No keyframes to paste");
+                       return OPERATOR_CANCELLED;
                }
        }
        
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_paste (wmOperatorType *ot)
+void ACT_OT_paste (wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Paste Keyframes";
-       ot->idname= "ACT_OT_keyframes_paste";
+       ot->idname= "ACT_OT_paste";
        
        /* api callbacks */
        ot->exec= actkeys_paste_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ******************** Insert Keyframes Operator ************************* */
+
+/* defines for insert keyframes tool */
+EnumPropertyItem prop_actkeys_insertkey_types[] = {
+       {1, "ALL", 0, "All Channels", ""},
+       {2, "SEL", 0, "Only Selected Channels", ""},
+       {3, "GROUP", 0, "In Active Group", ""}, // xxx not in all cases
+       {0, NULL, 0, NULL, NULL}
+};
+
+/* this function is responsible for snapping keyframes to frame-times */
+static void insert_action_keys(bAnimContext *ac, short mode) 
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       Scene *scene= ac->scene;
+       float cfra= (float)CFRA;
+       short flag = 0;
+       
+       /* filter data */
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       if (mode == 2)                  filter |= ANIMFILTER_SEL;
+       else if (mode == 3)     filter |= ANIMFILTER_ACTGROUPED;
+       
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       /* init keyframing flag */
+       if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
+       if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
+       // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
+       
+       /* insert keyframes */
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               AnimData *adt= ANIM_nla_mapping_get(ac, ale);
+               FCurve *fcu= (FCurve *)ale->key_data;
+               
+               /* adjust current frame for NLA-scaling */
+               if (adt)
+                       cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
+               else 
+                       cfra= (float)CFRA;
+                       
+               /* if there's an id */
+               if (ale->id)
+                       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);
+       }
+       
+       BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       short mode;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       if (ac.datatype == ANIMCONT_GPENCIL)
+               return OPERATOR_CANCELLED;
+               
+       /* get snapping mode */
+       mode= RNA_enum_get(op->ptr, "type");
+       
+       /* snap keyframes */
+       insert_action_keys(&ac, mode);
+       
+       /* validate keyframes after editing */
+       ANIM_editkeyframes_refresh(&ac);
+       
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ACT_OT_insert (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Insert Keyframes";
+       ot->idname= "ACT_OT_insert";
+       
+       /* api callbacks */
+       ot->invoke= WM_menu_invoke;
+       ot->exec= actkeys_insertkey_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* id-props */
+       RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
+}
+
+/* ******************** Duplicate Keyframes Operator ************************* */
+
+static void duplicate_action_keys (bAnimContext *ac)
+{
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       /* filter data */
+       if (ac->datatype == ANIMCONT_GPENCIL)
+               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
+       else
+               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       /* loop through filtered data and delete selected keys */
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               //if (ale->type == ANIMTYPE_GPLAYER)
+               //      delete_gplayer_frames((bGPDlayer *)ale->data);
+               //else
+                       duplicate_fcurve_keys((FCurve *)ale->key_data);
+       }
+       
+       /* free filtered list */
+       BLI_freelistN(&anim_data);
+}
+
+/* ------------------- */
+
+static int actkeys_duplicate_exec(bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+               
+       /* duplicate keyframes */
+       duplicate_action_keys(&ac);
+       
+       /* validate keyframes after editing */
+       ANIM_editkeyframes_refresh(&ac);
+       
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
+       
+       return OPERATOR_FINISHED; // xxx - start transform
+}
+
+static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       actkeys_duplicate_exec(C, op);
+       
+       RNA_int_set(op->ptr, "mode", TFM_TIME_TRANSLATE);
+       WM_operator_name_call(C, "TFM_OT_transform", WM_OP_INVOKE_REGION_WIN, op->ptr);
+
+       return OPERATOR_FINISHED;
+}
+void ACT_OT_duplicate (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Duplicate Keyframes";
+       ot->idname= "ACT_OT_duplicate";
+       
+       /* api callbacks */
+       ot->invoke= actkeys_duplicate_invoke;
+       ot->exec= actkeys_duplicate_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* to give to transform */
+       RNA_def_int(ot->srna, "mode", TFM_TIME_TRANSLATE, 0, INT_MAX, "Mode", "", 0, INT_MAX);
 }
 
 /* ******************** Delete Keyframes Operator ************************* */
@@ -591,15 +555,15 @@ static void delete_action_keys (bAnimContext *ac)
        if (ac->datatype == ANIMCONT_GPENCIL)
                filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through filtered data and delete selected keys */
        for (ale= anim_data.first; ale; ale= ale->next) {
                //if (ale->type == ANIMTYPE_GPLAYER)
                //      delete_gplayer_frames((bGPDlayer *)ale->data);
                //else
-                       delete_ipo_keys((Ipo *)ale->key_data);
+                       delete_fcurve_keys((FCurve *)ale->key_data); // XXX... this doesn't delete empty curves anymore
        }
        
        /* free filtered list */
@@ -622,24 +586,25 @@ static int actkeys_delete_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_delete (wmOperatorType *ot)
+void ACT_OT_delete (wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Delete Keyframes";
-       ot->idname= "ACT_OT_keyframes_delete";
+       ot->idname= "ACT_OT_delete";
        
        /* api callbacks */
+       ot->invoke= WM_operator_confirm;
        ot->exec= actkeys_delete_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* ******************** Clean Keyframes Operator ************************* */
@@ -651,12 +616,12 @@ static void clean_action_keys (bAnimContext *ac, float thresh)
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_ONLYICU);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through filtered data and clean curves */
        for (ale= anim_data.first; ale; ale= ale->next)
-               clean_ipo_curve((IpoCurve *)ale->key_data, thresh);
+               clean_fcurve((FCurve *)ale->key_data, thresh);
        
        /* free temp data */
        BLI_freelistN(&anim_data);
@@ -684,31 +649,28 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_clean (wmOperatorType *ot)
+void ACT_OT_clean (wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Clean Keyframes";
-       ot->idname= "ACT_OT_keyframes_clean";
+       ot->idname= "ACT_OT_clean";
        
        /* api callbacks */
        //ot->invoke=  // XXX we need that number popup for this! 
        ot->exec= actkeys_clean_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* properties */
-       prop= RNA_def_property(ot->srna, "threshold", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_default(prop, 0.001f);
+       RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
 }
 
 /* ******************** Sample Keyframes Operator *********************** */
@@ -726,19 +688,19 @@ static void sample_action_keys (bAnimContext *ac)
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ONLYICU);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through filtered data and add keys between selected keyframes on every frame  */
        for (ale= anim_data.first; ale; ale= ale->next) {
-               IpoCurve *icu= (IpoCurve *)ale->key_data;
+               FCurve *fcu= (FCurve *)ale->key_data;
                BezTriple *bezt, *start=NULL, *end=NULL;
                tempFrameValCache *value_cache, *fp;
                int sfra, range;
                int i, n;
                
                /* find selected keyframes... once pair has been found, add keyframes  */
-               for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
+               for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
                        /* check if selected, and which end this is */
                        if (BEZSELECTED(bezt)) {
                                if (start) {
@@ -757,19 +719,19 @@ static void sample_action_keys (bAnimContext *ac)
                                                /*      sample values   */
                                                for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
                                                        fp->frame= (float)(sfra + n);
-                                                       fp->val= eval_icu(icu, fp->frame);
+                                                       fp->val= evaluate_fcurve(fcu, fp->frame);
                                                }
                                                
                                                /*      add keyframes with these        */
                                                for (n=0, fp=value_cache; n<range && fp; n++, fp++) {
-                                                       insert_vert_icu(icu, fp->frame, fp->val, 1);
+                                                       insert_vert_fcurve(fcu, fp->frame, fp->val, 1);
                                                }
                                                
                                                /* free temp cache */
                                                MEM_freeN(value_cache);
                                                
                                                /* as we added keyframes, we need to compensate so that bezt is at the right place */
-                                               bezt = icu->bezt + i + range - 1;
+                                               bezt = fcu->bezt + i + range - 1;
                                                i += (range - 1);
                                        }
                                        
@@ -786,7 +748,7 @@ static void sample_action_keys (bAnimContext *ac)
                }
                
                /* recalculate channel's handles? */
-               calchandles_ipocurve(icu);
+               calchandles_fcurve(fcu);
        }
        
        /* admin and redraws */
@@ -811,24 +773,24 @@ static int actkeys_sample_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_sample (wmOperatorType *ot)
+void ACT_OT_sample (wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Sample Keyframes";
-       ot->idname= "ACT_OT_keyframes_sample";
+       ot->idname= "ACT_OT_sample";
        
        /* api callbacks */
        ot->exec= actkeys_sample_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* ************************************************************************** */
@@ -838,11 +800,9 @@ void ACT_OT_keyframes_sample (wmOperatorType *ot)
 
 /* defines for set extrapolation-type for selected keyframes tool */
 EnumPropertyItem prop_actkeys_expo_types[] = {
-       {IPO_HORIZ, "CONSTANT", "Constant", ""},
-       {IPO_DIR, "DIRECTIONAL", "Extrapolation", ""},
-       {IPO_CYCL, "CYCLIC", "Cyclic", ""},
-       {IPO_CYCLX, "CYCLIC_EXTRAPOLATION", "Cyclic Extrapolation", ""},
-       {0, NULL, NULL, NULL}
+       {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", ""},
+       {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", ""},
+       {0, NULL, 0, NULL, NULL}
 };
 
 /* this function is responsible for setting extrapolation mode for keyframes */
@@ -853,12 +813,14 @@ static void setexpo_action_keys(bAnimContext *ac, short mode)
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
-       /* loop through setting mode per ipo-curve */
-       for (ale= anim_data.first; ale; ale= ale->next)
-               setexprap_ipoloop(ale->key_data, mode);
+       /* loop through setting mode per F-Curve */
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               FCurve *fcu= (FCurve *)ale->data;
+               fcu->extend= mode;
+       }
        
        /* cleanup */
        BLI_freelistN(&anim_data);
@@ -886,43 +848,32 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_expotype (wmOperatorType *ot)
+void ACT_OT_extrapolation_type (wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Set Keyframe Extrapolation";
-       ot->idname= "ACT_OT_keyframes_expotype";
+       ot->idname= "ACT_OT_extrapolation_type";
        
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
        ot->exec= actkeys_expo_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_items(prop, prop_actkeys_expo_types);
+       RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
 }
 
 /* ******************** Set Interpolation-Type Operator *********************** */
 
-/* defines for set ipo-type for selected keyframes tool */
-EnumPropertyItem prop_actkeys_ipo_types[] = {
-       {IPO_CONST, "CONSTANT", "Constant Interpolation", ""},
-       {IPO_LIN, "LINEAR", "Linear Interpolation", ""},
-       {IPO_BEZ, "BEZIER", "Bezier Interpolation", ""},
-       {0, NULL, NULL, NULL}
-};
-
 /* this function is responsible for setting interpolation mode for keyframes */
 static void setipo_action_keys(bAnimContext *ac, short mode) 
 {
@@ -932,14 +883,14 @@ static void setipo_action_keys(bAnimContext *ac, short mode)
        BeztEditFunc set_cb= ANIM_editkeyframes_ipo(mode);
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through setting BezTriple interpolation
         * Note: we do not supply BeztEditData to the looper yet. Currently that's not necessary here...
         */
        for (ale= anim_data.first; ale; ale= ale->next)
-               ipo_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, ANIM_editkeyframes_ipocurve_ipotype);
+               ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
        
        /* cleanup */
        BLI_freelistN(&anim_data);
@@ -967,45 +918,32 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_ipotype (wmOperatorType *ot)
+void ACT_OT_interpolation_type (wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Set Keyframe Interpolation";
-       ot->idname= "ACT_OT_keyframes_ipotype";
+       ot->idname= "ACT_OT_interpolation_type";
        
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
        ot->exec= actkeys_ipo_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_items(prop, prop_actkeys_ipo_types);
+       RNA_def_enum(ot->srna, "type", beztriple_interpolation_mode_items, 0, "Type", "");
 }
 
 /* ******************** Set Handle-Type Operator *********************** */
 
-/* defines for set handle-type for selected keyframes tool */
-EnumPropertyItem prop_actkeys_handletype_types[] = {
-       {HD_AUTO, "AUTO", "Auto Handles", ""},
-       {HD_VECT, "VECTOR", "Vector Handles", ""},
-       {HD_FREE, "FREE", "Free Handles", ""},
-       {HD_ALIGN, "ALIGN", "Aligned Handles", ""},
-//     {-1, "TOGGLE", "Toggle between Free and Aligned Handles", ""},
-       {0, NULL, NULL, NULL}
-};
-
 /* this function is responsible for setting handle-type of selected keyframes */
 static void sethandles_action_keys(bAnimContext *ac, short mode) 
 {
@@ -1015,8 +953,8 @@ static void sethandles_action_keys(bAnimContext *ac, short mode)
        BeztEditFunc set_cb= ANIM_editkeyframes_handles(mode);
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through setting flags for handles 
         * Note: we do not supply BeztEditData to the looper yet. Currently that's not necessary here...
@@ -1028,17 +966,17 @@ static void sethandles_action_keys(bAnimContext *ac, short mode)
                        /* check which type of handle to set (free or aligned) 
                         *      - check here checks for handles with free alignment already
                         */
-                       if (ipo_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, NULL))
+                       if (ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, NULL))
                                toggle_cb= ANIM_editkeyframes_handles(HD_FREE);
                        else
                                toggle_cb= ANIM_editkeyframes_handles(HD_ALIGN);
                                
                        /* set handle-type */
-                       ipo_keys_bezier_loop(NULL, ale->key_data, NULL, toggle_cb, calchandles_ipocurve);
+                       ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, toggle_cb, calchandles_fcurve);
                }
                else {
                        /* directly set handle-type */
-                       ipo_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_ipocurve);
+                       ANIM_fcurve_keys_bezier_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
                }
        }
        
@@ -1068,56 +1006,37 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_handletype (wmOperatorType *ot)
+void ACT_OT_handle_type (wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Set Keyframe Handle Type";
-       ot->idname= "ACT_OT_keyframes_handletype";
+       ot->idname= "ACT_OT_handle_type";
        
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
        ot->exec= actkeys_handletype_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_items(prop, prop_actkeys_handletype_types);
+       RNA_def_enum(ot->srna, "type", beztriple_handle_type_items, 0, "Type", "");
 }
 
 /* ************************************************************************** */
 /* TRANSFORM STUFF */
 
-/* ***************** Snap Current Frame Operator *********************** */
-
-/* helper callback for actkeys_cfrasnap_exec() -> used to help get the average time of all selected beztriples */
-// TODO: if some other code somewhere needs this, it'll be time to port this over to keyframes_edit.c!!!
-static short bezt_calc_average(BeztEditData *bed, BezTriple *bezt)
-{
-       /* only if selected */
-       if (bezt->f2 & SELECT) {
-               /* store average time in float (only do rounding at last step */
-               bed->f1 += bezt->vec[1][0];
-               
-               /* increment number of items */
-               bed->i1++;
-       }
-       
-       return 0;
-}
+/* ***************** Jump to Selected Frames Operator *********************** */
 
 /* snap current-frame indicator to 'average time' of selected keyframe */
-static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
+static int actkeys_framejump_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
        ListBase anim_data= {NULL, NULL};
@@ -1133,11 +1052,20 @@ static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
        memset(&bed, 0, sizeof(BeztEditData));
        
        /* loop over action data, averaging values */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac.data, ac.datatype);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
        
-       for (ale= anim_data.first; ale; ale= ale->next)
-               ipo_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
+               
+               if (adt) {
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 
+                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
+               }
+               else
+                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_calc_average, NULL);
+       }
        
        BLI_freelistN(&anim_data);
        
@@ -1147,35 +1075,35 @@ static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
                CFRA= (int)floor((bed.f1 / bed.i1) + 0.5f);
        }
        
-       /* set notifier tha things have changed */
+       /* set notifier that things have changed */
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene);
        
        return OPERATOR_FINISHED;
 }
 
-void ACT_OT_keyframes_cfrasnap (wmOperatorType *ot)
+void ACT_OT_frame_jump (wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Snap Current Frame to Keys";
-       ot->idname= "ACT_OT_keyframes_cfrasnap";
+       ot->name= "Jump to Frame";
+       ot->idname= "ACT_OT_frame_jump";
        
        /* api callbacks */
-       ot->exec= actkeys_cfrasnap_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->exec= actkeys_framejump_exec;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* ******************** Snap Keyframes Operator *********************** */
 
 /* defines for snap keyframes tool */
 EnumPropertyItem prop_actkeys_snap_types[] = {
-       {ACTKEYS_SNAP_CFRA, "CFRA", "Current frame", ""},
-       {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", "Nearest Frame", ""}, // XXX as single entry?
-       {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", "Nearest Second", ""}, // XXX as single entry?
-       {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", "Nearest Marker", ""},
-       {0, NULL, NULL, NULL}
+       {ACTKEYS_SNAP_CFRA, "CFRA", 0, "Current frame", ""},
+       {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry?
+       {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry?
+       {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""},
+       {0, NULL, 0, NULL, NULL}
 };
 
 /* this function is responsible for snapping keyframes to frame-times */
@@ -1192,28 +1120,32 @@ static void snap_action_keys(bAnimContext *ac, short mode)
        if (ac->datatype == ANIMCONT_GPENCIL)
                filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* get beztriple editing callbacks */
        edit_cb= ANIM_editkeyframes_snap(mode);
        
        memset(&bed, 0, sizeof(BeztEditData)); 
        bed.scene= ac->scene;
+       if (mode == ACTKEYS_SNAP_NEAREST_MARKER) {
+               bed.list.first= (ac->markers) ? ac->markers->first : NULL;
+               bed.list.last= (ac->markers) ? ac->markers->last : NULL;
+       }
        
        /* snap keyframes */
        for (ale= anim_data.first; ale; ale= ale->next) {
-               Object *nob= ANIM_nla_mapping_get(ac, ale);
+               AnimData *adt= ANIM_nla_mapping_get(ac, ale);
                
-               if (nob) {
-                       ANIM_nla_mapping_apply(nob, ale->key_data, 0, 1); 
-                       ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
-                       ANIM_nla_mapping_apply(nob, ale->key_data, 1, 1);
+               if (adt) {
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 
+                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
                //else if (ale->type == ACTTYPE_GPLAYER)
                //      snap_gplayer_frames(ale->data, mode);
                else 
-                       ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
+                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
        }
        BLI_freelistN(&anim_data);
 }
@@ -1238,42 +1170,39 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_snap (wmOperatorType *ot)
+void ACT_OT_snap (wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Snap Keys";
-       ot->idname= "ACT_OT_keyframes_snap";
+       ot->idname= "ACT_OT_snap";
        
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
        ot->exec= actkeys_snap_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_items(prop, prop_actkeys_snap_types);
+       RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
 }
 
 /* ******************** Mirror Keyframes Operator *********************** */
 
 /* defines for mirror keyframes tool */
 EnumPropertyItem prop_actkeys_mirror_types[] = {
-       {ACTKEYS_MIRROR_CFRA, "CFRA", "Current frame", ""},
-       {ACTKEYS_MIRROR_YAXIS, "YAXIS", "Vertical Axis", ""},
-       {ACTKEYS_MIRROR_XAXIS, "XAXIS", "Horizontal Axis", ""},
-       {ACTKEYS_MIRROR_MARKER, "MARKER", "First Selected Marker", ""},
-       {0, NULL, NULL, NULL}
+       {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "Current frame", ""},
+       {ACTKEYS_MIRROR_YAXIS, "YAXIS", 0, "Vertical Axis", ""},
+       {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "Horizontal Axis", ""},
+       {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "First Selected Marker", ""},
+       {0, NULL, 0, NULL, NULL}
 };
 
 /* this function is responsible for mirroring keyframes */
@@ -1295,13 +1224,14 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
        /* for 'first selected marker' mode, need to find first selected marker first! */
        // XXX should this be made into a helper func in the API?
        if (mode == ACTKEYS_MIRROR_MARKER) {
-               Scene *scene= ac->scene;
                TimeMarker *marker= NULL;
                
                /* find first selected marker */
-               for (marker= scene->markers.first; marker; marker=marker->next) {
-                       if (marker->flag & SELECT) {
-                               break;
+               if (ac->markers) {
+                       for (marker= ac->markers->first; marker; marker=marker->next) {
+                               if (marker->flag & SELECT) {
+                                       break;
+                               }
                        }
                }
                
@@ -1316,22 +1246,22 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
        if (ac->datatype == ANIMCONT_GPENCIL)
                filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
-       ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
+               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* mirror keyframes */
        for (ale= anim_data.first; ale; ale= ale->next) {
-               Object *nob= ANIM_nla_mapping_get(ac, ale);
+               AnimData *adt= ANIM_nla_mapping_get(ac, ale);
                
-               if (nob) {
-                       ANIM_nla_mapping_apply(nob, ale->key_data, 0, 1); 
-                       ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
-                       ANIM_nla_mapping_apply(nob, ale->key_data, 1, 1);
+               if (adt) {
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 
+                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
                //else if (ale->type == ACTTYPE_GPLAYER)
                //      snap_gplayer_frames(ale->data, mode);
                else 
-                       ipo_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_ipocurve);
+                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, edit_cb, calchandles_fcurve);
        }
        BLI_freelistN(&anim_data);
 }
@@ -1356,31 +1286,28 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
-       ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
+       /* set notifier that things have changed */
+       ANIM_animdata_send_notifiers(C, &ac, ANIM_CHANGED_KEYFRAMES_VALUES);
        
        return OPERATOR_FINISHED;
 }
  
-void ACT_OT_keyframes_mirror (wmOperatorType *ot)
+void ACT_OT_mirror (wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Mirror Keys";
-       ot->idname= "ACT_OT_keyframes_mirror";
+       ot->idname= "ACT_OT_mirror";
        
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
        ot->exec= actkeys_mirror_exec;
-       ot->poll= ED_operator_areaactive;
+       ot->poll= ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       prop= RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_items(prop, prop_actkeys_mirror_types);
+       RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
 }
 
 /* ************************************************************************** */