Fix #34040: Moving Normal Node with enabled Cycles Material Preview crashes
[blender.git] / source / blender / editors / space_action / action_edit.c
index 5276e62b9eb0710f89abbf1b56383458e3472bbc..7e99e6c065dfed7ce87c4f3bf8ce46c0427fed19 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -46,6 +44,7 @@
 #include "DNA_gpencil_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_mask_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -53,6 +52,8 @@
 
 #include "BKE_action.h"
 #include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
 #include "BKE_nla.h"
 #include "BKE_context.h"
 #include "BKE_report.h"
@@ -66,6 +67,7 @@
 #include "ED_screen.h"
 #include "ED_transform.h"
 #include "ED_markers.h"
+#include "ED_mask.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -88,7 +90,7 @@ static int act_new_exec(bContext *C, wmOperator *UNUSED(op))
        uiIDContextProperty(C, &ptr, &prop);
        
        if (prop) {
-               bAction *action=NULL, *oldact=NULL;
+               bAction *action = NULL, *oldact = NULL;
                PointerRNA oldptr;
                
                /* create action - the way to do this depends on whether we've got an
@@ -98,13 +100,15 @@ static int act_new_exec(bContext *C, wmOperator *UNUSED(op))
                oldptr = RNA_property_pointer_get(&ptr, prop);
                oldact = (bAction *)oldptr.id.data;
                
-               if (oldact && GS(oldact->id.name)==ID_AC) {
+               if (oldact && GS(oldact->id.name) == ID_AC) {
                        /* make a copy of the existing action */
-                       action= copy_action(oldact);
+                       action = BKE_action_copy(oldact);
                }
                else {
+                       Main *bmain = CTX_data_main(C);
+
                        /* just make a new (empty) action */
-                       action= add_empty_action("Action");
+                       action = add_empty_action(bmain, "Action");
                }
                
                /* when creating new ID blocks, use is already 1 (fake user), 
@@ -118,25 +122,25 @@ static int act_new_exec(bContext *C, wmOperator *UNUSED(op))
        }
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_new (wmOperatorType *ot)
+void ACTION_OT_new(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "New Action";
-       ot->idname= "ACTION_OT_new";
-       ot->description= "Create new action";
+       ot->name = "New Action";
+       ot->idname = "ACTION_OT_new";
+       ot->description = "Create new action";
        
        /* api callbacks */
-       ot->exec= act_new_exec;
-               // NOTE: this is used in the NLA too...
-       //ot->poll= ED_operator_action_active;
+       ot->exec = act_new_exec;
+       /* NOTE: this is used in the NLA too... */
+       //ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ************************************************************************** */
@@ -145,9 +149,9 @@ void ACTION_OT_new (wmOperatorType *ot)
 /* *************************** Localise Markers ***************************** */
 
 /* ensure that there is:
- *     1) an active action editor
- *     2) that the mode will have an active action available 
- *     3) that the set of markers being shown are the scene markers, not the list we're merging
+ *  1) an active action editor
+ *  2) that the mode will have an active action available
+ *  3) that the set of markers being shown are the scene markers, not the list we're merging
  *     4) that there are some selected markers
  */
 static int act_markers_make_local_poll(bContext *C)
@@ -172,14 +176,14 @@ static int act_markers_make_local_poll(bContext *C)
        return ED_markers_get_first_selected(ED_context_get_markers(C)) != NULL;
 }
 
