At last... this merge should finally do the trick!
[blender.git] / source / blender / editors / space_action / action_edit.c
index d618d2869c8582d6ad1f3d80949796d4bd71665c..61dbc41e7c8c2fd4cb8a1d70b2f7982bb7289215 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
 
 #include "RNA_access.h"
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
 
 #include "BKE_action.h"
 #include "BKE_depsgraph.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"
@@ -108,17 +113,16 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max)
        if (anim_data.first) {
                /* go through channels, finding max extents */
                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);
                        FCurve *fcu= (FCurve *)ale->key_data;
                        float tmin, tmax;
                        
                        /* get range and apply necessary scaling before */
                        calc_fcurve_range(fcu, &tmin, &tmax);
-                       tmin= tmax= 0.0f; // xxx
                        
-                       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 */
@@ -170,18 +174,18 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *op)
        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 ****************** */
@@ -200,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;
        
@@ -225,265 +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;
+/* NOTE: the backend code for this is shared with the graph editor */
 
-/* This function frees any MEM_calloc'ed copy/paste buffer data */
-// XXX find some header to put this in!
-void free_actcopybuf ()
-{
-       FCurve *fcu, *fcn;
-       
-       /* free_fcurve() frees F-Curve memory too, but we don't need to do remlink first, as we're freeing all 
-        * channels anyway, and the freeing func only cares about the data it's given
-        */
-       for (fcu= actcopybuf.first; fcu; fcu= fcn) {
-               fcn= fcu->next;
-               free_fcurve(fcu);
-       }
-       
-       actcopybuf.first= actcopybuf.last= NULL;
-       actcopy_firstframe= 999999999.0f;
-}
-
-/* ------------------- */
-
-/* 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)
 {      
-#if 0 // XXX old animation system
        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);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
        ANIM_animdata_filter(ac, &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); // XXX
-                                       
-                                       /* check if this is the earliest frame encountered so far */
-                                       if (bezt->vec[1][0] < actcopy_firstframe)
-                                               actcopy_firstframe= bezt->vec[1][0];
-                               }
-                       }
-               }
-       }
-       
-       /* 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);
-#endif // XXX old animation system
-       
-       /* everything went fine */
-       return 0;
+
+       return ok;
 }
 
+
 static short paste_action_keys (bAnimContext *ac)
-{
-#if 0 // XXX old animation system
+{      
        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);
+       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); // XXX
-                                       
-                                       /* 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_fcurve(fcu);
-                       }
-               }
-       }
+       /* 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
 
-#endif // XXX old animation system
-
-       return 0;
+       return ok;
 }
 
 /* ------------------- */
@@ -502,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 */
+       /* 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;
 }
 
 
@@ -543,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 */
+       /* 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;
+}
+
+/* ******************** 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*/;
+       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 ************************* */
@@ -614,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 */
+       /* 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 ************************* */
@@ -676,25 +649,25 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
+       /* 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)
 {
        /* 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 */
        RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
@@ -800,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 */
+       /* 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;
 }
 
 /* ************************************************************************** */
@@ -825,13 +798,11 @@ void ACT_OT_keyframes_sample (wmOperatorType *ot)
 
 /* ******************** Set Extrapolation-Type Operator *********************** */
 
-// XXX rename this operator...
-
 /* defines for set extrapolation-type for selected keyframes tool */
 EnumPropertyItem prop_actkeys_expo_types[] = {
-       {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", "Constant Extrapolation", ""},
-       {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", "Linear 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 */
@@ -877,25 +848,25 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
+       /* 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)
 {
        /* 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 */
        RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
@@ -903,14 +874,6 @@ void ACT_OT_keyframes_expotype (wmOperatorType *ot)
 
 /* ******************** Set Interpolation-Type Operator *********************** */
 
-/* defines for set ipo-type for selected keyframes tool */
-EnumPropertyItem prop_actkeys_ipo_types[] = {
-       {BEZT_IPO_CONST, "CONSTANT", "Constant Interpolation", ""},
-       {BEZT_IPO_LIN, "LINEAR", "Linear Interpolation", ""},
-       {BEZT_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) 
 {
@@ -955,42 +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 */
+       /* 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)
 {
        /* 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 */
-       RNA_def_enum(ot->srna, "type", prop_actkeys_ipo_types, 0, "Type", "");
+       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) 
 {
@@ -1053,53 +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 */
+       /* 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)
 {
        /* 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 */
-       RNA_def_enum(ot->srna, "type", prop_actkeys_handletype_types, 0, "Type", "");
+       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};
@@ -1118,8 +1055,17 @@ static int actkeys_cfrasnap_exec(bContext *C, wmOperator *op)
        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)
-               ANIM_fcurve_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);
        
@@ -1129,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 */
@@ -1182,15 +1128,19 @@ static void snap_action_keys(bAnimContext *ac, short 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_fcurve(nob, ale->key_data, 0, 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(nob, ale->key_data, 1, 1);
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
                //else if (ale->type == ACTTYPE_GPLAYER)
                //      snap_gplayer_frames(ale->data, mode);
@@ -1220,25 +1170,25 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
+       /* 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)
 {
        /* 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 */
        RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
@@ -1248,11 +1198,11 @@ void ACT_OT_keyframes_snap (wmOperatorType *ot)
 
 /* 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 */
@@ -1274,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;
+                               }
                        }
                }
                
@@ -1300,12 +1251,12 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
        
        /* 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_fcurve(nob, ale->key_data, 0, 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(nob, ale->key_data, 1, 1);
+                       ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
                //else if (ale->type == ACTTYPE_GPLAYER)
                //      snap_gplayer_frames(ale->data, mode);
@@ -1335,25 +1286,25 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
        /* validate keyframes after editing */
        ANIM_editkeyframes_refresh(&ac);
        
-       /* set notifier tha things have changed */
+       /* 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)
 {
        /* 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 */
        RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");