-static int act_markers_make_local_exec (bContext *C, wmOperator *UNUSED(op))
+static int act_markers_make_local_exec(bContext *C, wmOperator *UNUSED(op))
 {      
        ListBase *markers = ED_context_get_markers(C);
        
        SpaceAction *sact = CTX_wm_space_action(C);
-       bAction *act = (sact)? sact->action : NULL;
+       bAction *act = (sact) ? sact->action : NULL;
        
-       TimeMarker *marker, *markern=NULL;
+       TimeMarker *marker, *markern = NULL;
        
        /* sanity checks */
        if (ELEM(NULL, markers, act))
@@ -200,25 +204,25 @@ static int act_markers_make_local_exec (bContext *C, wmOperator *UNUSED(op))
        sact->flag |= SACTION_POSEMARKERS_SHOW;
        
        /* notifiers - both sets, as this change affects both */
-       WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
-       WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
+       WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-void ACTION_OT_markers_make_local (wmOperatorType *ot)
+void ACTION_OT_markers_make_local(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Make Markers Local";
-       ot->idname= "ACTION_OT_markers_make_local";
-       ot->description= "Move selected scene markers to the active Action as local 'pose' markers";
+       ot->name = "Make Markers Local";
+       ot->idname = "ACTION_OT_markers_make_local";
+       ot->description = "Move selected scene markers to the active Action as local 'pose' markers";
        
        /* callbacks */
        ot->exec = act_markers_make_local_exec;
        ot->poll = act_markers_make_local_poll;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ************************************************************************** */
@@ -227,40 +231,68 @@ void ACTION_OT_markers_make_local (wmOperatorType *ot)
 /* *************************** Calculate Range ************************** */
 
 /* Get the min/max keyframes*/
-static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, const short onlySel)
+static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
        /* get data to filter, from Action or Dopesheet */
-       // XXX: what is sel doing here?!
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       /* XXX: what is sel doing here?!
+        *      Commented it, was breaking things (eg. the "auto preview range" tool). */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL *//*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* set large values to try to override */
-       *min= 999999999.0f;
-       *max= -999999999.0f;
+       *min = 999999999.0f;
+       *max = -999999999.0f;
        
        /* check if any channels to set range with */
        if (anim_data.first) {
                /* go through channels, finding max extents */
-               for (ale= anim_data.first; ale; ale= ale->next) {
-                       AnimData *adt= ANIM_nla_mapping_get(ac, ale);
-                       FCurve *fcu= (FCurve *)ale->key_data;
-                       float tmin, tmax;
-                       
-                       /* get range and apply necessary scaling before processing */
-                       calc_fcurve_range(fcu, &tmin, &tmax, onlySel);
-                       
-                       if (adt) {
-                               tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
-                               tmax= BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
+               for (ale = anim_data.first; ale; ale = ale->next) {
+                       AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+                       if (ale->datatype == ALE_GPFRAME) {
+                               bGPDlayer *gpl = ale->data;
+                               bGPDframe *gpf;
+
+                               /* find gp-frame which is less than or equal to cframe */
+                               for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+                                       const float framenum = (float)gpf->framenum;
+                                       *min = min_ff(*min, framenum);
+                                       *max = max_ff(*max, framenum);
+                               }
+                       }
+                       else if (ale->datatype == ALE_MASKLAY) {
+                               MaskLayer *masklay = ale->data;
+                               MaskLayerShape *masklay_shape;
+
+                               /* find mask layer which is less than or equal to cframe */
+                               for (masklay_shape = masklay->splines_shapes.first;
+                                    masklay_shape;
+                                    masklay_shape = masklay_shape->next)
+                               {
+                                       const float framenum = (float)masklay_shape->frame;
+                                       *min = min_ff(*min, framenum);
+                                       *max = max_ff(*max, framenum);
+                               }
+                       }
+                       else {
+                               FCurve *fcu = (FCurve *)ale->key_data;
+                               float tmin, tmax;
+
+                               /* get range and apply necessary scaling before processing */
+                               calc_fcurve_range(fcu, &tmin, &tmax, onlySel, TRUE);
+
+                               if (adt) {
+                                       tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
+                                       tmax = BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP);
+                               }
+
+                               /* try to set cur using these values, if they're more extreme than previously set values */
+                               *min = min_ff(*min, tmin);
+                               *max = max_ff(*max, tmax);
                        }
-                       
-                       /* try to set cur using these values, if they're more extreme than previously set values */
-                       *min= MIN2(*min, tmin);
-                       *max= MAX2(*max, tmax);
                }
                
                /* free memory */
@@ -269,12 +301,12 @@ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, cons
        else {
                /* set default range */
                if (ac->scene) {
-                       *min= (float)ac->scene->r.sfra;
-                       *max= (float)ac->scene->r.efra;
+                       *min = (float)ac->scene->r.sfra;
+                       *max = (float)ac->scene->r.efra;
                }
                else {
-                       *min= -5;
-                       *max= 100;
+                       *min = -5;
+                       *max = 100;
                }
        }
 }
@@ -293,34 +325,34 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
        if (ac.scene == NULL)
                return OPERATOR_CANCELLED;
        else
-               scene= ac.scene;
+               scene = ac.scene;
        
        /* set the range directly */
        get_keyframe_extents(&ac, &min, &max, FALSE);
        scene->r.flag |= SCER_PRV_RANGE;
-       scene->r.psfra= (int)floor(min + 0.5f);
-       scene->r.pefra= (int)floor(max + 0.5f);
+       scene->r.psfra = (int)floor(min + 0.5f);
+       scene->r.pefra = (int)floor(max + 0.5f);
        
        /* 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); 
+       WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_previewrange_set (wmOperatorType *ot)
+void ACTION_OT_previewrange_set(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Auto-Set Preview Range";
-       ot->idname= "ACTION_OT_previewrange_set";
-       ot->description= "Set Preview Range based on extents of selected Keyframes";
+       ot->name = "Auto-Set Preview Range";
+       ot->idname = "ACTION_OT_previewrange_set";
+       ot->description = "Set Preview Range based on extents of selected Keyframes";
        
        /* api callbacks */
-       ot->exec= actkeys_previewrange_exec;
-       ot->poll= ED_operator_action_active;
+       ot->exec = actkeys_previewrange_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ****************** View-All Operator ****************** */
@@ -334,18 +366,18 @@ static int actkeys_viewall(bContext *C, const short onlySel)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       v2d= &ac.ar->v2d;
+       v2d = &ac.ar->v2d;
        
        /* 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, onlySel);
        
-       extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin);
+       extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
        v2d->cur.xmin -= extra;
        v2d->cur.xmax += extra;
        
        /* set vertical range */
-       v2d->cur.ymax= 0.0f;
-       v2d->cur.ymin= (float)-(v2d->mask.ymax - v2d->mask.ymin);
+       v2d->cur.ymax = 0.0f;
+       v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask);
        
        /* do View2D syncing */
        UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
@@ -370,34 +402,34 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op))
        return actkeys_viewall(C, TRUE);
 }
  
-void ACTION_OT_view_all (wmOperatorType *ot)
+void ACTION_OT_view_all(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "View All";
-       ot->idname= "ACTION_OT_view_all";
-       ot->description= "Reset viewable area to show full keyframe range";
+       ot->name = "View All";
+       ot->idname = "ACTION_OT_view_all";
+       ot->description = "Reset viewable area to show full keyframe range";
        
        /* api callbacks */
-       ot->exec= actkeys_viewall_exec;
-       ot->poll= ED_operator_action_active;
+       ot->exec = actkeys_viewall_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-void ACTION_OT_view_selected (wmOperatorType *ot)
+void ACTION_OT_view_selected(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "View Selected";
-       ot->idname= "ACTION_OT_view_selected";
-       ot->description= "Reset viewable area to show selected keyframes range";
+       ot->name = "View Selected";
+       ot->idname = "ACTION_OT_view_selected";
+       ot->description = "Reset viewable area to show selected keyframes range";
        
        /* api callbacks */
-       ot->exec= actkeys_viewsel_exec;
-       ot->poll= ED_operator_action_active;
+       ot->exec = actkeys_viewsel_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ************************************************************************** */
@@ -406,20 +438,20 @@ void ACTION_OT_view_selected (wmOperatorType *ot)
 /* ******************** Copy/Paste Keyframes Operator ************************* */
 /* NOTE: the backend code for this is shared with the graph editor */
 
-static short copy_action_keys (bAnimContext *ac)
+static short copy_action_keys(bAnimContext *ac)
 {      
        ListBase anim_data = {NULL, NULL};
-       int filter, ok=0;
+       int filter, ok = 0;
        
        /* clear buffer first */
        free_anim_copybuf();
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* copy keyframes */
-       ok= copy_animedit_keys(ac, &anim_data);
+       ok = copy_animedit_keys(ac, &anim_data);
        
        /* clean up */
        BLI_freelistN(&anim_data);
@@ -428,18 +460,25 @@ static short copy_action_keys (bAnimContext *ac)
 }
 
 
-static short paste_action_keys (bAnimContext *ac,
-       const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
+static short paste_action_keys(bAnimContext *ac,
+                               const eKeyPasteOffset offset_mode, const eKeyMergeMode merge_mode)
 {      
        ListBase anim_data = {NULL, NULL};
-       int filter, ok=0;
+       int filter, ok = 0;
        
-       /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
-       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       /* filter data 
+        * - First time we try to filter more strictly, allowing only selected channels 
+        *   to allow copying animation between channels
+        * - Second time, we loosen things up if nothing was found the first time, allowing
+        *   users to just paste keyframes back into the original curve again [#31670]
+        */
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       
+       if (ANIM_animdata_filter(ac, &anim_data, filter | ANIMFILTER_SEL, ac->data, ac->datatype) == 0)
+               ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* paste keyframes */
-       ok= paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
+       ok = paste_animedit_keys(ac, &anim_data, offset_mode, merge_mode);
        
        /* clean up */
        BLI_freelistN(&anim_data);
@@ -456,13 +495,20 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       
+
        /* copy keyframes */
        if (ac.datatype == ANIMCONT_GPENCIL) {
-               // FIXME...
+               /* FIXME... */
+               BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil mode");
+               return OPERATOR_CANCELLED;
+       }
+       else if (ac.datatype == ANIMCONT_MASK) {
+               /* FIXME... */
+               BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode");
+               return OPERATOR_CANCELLED;
        }
        else {
-               if (copy_action_keys(&ac)) {    
+               if (copy_action_keys(&ac)) {
                        BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
                        return OPERATOR_CANCELLED;
                }
@@ -471,44 +517,44 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_copy (wmOperatorType *ot)
+void ACTION_OT_copy(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Copy Keyframes";
-       ot->idname= "ACTION_OT_copy";
-       ot->description= "Copy selected keyframes to the copy/paste buffer";
+       ot->name = "Copy Keyframes";
+       ot->idname = "ACTION_OT_copy";
+       ot->description = "Copy selected keyframes to the copy/paste buffer";
        
        /* api callbacks */
-//     ot->invoke= WM_operator_props_popup; // better wait for graph redo panel
-       ot->exec= actkeys_copy_exec;
-       ot->poll= ED_operator_action_active;
+       ot->exec = actkeys_copy_exec;
+       ot->poll = ED_operator_action_active;
 
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 static int actkeys_paste_exec(bContext *C, wmOperator *op)
 {
        bAnimContext ac;
 
-       const eKeyPasteOffset offset_mode= RNA_enum_get(op->ptr, "offset");
-       const eKeyMergeMode merge_mode= RNA_enum_get(op->ptr, "merge");
+       const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset");
+       const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge");
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       
-       if(ac.reports==NULL) {
-               ac.reports= op->reports;
-       }
+               
+       /* ac.reports by default will be the global reports list, which won't show warnings */
+       ac.reports = op->reports;
        
        /* paste keyframes */
-       if (ac.datatype == ANIMCONT_GPENCIL) {
-               // FIXME...
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
+               /* FIXME... */
+               BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil or mask mode");
+               return OPERATOR_CANCELLED;
        }
        else {
+               /* non-zero return means an error occurred while trying to paste */
                if (paste_action_keys(&ac, offset_mode, merge_mode)) {
-                       BKE_report(op->reports, RPT_ERROR, "No keyframes to paste");
                        return OPERATOR_CANCELLED;
                }
        }
@@ -517,27 +563,29 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_paste (wmOperatorType *ot)
+void ACTION_OT_paste(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Paste Keyframes";
-       ot->idname= "ACTION_OT_paste";
-       ot->description= "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame";
+       ot->name = "Paste Keyframes";
+       ot->idname = "ACTION_OT_paste";
+       ot->description = "Paste keyframes from copy/paste buffer for the selected channels, starting on the current frame";
        
        /* api callbacks */
-       ot->exec= actkeys_paste_exec;
-       ot->poll= ED_operator_action_active;
+//     ot->invoke = WM_operator_props_popup; // better wait for action redo panel
+       ot->exec = actkeys_paste_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       
+       /* props */
        RNA_def_enum(ot->srna, "offset", keyframe_paste_offset_items, KEYFRAME_PASTE_OFFSET_CFRA_START, "Offset", "Paste time offset of keys");
-       RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merking pasted keys and existing");
+       RNA_def_enum(ot->srna, "merge", keyframe_paste_merge_items, KEYFRAME_PASTE_MERGE_MIX, "Type", "Method of merging pasted keys and existing");
 }
 
 /* ******************** Insert Keyframes Operator ************************* */
@@ -546,7 +594,7 @@ void ACTION_OT_paste (wmOperatorType *ot)
 static 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
+       {3, "GROUP", 0, "In Active Group", ""},  /* XXX not in all cases */
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -558,13 +606,13 @@ static void insert_action_keys(bAnimContext *ac, short mode)
        int filter;
        
        ReportList *reports = ac->reports;
-       Scene *scene= ac->scene;
+       Scene *scene = ac->scene;
        short flag = 0;
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
-       if (mode == 2)                  filter |= ANIMFILTER_SEL;
-       else if (mode == 3)     filter |= ANIMFILTER_ACTGROUPED;
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       if (mode == 2) filter |= ANIMFILTER_SEL;
+       else if (mode == 3) filter |= ANIMFILTER_ACTGROUPED;
        
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
@@ -572,20 +620,20 @@ static void insert_action_keys(bAnimContext *ac, short mode)
        flag = ANIM_get_keyframing_flags(scene, 1);
        
        /* 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;
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+               FCurve *fcu = (FCurve *)ale->key_data;
                float cfra;
                
                /* adjust current frame for NLA-scaling */
                if (adt)
-                       cfra= BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+                       cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
                else 
-                       cfra= (float)CFRA;
+                       cfra = (float)CFRA;
                        
                /* if there's an id */
                if (ale->id)
-                       insert_keyframe(reports, ale->id, NULL, ((fcu->grp)?(fcu->grp->name):(NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
+                       insert_keyframe(reports, 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);
        }
@@ -603,11 +651,11 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_CANCELLED;
                
        /* what channels to affect? */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* insert keyframes */
        insert_action_keys(&ac, mode);
@@ -616,51 +664,55 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
 
-void ACTION_OT_keyframe_insert (wmOperatorType *ot)
+void ACTION_OT_keyframe_insert(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Insert Keyframes";
-       ot->idname= "ACTION_OT_keyframe_insert";
-       ot->description= "Insert keyframes for the specified channels";
+       ot->name = "Insert Keyframes";
+       ot->idname = "ACTION_OT_keyframe_insert";
+       ot->description = "Insert keyframes for the specified channels";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_insertkey_exec;
-       ot->poll= ED_operator_action_active;
+       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 */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_insertkey_types, 0, "Type", "");
 }
 
 /* ******************** Duplicate Keyframes Operator ************************* */
 
-static void duplicate_action_keys (bAnimContext *ac)
+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_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
        else
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        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) {
+       for (ale = anim_data.first; ale; ale = ale->next) {
                if (ale->type == ANIMTYPE_FCURVE)
                        duplicate_fcurve_keys((FCurve *)ale->key_data);
+               else if (ale->type == ANIMTYPE_GPLAYER)
+                       ED_gplayer_frames_duplicate((bGPDlayer *)ale->data);
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       ED_masklayer_frames_duplicate((MaskLayer *)ale->data);
                else
-                       duplicate_gplayer_frames((bGPDlayer *)ale->data);
+                       BLI_assert(0);
        }
        
        /* free filtered list */
@@ -681,12 +733,13 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
        duplicate_action_keys(&ac);
        
        /* validate keyframes after editing */
-       ANIM_editkeyframes_refresh(&ac);
+       if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
-       return OPERATOR_FINISHED; // xxx - start transform
+       return OPERATOR_FINISHED;
 }
 
 static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
@@ -696,45 +749,48 @@ static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_duplicate (wmOperatorType *ot)
+void ACTION_OT_duplicate(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Duplicate Keyframes";
-       ot->idname= "ACTION_OT_duplicate";
-       ot->description= "Make a copy of all selected keyframes";
+       ot->name = "Duplicate Keyframes";
+       ot->idname = "ACTION_OT_duplicate";
+       ot->description = "Make a copy of all selected keyframes";
        
        /* api callbacks */
-       ot->invoke= actkeys_duplicate_invoke;
-       ot->exec= actkeys_duplicate_exec;
-       ot->poll= ED_operator_action_active;
+       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_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", "");
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ******************** Delete Keyframes Operator ************************* */
 
-static void delete_action_keys (bAnimContext *ac)
+static void delete_action_keys(bAnimContext *ac)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
        else
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        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) {
-                       FCurve *fcu= (FCurve *)ale->key_data;
-                       AnimData *adt= ale->adt;
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               if (ale->type == ANIMTYPE_GPLAYER) {
+                       ED_gplayer_frames_delete((bGPDlayer *)ale->data);
+               }
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       ED_masklayer_frames_delete((MaskLayer *)ale->data);
+               }
+               else {
+                       FCurve *fcu = (FCurve *)ale->key_data;
+                       AnimData *adt = ale->adt;
                        
                        /* delete selected keyframes only */
                        delete_fcurve_keys(fcu); 
@@ -743,8 +799,6 @@ static void delete_action_keys (bAnimContext *ac)
                        if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
                                ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
                }
-               else
-                       delete_gplayer_frames((bGPDlayer *)ale->data);
        }
        
        /* free filtered list */
@@ -765,44 +819,45 @@ static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
        delete_action_keys(&ac);
        
        /* validate keyframes after editing */
-       ANIM_editkeyframes_refresh(&ac);
+       if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_delete (wmOperatorType *ot)
+void ACTION_OT_delete(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Delete Keyframes";
-       ot->idname= "ACTION_OT_delete";
-       ot->description= "Remove all selected keyframes";
+       ot->name = "Delete Keyframes";
+       ot->idname = "ACTION_OT_delete";
+       ot->description = "Remove all selected keyframes";
        
        /* api callbacks */
-       ot->invoke= WM_operator_confirm;
-       ot->exec= actkeys_delete_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_operator_confirm;
+       ot->exec = actkeys_delete_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ******************** Clean Keyframes Operator ************************* */
 
-static void clean_action_keys (bAnimContext *ac, float thresh)
+static void clean_action_keys(bAnimContext *ac, float thresh)
 {      
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        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)
+       for (ale = anim_data.first; ale; ale = ale->next)
                clean_fcurve((FCurve *)ale->key_data, thresh);
        
        /* free temp data */
@@ -819,11 +874,11 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get cleaning threshold */
-       thresh= RNA_float_get(op->ptr, "threshold");
+       thresh = RNA_float_get(op->ptr, "threshold");
        
        /* clean keyframes */
        clean_action_keys(&ac, thresh);
@@ -832,45 +887,45 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_clean (wmOperatorType *ot)
+void ACTION_OT_clean(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Clean Keyframes";
-       ot->idname= "ACTION_OT_clean";
-       ot->description= "Simplify F-Curves by removing closely spaced keyframes";
+       ot->name = "Clean Keyframes";
+       ot->idname = "ACTION_OT_clean";
+       ot->description = "Simplify F-Curves by removing closely spaced keyframes";
        
        /* api callbacks */
-       //ot->invoke=  // XXX we need that number popup for this! 
-       ot->exec= actkeys_clean_exec;
-       ot->poll= ED_operator_action_active;
+       //ot->invoke =  // XXX we need that number popup for this! 
+       ot->exec = actkeys_clean_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* properties */
-       ot->prop= RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
+       ot->prop = RNA_def_float(ot->srna, "threshold", 0.001f, 0.0f, FLT_MAX, "Threshold", "", 0.0f, 1000.0f);
 }
 
 /* ******************** Sample Keyframes Operator *********************** */
 
 /* Evaluates the curves between each selected keyframe on each frame, and keys the value  */
-static void sample_action_keys (bAnimContext *ac)
+static void sample_action_keys(bAnimContext *ac)
 {      
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        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)
+       for (ale = anim_data.first; ale; ale = ale->next)
                sample_fcurve((FCurve *)ale->key_data);
        
        /* admin and redraws */
@@ -886,7 +941,7 @@ static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
        
        /* sample keyframes */
@@ -896,24 +951,24 @@ static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_sample (wmOperatorType *ot)
+void ACTION_OT_sample(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Sample Keyframes";
-       ot->idname= "ACTION_OT_sample";
-       ot->description= "Add keyframes on every frame between the selected keyframes";
+       ot->name = "Sample Keyframes";
+       ot->idname = "ACTION_OT_sample";
+       ot->description = "Add keyframes on every frame between the selected keyframes";
        
        /* api callbacks */
-       ot->exec= actkeys_sample_exec;
-       ot->poll= ED_operator_action_active;
+       ot->exec = actkeys_sample_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ************************************************************************** */
@@ -922,13 +977,13 @@ void ACTION_OT_sample (wmOperatorType *ot)
 /* ******************** Set Extrapolation-Type Operator *********************** */
 
 /* defines for make/clear cyclic extrapolation tools */
-#define MAKE_CYCLIC_EXPO       -1
-#define CLEAR_CYCLIC_EXPO      -2
+#define MAKE_CYCLIC_EXPO    -1
+#define CLEAR_CYCLIC_EXPO   -2
 
 /* defines for set extrapolation-type for selected keyframes tool */
 static EnumPropertyItem prop_actkeys_expo_types[] = {
-       {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", ""},
-       {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", ""},
+       {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", "Values on endpoint keyframes are held"},
+       {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", "Straight-line slope of end segments are extended past the endpoint keyframes"},
        
        {MAKE_CYCLIC_EXPO, "MAKE_CYCLIC", 0, "Make Cyclic (F-Modifier)", "Add Cycles F-Modifier if one doesn't exist already"},
        {CLEAR_CYCLIC_EXPO, "CLEAR_CYCLIC", 0, "Clear Cyclic (F-Modifier)", "Remove Cycles F-Modifier if not needed anymore"},
@@ -943,16 +998,16 @@ static void setexpo_action_keys(bAnimContext *ac, short mode)
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through setting mode per F-Curve */
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               FCurve *fcu= (FCurve *)ale->data;
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               FCurve *fcu = (FCurve *)ale->data;
                
                if (mode >= 0) {
                        /* just set mode setting */
-                       fcu->extend= mode;
+                       fcu->extend = mode;
                }
                else {
                        /* shortcuts for managing Cycles F-Modifiers to make it easier to toggle cyclic animation 
@@ -961,13 +1016,13 @@ static void setexpo_action_keys(bAnimContext *ac, short mode)
                        if (mode == MAKE_CYCLIC_EXPO) {
                                /* only add if one doesn't exist */
                                if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) {
-                                       // TODO: add some more preset versions which set different extrapolation options?
+                                       /* TODO: add some more preset versions which set different extrapolation options? */
                                        add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES);
                                }
                        }
                        else if (mode == CLEAR_CYCLIC_EXPO) {
                                /* remove all the modifiers fitting this description */
-                               FModifier *fcm, *fcn=NULL;
+                               FModifier *fcm, *fcn = NULL;
                                
                                for (fcm = fcu->modifiers.first; fcm; fcm = fcn) {
                                        fcn = fcm->next;
@@ -993,11 +1048,11 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL) 
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get handle setting mode */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* set handle type */
        setexpo_action_keys(&ac, mode);
@@ -1006,28 +1061,28 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframe properties have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_extrapolation_type (wmOperatorType *ot)
+void ACTION_OT_extrapolation_type(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Set Keyframe Extrapolation";
-       ot->idname= "ACTION_OT_extrapolation_type";
-       ot->description= "Set extrapolation mode for selected F-Curves";
+       ot->name = "Set Keyframe Extrapolation";
+       ot->idname = "ACTION_OT_extrapolation_type";
+       ot->description = "Set extrapolation mode for selected F-Curves";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_expo_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = actkeys_expo_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* id-props */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_expo_types, 0, "Type", "");
 }
 
 /* ******************** Set Interpolation-Type Operator *********************** */
@@ -1038,16 +1093,16 @@ static void setipo_action_keys(bAnimContext *ac, short mode)
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
-       KeyframeEditFunc set_cb= ANIM_editkeyframes_ipo(mode);
+       KeyframeEditFunc set_cb = ANIM_editkeyframes_ipo(mode);
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through setting BezTriple interpolation
         * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here...
         */
-       for (ale= anim_data.first; ale; ale= ale->next)
+       for (ale = anim_data.first; ale; ale = ale->next)
                ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, calchandles_fcurve);
        
        /* cleanup */
@@ -1064,11 +1119,11 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL) 
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get handle setting mode */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* set handle type */
        setipo_action_keys(&ac, mode);
@@ -1077,28 +1132,28 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframe properties have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_interpolation_type (wmOperatorType *ot)
+void ACTION_OT_interpolation_type(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Set Keyframe Interpolation";
-       ot->idname= "ACTION_OT_interpolation_type";
-       ot->description= "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
+       ot->name = "Set Keyframe Interpolation";
+       ot->idname = "ACTION_OT_interpolation_type";
+       ot->description = "Set interpolation mode for the F-Curve segments starting from the selected keyframes";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_ipo_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = actkeys_ipo_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* id-props */
-       ot->prop= RNA_def_enum(ot->srna, "type", beztriple_interpolation_mode_items, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", beztriple_interpolation_mode_items, 0, "Type", "");
 }
 
 /* ******************** Set Handle-Type Operator *********************** */
@@ -1110,18 +1165,18 @@ static void sethandles_action_keys(bAnimContext *ac, short mode)
        bAnimListElem *ale;
        int filter;
        
-       KeyframeEditFunc edit_cb= ANIM_editkeyframes_handles(mode);
-       KeyframeEditFunc sel_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+       KeyframeEditFunc edit_cb = ANIM_editkeyframes_handles(mode);
+       KeyframeEditFunc sel_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through setting flags for handles 
         * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here...
         */
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               FCurve *fcu= (FCurve *)ale->key_data;
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               FCurve *fcu = (FCurve *)ale->key_data;
                
                /* any selected keyframes for editing? */
                if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL)) {
@@ -1144,11 +1199,11 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL) 
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get handle setting mode */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* set handle type */
        sethandles_action_keys(&ac, mode);
@@ -1157,28 +1212,28 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframe properties have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_handle_type (wmOperatorType *ot)
+void ACTION_OT_handle_type(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Set Keyframe Handle Type";
-       ot->idname= "ACTION_OT_handle_type";
-       ot->description= "Set type of handle for selected keyframes";
+       ot->name = "Set Keyframe Handle Type";
+       ot->idname = "ACTION_OT_handle_type";
+       ot->description = "Set type of handle for selected keyframes";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_handletype_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = actkeys_handletype_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* id-props */
-       ot->prop= RNA_def_enum(ot->srna, "type", keyframe_handle_type_items, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", keyframe_handle_type_items, 0, "Type", "");
 }
 
 /* ******************** Set Keyframe-Type Operator *********************** */
@@ -1189,16 +1244,16 @@ static void setkeytype_action_keys(bAnimContext *ac, short mode)
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
-       KeyframeEditFunc set_cb= ANIM_editkeyframes_keytype(mode);
+       KeyframeEditFunc set_cb = ANIM_editkeyframes_keytype(mode);
        
        /* filter data */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* loop through setting BezTriple interpolation
         * Note: we do not supply KeyframeEditData to the looper yet. Currently that's not necessary here...
         */
-       for (ale= anim_data.first; ale; ale= ale->next)
+       for (ale = anim_data.first; ale; ale = ale->next)
                ANIM_fcurve_keyframes_loop(NULL, ale->key_data, NULL, set_cb, NULL);
        
        /* cleanup */
@@ -1215,11 +1270,11 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-       if (ac.datatype == ANIMCONT_GPENCIL) 
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get handle setting mode */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* set handle type */
        setkeytype_action_keys(&ac, mode);
@@ -1228,28 +1283,28 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframe properties have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_keyframe_type (wmOperatorType *ot)
+void ACTION_OT_keyframe_type(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Set Keyframe Type";
-       ot->idname= "ACTION_OT_keyframe_type";
-       ot->description= "Set type of keyframe for the selected keyframes";
+       ot->name = "Set Keyframe Type";
+       ot->idname = "ACTION_OT_keyframe_type";
+       ot->description = "Set type of keyframe for the selected keyframes";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_keytype_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = actkeys_keytype_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* id-props */
-       ot->prop= RNA_def_enum(ot->srna, "type", beztriple_keyframe_type_items, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", beztriple_keyframe_type_items, 0, "Type", "");
 }
 
 /* ************************************************************************** */
@@ -1257,26 +1312,35 @@ void ACTION_OT_keyframe_type (wmOperatorType *ot)
 
 /* ***************** Jump to Selected Frames Operator *********************** */
 
+static int actkeys_framejump_poll(bContext *C)
+{
+       /* prevent changes during render */
+       if (G.is_rendering)
+               return 0;
+
+       return ED_operator_action_active(C);
+}
+
 /* snap current-frame indicator to 'average time' of selected keyframe */
 static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
 {
        bAnimContext ac;
-       ListBase anim_data= {NULL, NULL};
+       ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
-       KeyframeEditData ked= {{NULL}};
+       KeyframeEditData ked = {{NULL}};
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
        
-       /* init edit data */    
+       /* init edit data */
        /* loop over action data, averaging values */
-       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
+       filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
        
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
+       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_keyframes_loop(&ked, ale->key_data, NULL, bezt_calc_average, NULL);
@@ -1290,40 +1354,44 @@ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op))
        
        /* set the new current frame value, based on the average time */
        if (ked.i1) {
-               Scene *scene= ac.scene;
-               CFRA= (int)floor((ked.f1 / ked.i1) + 0.5f);
-               SUBFRA= 0.f;
+               Scene *scene = ac.scene;
+               CFRA = (int)floor((ked.f1 / ked.i1) + 0.5f);
+               SUBFRA = 0.f;
        }
        
        /* set notifier that things have changed */
-       WM_event_add_notifier(C, NC_SCENE|ND_FRAME, ac.scene);
+       WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
        
        return OPERATOR_FINISHED;
 }
 
-void ACTION_OT_frame_jump (wmOperatorType *ot)
+void ACTION_OT_frame_jump(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Jump to Frame";
-       ot->idname= "ACTION_OT_frame_jump";
-       ot->description= "Set the current frame to the average frame of the selected keyframes";
+       ot->name = "Jump to Keyframes";
+       ot->idname = "ACTION_OT_frame_jump";
+       ot->description = "Set the current frame to the average frame value of selected keyframes";
        
        /* api callbacks */
-       ot->exec= actkeys_framejump_exec;
-       ot->poll= ED_operator_action_active;
+       ot->exec = actkeys_framejump_exec;
+       ot->poll = actkeys_framejump_poll;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
 /* ******************** Snap Keyframes Operator *********************** */
 
 /* defines for snap keyframes tool */
 static EnumPropertyItem prop_actkeys_snap_types[] = {
-       {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", ""},
+       {ACTKEYS_SNAP_CFRA, "CFRA", 0, "Current frame",
+        "Snap selected keyframes to the current frame"},
+       {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame",
+        "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame offsets)"},
+       {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second",
+        "Snap selected keyframes to the nearest second"},
+       {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker",
+        "Snap selected keyframes to the nearest marker"},
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -1334,38 +1402,43 @@ static void snap_action_keys(bAnimContext *ac, short mode)
        bAnimListElem *ale;
        int filter;
        
-       KeyframeEditData ked= {{NULL}};
+       KeyframeEditData ked = {{NULL}};
        KeyframeEditFunc edit_cb;
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
        else
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* get beztriple editing callbacks */
-       edit_cb= ANIM_editkeyframes_snap(mode);
+       edit_cb = ANIM_editkeyframes_snap(mode);
 
-       ked.scene= ac->scene;
+       ked.scene = ac->scene;
        if (mode == ACTKEYS_SNAP_NEAREST_MARKER) {
-               ked.list.first= (ac->markers) ? ac->markers->first : NULL;
-               ked.list.last= (ac->markers) ? ac->markers->last : NULL;
+               ked.list.first = (ac->markers) ? ac->markers->first : NULL;
+               ked.list.last = (ac->markers) ? ac->markers->last : NULL;
        }
        
        /* snap keyframes */
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               AnimData *adt= ANIM_nla_mapping_get(ac, ale);
+       for (ale = anim_data.first; ale; ale = ale->next) {
+               AnimData *adt = ANIM_nla_mapping_get(ac, ale);
                
-               if (adt) {
+               if (ale->type == ANIMTYPE_GPLAYER) {
+                       ED_gplayer_snap_frames(ale->data, ac->scene, mode);
+               }
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       ED_masklayer_snap_frames(ale->data, ac->scene, mode);
+               }
+               else if (adt) {
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); 
                        ANIM_fcurve_keyframes_loop(&ked, 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 
+               else {
                        ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve);
+               }
        }
        
        BLI_freelistN(&anim_data);
@@ -1381,48 +1454,52 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
-               
+       
        /* get snapping mode */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* snap keyframes */
        snap_action_keys(&ac, mode);
        
        /* validate keyframes after editing */
-       ANIM_editkeyframes_refresh(&ac);
+       if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_snap (wmOperatorType *ot)
+void ACTION_OT_snap(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Snap Keys";
-       ot->idname= "ACTION_OT_snap";
-       ot->description= "Snap selected keyframes to the times specified";
+       ot->name = "Snap Keys";
+       ot->idname = "ACTION_OT_snap";
+       ot->description = "Snap selected keyframes to the times specified";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_snap_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = actkeys_snap_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* id-props */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_snap_types, 0, "Type", "");
 }
 
 /* ******************** Mirror Keyframes Operator *********************** */
 
 /* defines for mirror keyframes tool */
 static EnumPropertyItem prop_actkeys_mirror_types[] = {
-       {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""},
-       {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""},
-       {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""},
+       {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame",
+        "Flip times of selected keyframes using the current frame as the mirror line"},
+       {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0",
+        "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"},
+       {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker",
+        "Flip times of selected keyframes using the first selected marker as the reference point"},
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -1433,39 +1510,35 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
        bAnimListElem *ale;
        int filter;
        
-       KeyframeEditData ked= {{NULL}};
+       KeyframeEditData ked = {{NULL}};
        KeyframeEditFunc edit_cb;
        
        /* get beztriple editing callbacks */
-       edit_cb= ANIM_editkeyframes_mirror(mode);
+       edit_cb = ANIM_editkeyframes_mirror(mode);
 
-       ked.scene= ac->scene;
+       ked.scene = ac->scene;
        
        /* for 'first selected marker' mode, need to find first selected marker first! */
-       // XXX should this be made into a helper func in the API?
+       /* XXX should this be made into a helper func in the API? */
        if (mode == ACTKEYS_MIRROR_MARKER) {
-               TimeMarker *marker= NULL;
+               TimeMarker *marker = ED_markers_get_first_selected(ac->markers);
                
-               /* find first selected marker */
-               marker= ED_markers_get_first_selected(ac->markers);
-               
-               /* store marker's time (if available) */
                if (marker)
-                       ked.f1= (float)marker->frame;
+                       ked.f1 = (float)marker->frame;
                else
                        return;
        }
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
        else
-               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+               filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* mirror keyframes */
-       for (ale= anim_data.first; ale; ale= ale->next) {
-               AnimData *adt= ANIM_nla_mapping_get(ac, ale);
+       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); 
@@ -1492,8 +1565,12 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
                
+       /* XXX... */
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
+               return OPERATOR_PASS_THROUGH;
+               
        /* get mirroring mode */
-       mode= RNA_enum_get(op->ptr, "type");
+       mode = RNA_enum_get(op->ptr, "type");
        
        /* mirror keyframes */
        mirror_action_keys(&ac, mode);
@@ -1502,28 +1579,28 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
        ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
        
        return OPERATOR_FINISHED;
 }
  
-void ACTION_OT_mirror (wmOperatorType *ot)
+void ACTION_OT_mirror(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Mirror Keys";
-       ot->idname= "ACTION_OT_mirror";
-       ot->description= "Flip selected keyframes over the selected mirror line";
+       ot->name = "Mirror Keys";
+       ot->idname = "ACTION_OT_mirror";
+       ot->description = "Flip selected keyframes over the selected mirror line";
        
        /* api callbacks */
-       ot->invoke= WM_menu_invoke;
-       ot->exec= actkeys_mirror_exec;
-       ot->poll= ED_operator_action_active;
+       ot->invoke = WM_menu_invoke;
+       ot->exec = actkeys_mirror_exec;
+       ot->poll = ED_operator_action_active;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
        
        /* id-props */
-       ot->prop= RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", prop_actkeys_mirror_types, 0, "Type", "");
 }
 
 /* ************************************************************************** */