soc-2008-mxcurioni: merged changes to revision 15705
[blender.git] / source / blender / src / editaction.c
index f93a1526e3cb891d53a389e24115595736f4531a..3251cb33b53766716d15bcc9fc69108fd8670664 100644 (file)
@@ -52,6 +52,7 @@
 #include "DNA_mesh_types.h"
 #include "DNA_nla_types.h"
 #include "DNA_lattice_types.h"
+#include "DNA_gpencil_types.h"
 
 #include "BKE_action.h"
 #include "BKE_armature.h"
@@ -90,6 +91,7 @@
 
 #include "BDR_drawaction.h"
 #include "BDR_editobject.h"
+#include "BDR_gpencil.h"
 
 #include "mydevice.h"
 #include "blendef.h"
@@ -296,6 +298,16 @@ bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, sho
                                ale->datatype= ALE_IPO;
                        }
                                break;
+                       case ACTTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl= (bGPDlayer *)data;
+                               
+                               ale->flag= gpl->flag;
+                               
+                               ale->key_data= NULL;
+                               ale->datatype= ALE_GPFRAME;
+                       }
+                               break;
                }
        }
        
@@ -505,6 +517,29 @@ static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mo
        }
 }
  
+static void actdata_filter_gpencil (ListBase *act_data, bGPdata *gpd, int filter_mode)
+{
+       bActListElem *ale;
+       bGPDlayer *gpl;
+       
+       /* check if filtering types are appropriate */
+       if ( !(filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU|ACTFILTER_ACTGROUPED)) ) 
+       {
+               /* loop over layers as the conditions are acceptable */
+               for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+                       /* only if selected */
+                       if (!(filter_mode & ACTFILTER_SEL) || SEL_GPL(gpl)) {
+                               /* only if editable */
+                               if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+                                       /* add to list */
+                                       ale= make_new_actlistelem(gpl, ACTTYPE_GPLAYER, NULL, ACTTYPE_NONE);
+                                       if (ale) BLI_addtail(act_data, ale);
+                               }
+                       }
+               }
+       }
+}
 /* This function filters the active data source to leave only the desired
  * data types. 'Public' api call.
  *     *act_data: is a pointer to a ListBase, to which the filtered action data 
@@ -525,6 +560,9 @@ void actdata_filter (ListBase *act_data, int filter_mode, void *data, short data
                        case ACTCONT_SHAPEKEY:
                                actdata_filter_shapekey(act_data, data, filter_mode);
                                break;
+                       case ACTCONT_GPENCIL:
+                               actdata_filter_gpencil(act_data, data, filter_mode);
+                               break;
                }
                        
                /* remove any weedy entries */
@@ -743,6 +781,10 @@ static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, b
                                bActionGroup *agrp= (bActionGroup *)ale->data;
                                agroup_to_keylist(agrp, &act_keys, NULL, NULL);
                        }
+                       else if (ale->type == ACTTYPE_GPLAYER) {
+                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               gpl_to_keylist(gpl, &act_keys, NULL, NULL);
+                       }
                        
                        /* loop through keyframes, finding one that was clicked on */
                        for (ak= act_keys.first; ak; ak= ak->next) {
@@ -766,6 +808,10 @@ static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, b
                                data = ale->key_data;
                                *ret_type= ACTTYPE_ICU;
                        }
+                       else if (datatype == ACTCONT_GPENCIL) {
+                               data = ale->data;
+                               *ret_type= ACTTYPE_GPLAYER;
+                       }
                        
                        /* cleanup tempolary lists */
                        BLI_freelistN(&act_keys);
@@ -795,17 +841,43 @@ void *get_action_context (short *datatype)
        act = (G.saction)? G.saction->action: NULL;
        key = get_action_mesh_key();
        
-       if (act) {
-               *datatype= ACTCONT_ACTION;
-               return act;
-       }
-       else if (key) {
-               *datatype= ACTCONT_SHAPEKEY;
-               return key;
+       /* check mode selector */
+       if (G.saction) {
+               switch (G.saction->mode) {
+                       case SACTCONT_ACTION: 
+                               *datatype= ACTCONT_ACTION;
+                               return act;
+                               
+                       case SACTCONT_SHAPEKEY:
+                               *datatype= ACTCONT_SHAPEKEY;
+                               return key;
+                               
+                       case SACTCONT_GPENCIL:
+                               *datatype= ACTCONT_GPENCIL;
+                               if (G.saction->pin)
+                                       return G.saction->gpd;
+                               else
+                                       return gpencil_data_getetime(G.curscreen);
+                       
+                       default: /* includes SACTCONT_DOPESHEET for now */
+                               *datatype= ACTCONT_NONE;
+                               return NULL;
+               }
        }
        else {
-               *datatype= ACTCONT_NONE;
-               return NULL;
+               /* resort to guessing based on what is available */
+               if (act) {
+                       *datatype= ACTCONT_ACTION;
+                       return act;
+               }
+               else if (key) {
+                       *datatype= ACTCONT_SHAPEKEY;
+                       return key;
+               }
+               else {
+                       *datatype= ACTCONT_NONE;
+                       return NULL;
+               }
        }
 }
 
@@ -1114,6 +1186,38 @@ void action_groups_ungroup (void)
        allqueue(REDRAWACTION, 0);
 }
 
+/* Copy colors from a specified theme's color set to an Action/Bone Group */
+void actionbone_group_copycolors (bActionGroup *grp, short init_new)
+{
+       /* error checking */
+       if (grp == NULL)
+               return;
+       
+       /* only do color copying if using a custom color */
+       if (grp->customCol) {
+               if (grp->customCol > 0) {
+                       /* copy theme colors on-to group's custom color in case user tries to edit color */
+                       bTheme *btheme= U.themes.first;
+                       ThemeWireColor *col_set= &btheme->tarm[(grp->customCol - 1)];
+                       
+                       memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
+               }
+               else if (init_new) {
+                       /* init custom colors with a generic multi-color rgb set, if not initialised already (and allowed to do so) */
+                       if (grp->cs.solid[0] == 0) {
+                               /* define for setting colors in theme below */
+                               #define SETCOL(col, r, g, b, a)  col[0]=r; col[1]=g; col[2]= b; col[3]= a;
+                               
+                               SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255);
+                               SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255);
+                               SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255);
+                               
+                               #undef SETCOL
+                       }
+               }
+       }
+}
+
 /* This function is used when inserting keyframes for pose-channels. It assigns the
  * action-channel with the nominated name to a group with the same name as that of 
  * the pose-channel with the nominated name.
@@ -1160,34 +1264,9 @@ void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[])
                        /* copy name */
                        sprintf(grp->name, agrp->name);
                        
-                       /* deal with group-color copying */
-                       if (agrp->customCol) {
-                               if (agrp->customCol > 0) {
-                                       /* copy theme colors on-to group's custom color in case user tries to edit color */
-                                       bTheme *btheme= U.themes.first;
-                                       ThemeWireColor *col_set= &btheme->tarm[(agrp->customCol - 1)];
-                                       
-                                       memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
-                               }
-                               else {
-                                       /* init custom colors with a generic multi-color rgb set, if not initialised already */
-                                       if (agrp->cs.solid[0] == 0) {
-                                               /* define for setting colors in theme below */
-                                               #define SETCOL(col, r, g, b, a)  col[0]=r; col[1]=g; col[2]= b; col[3]= a;
-                                               
-                                               SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255);
-                                               SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255);
-                                               SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255);
-                                               
-                                               #undef SETCOL
-                                       }
-                                       else {
-                                               /* just copy color set specified */
-                                               memcpy(&grp->cs, &agrp->cs, sizeof(ThemeWireColor));
-                                       }
-                               }
-                       }
-                       grp->customCol= agrp->customCol;
+                       /* deal with group-color copying (grp is destination, agrp is source) */
+                       memcpy(grp, agrp, sizeof(bActionGroup));
+                       actionbone_group_copycolors(grp, 1);
                        
                        BLI_addtail(&act->groups, grp);
                }
@@ -1300,12 +1379,18 @@ void duplicate_action_keys (void)
        if (data == NULL) return;
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* loop through filtered data and duplicate selected keys */
        for (ale= act_data.first; ale; ale= ale->next) {
-               duplicate_ipo_keys((Ipo *)ale->key_data);
+               if (ale->type == ACTTYPE_GPLAYER)
+                       duplicate_gplayer_frames(ale->data);
+               else
+                       duplicate_ipo_keys((Ipo *)ale->key_data);
        }
        
        /* free filtered list */
@@ -1391,7 +1476,10 @@ void snap_action_keys(short mode)
        }
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* snap to frame */
@@ -1401,6 +1489,8 @@ void snap_action_keys(short mode)
                        snap_ipo_keys(ale->key_data, mode);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       snap_gplayer_frames(ale->data, mode);
                else 
                        snap_ipo_keys(ale->key_data, mode);
        }
@@ -1414,6 +1504,7 @@ void snap_action_keys(short mode)
        allqueue(REDRAWACTION, 0);
        allqueue(REDRAWIPO, 0);
        allqueue(REDRAWNLA, 0);
+       allqueue(REDRAWVIEW3D, 0);
 }
 
 /* this function is responsible for snapping keyframes to frame-times */
@@ -1449,7 +1540,10 @@ void mirror_action_keys(short mode)
        }
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* mirror */
@@ -1459,6 +1553,8 @@ void mirror_action_keys(short mode)
                        mirror_ipo_keys(ale->key_data, mode);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       mirror_gplayer_frames(ale->data, mode);
                else 
                        mirror_ipo_keys(ale->key_data, mode);
        }
@@ -1543,6 +1639,10 @@ void insertkey_action(void)
                        }
                }
        }
+       else {
+               /* this tool is not supported in this mode */
+               return;
+       }
        
        BIF_undo_push("Insert Key");
        allspace(REMAKEIPO, 0);
@@ -1566,12 +1666,18 @@ void delete_action_keys (void)
        if (data == NULL) return;
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* loop through filtered data and delete selected keys */
        for (ale= act_data.first; ale; ale= ale->next) {
-               delete_ipo_keys((Ipo *)ale->key_data);
+               if (ale->type == ACTTYPE_GPLAYER)
+                       delete_gplayer_frames((bGPDlayer *)ale->data);
+               else
+                       delete_ipo_keys((Ipo *)ale->key_data);
        }
        
        /* free filtered list */
@@ -1692,6 +1798,7 @@ void clean_action (void)
                                0.0000001f, 1.0, 0.001, 0.1,
                                "Clean Threshold");
        if (!ok) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* filter data */
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_SEL | ACTFILTER_ONLYICU);
@@ -1730,6 +1837,7 @@ void sample_action_keys (void)
        /* sanity checks */
        data= get_action_context(&datatype);
        if (data == NULL) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* filter data */
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
@@ -2089,6 +2197,7 @@ void action_set_ipo_flags (short mode, short event)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* determine which set of processing we are doing */
        switch (mode) {
@@ -2187,6 +2296,7 @@ void sethandles_action_keys (int code)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
+       if (datatype == ACTCONT_GPENCIL) return;
        
        /* filter data */
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
@@ -2225,11 +2335,12 @@ static void numbuts_action ()
        bConstraintChannel *conchan= NULL;
        IpoCurve *icu= NULL;
        KeyBlock *kb= NULL;
+       bGPDlayer *gpl= NULL;
        
        short mval[2];
        
        int but=0;
-    char str[64];
+    char str[128];
        short expand, protect, mute;
        float slidermin, slidermax;
        
@@ -2338,6 +2449,18 @@ static void numbuts_action ()
                add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Group is Expanded");
                add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Group is Protected");
        }
+       else if (chantype == ACTTYPE_GPLAYER) {
+               /* Grease-Pencil Layer */
+               gpl= (bGPDlayer *)act_channel;
+               
+               strcpy(str, gpl->info);
+               protect= (gpl->flag & GP_LAYER_LOCKED);
+               mute = (gpl->flag & GP_LAYER_HIDE);
+               
+               add_numbut(but++, TEX, "GP-Layer: ", 0, 128, str, "Name of Grease Pencil Layer");
+               add_numbut(but++, TOG|SHO, "Hide", 0, 24, &mute, "Grease Pencil Layer is Visible");
+               add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Grease Pencil Layer is Protected");
+       }
        else {
                /* nothing under-cursor */
                return;
@@ -2386,6 +2509,16 @@ static void numbuts_action ()
                        if (protect) agrp->flag |= AGRP_PROTECTED;
                        else agrp->flag &= ~AGRP_PROTECTED;
                }
+               else if (gpl) {
+                       strcpy(gpl->info, str);
+                       BLI_uniquename(&( ((bGPdata *)data)->layers ), gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
+                       
+                       if (mute) gpl->flag |= GP_LAYER_HIDE;
+                       else gpl->flag &= ~GP_LAYER_HIDE;;
+                       
+                       if (protect) gpl->flag |= GP_LAYER_LOCKED;
+                       else gpl->flag &= ~GP_LAYER_LOCKED;
+               }
                
         allqueue(REDRAWACTION, 0);
                allspace(REMAKEIPO, 0);
@@ -2517,6 +2650,31 @@ void setflag_action_channels (short mode)
                                }
                        }
                                break;
+                       case ACTTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               
+                               /* 'protect' and 'mute' */
+                               if (val == 2) {
+                                       /* mute */
+                                       if (mode == 2)
+                                               gpl->flag &= ~GP_LAYER_HIDE;
+                                       else if (mode == 1)
+                                               gpl->flag |= GP_LAYER_HIDE;
+                                       else
+                                               gpl->flag ^= GP_LAYER_HIDE;
+                               }
+                               else if (val == 1) {
+                                       /* protected */
+                                       if (mode == 2)
+                                               gpl->flag &= ~GP_LAYER_LOCKED;
+                                       else if (mode == 1)
+                                               gpl->flag |= GP_LAYER_LOCKED;
+                                       else
+                                               gpl->flag ^= GP_LAYER_LOCKED;
+                               }
+                       }
+                               break;
                }
        }
        BLI_freelistN(&act_data);
@@ -2557,7 +2715,7 @@ static void select_action_group (bAction *act, bActionGroup *agrp, int selectmod
        set_active_actiongroup(act, agrp, select);
 }
 
-static void hilight_channel(bAction *act, bActionChannel *achan, short select)
+static void hilight_channel (bAction *act, bActionChannel *achan, short select)
 {
        bActionChannel *curchan;
 
@@ -2630,7 +2788,7 @@ void select_actionchannel_by_name (bAction *act, char *name, int select)
 
 /* exported for outliner (ton) */
 /* apparently within active object context */
-int select_channel(bAction *act, bActionChannel *achan, int selectmode) 
+int select_channel (bAction *act, bActionChannel *achan, int selectmode) 
 {
        /* Select the channel based on the selection mode */
        int flag;
@@ -2654,9 +2812,9 @@ int select_channel(bAction *act, bActionChannel *achan, int selectmode)
        return flag;
 }
 
-static int select_constraint_channel(bAction *act, 
-                                     bConstraintChannel *conchan, 
-                                     int selectmode) 
+static int select_constraint_channel (bAction *act, 
+                                      bConstraintChannel *conchan, 
+                                      int selectmode) 
 {
        /* Select the constraint channel based on the selection mode */
        int flag;
@@ -2677,7 +2835,7 @@ static int select_constraint_channel(bAction *act,
        return flag;
 }
 
-int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode) 
+int select_icu_channel (bAction *act, IpoCurve *icu, int selectmode) 
 {
        /* Select the channel based on the selection mode */
        int flag;
@@ -2697,6 +2855,51 @@ int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode)
        return flag;
 }
 
+int select_gplayer_channel (bGPdata *gpd, bGPDlayer *gpl, int selectmode) 
+{
+       /* Select the channel based on the selection mode */
+       int flag;
+
+       switch (selectmode) {
+       case SELECT_ADD:
+               gpl->flag |= GP_LAYER_SELECT;
+               break;
+       case SELECT_SUBTRACT:
+               gpl->flag &= ~GP_LAYER_SELECT;
+               break;
+       case SELECT_INVERT:
+               gpl->flag ^= GP_LAYER_SELECT;
+               break;
+       }
+       flag = (gpl->flag & GP_LAYER_SELECT) ? 1 : 0;
+
+       gpencil_layer_setactive(gpd, gpl);
+
+       return flag;
+}
+
+
+/* select only the active action-group's action channels */
+void select_action_group_channels (bAction *act, bActionGroup *agrp)
+{
+       bActionChannel *achan;
+       
+       /* error checking */
+       if (ELEM(NULL, act, agrp))
+               return;
+       
+       /* deselect all other channels */
+       deselect_actionchannels(act, 0);
+       
+       /* only select channels in group */
+       for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
+               select_channel(act, achan, SELECT_ADD);
+               
+               /* messy... set active bone */
+               select_poseelement_by_name(achan->name, 1);
+       }
+}
+
 /* ----------------------------------------- */
 
 /* De-selects or inverts the selection of Channels in a given Action 
@@ -2819,6 +3022,8 @@ void deselect_action_channels (short mode)
        /* based on type */
        if (datatype == ACTCONT_ACTION)
                deselect_actionchannels(data, mode);
+       else if (datatype == ACTCONT_GPENCIL)
+               deselect_gpencil_layers(data, mode);
        // should shapekey channels be allowed to do this? 
 }
 
@@ -2834,24 +3039,40 @@ void deselect_action_keys (short test, short sel)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
-               
+       
+       /* determine type-based settings */
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+       
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        /* See if we should be selecting or deselecting */
        if (test) {
                for (ale= act_data.first; ale; ale= ale->next) {
-                       if (is_ipo_key_selected(ale->key_data)) {
-                               sel= 0;
-                               break;
+                       if (ale->type == ACTTYPE_GPLAYER) {
+                               if (is_gplayer_frame_selected(ale->data)) {
+                                       sel= 0;
+                                       break;
+                               }
+                       }
+                       else {
+                               if (is_ipo_key_selected(ale->key_data)) {
+                                       sel= 0;
+                                       break;
+                               }
                        }
                }
        }
                
        /* Now set the flags */
        for (ale= act_data.first; ale; ale= ale->next) {
-               set_ipo_key_selection(ale->key_data, sel);
+               if (ale->type == ACTTYPE_GPLAYER)
+                       set_gplayer_frame_selection(ale->data, sel);
+               else
+                       set_ipo_key_selection(ale->key_data, sel);
        }
        
        /* Cleanup */
@@ -2917,6 +3138,12 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
                                        select_icu_bezier_keys(icu, select_mode);
                                }
                                        break;
+                               case ACTTYPE_GPLAYER:
+                               {
+                                       bGPDlayer *gpl= (bGPDlayer *)act_channel;
+                                       select_gpencil_frames(gpl, select_mode);
+                               }
+                                       break;
                        }
                }
                        break;
@@ -2942,12 +3169,16 @@ void selectall_action_keys (short mval[], short mode, short select_mode)
                        rectf.xmax = rectf.xmax + 0.5;
                        
                        /* filter data */
-                       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+                       if (datatype == ACTCONT_GPENCIL)
+                               filter= (ACTFILTER_VISIBLE);
+                       else
+                               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
                        actdata_filter(&act_data, filter, data, datatype);
                                
                        /* Now set the flags */
-                       for (ale= act_data.first; ale; ale= ale->next)
+                       for (ale= act_data.first; ale; ale= ale->next) {
                                borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, select_mode);
+                       }
                        
                        /* Cleanup */
                        BLI_freelistN(&act_data);
@@ -3029,19 +3260,23 @@ void selectkeys_leftright (short leftright, short select_mode)
        }
        
        /* filter data */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
                
        /* select keys on the side where most data occurs */
        for (ale= act_data.first; ale; ale= ale->next) {
-               if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
+               if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
                        borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
-               else {
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
+               else
                        borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
-               }
        }
        
        /* Cleanup */
@@ -3079,7 +3314,10 @@ void nextprev_action_keyframe (short dir)
                return;
        
        /* get list of keyframes that can be used (in global-time) */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
        actdata_filter(&act_data, filter, data, datatype);
        
        for (ale= act_data.first; ale; ale= ale->next) {
@@ -3088,6 +3326,8 @@ void nextprev_action_keyframe (short dir)
                        make_cfra_list(ale->key_data, &elems);
                        actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
                }
+               else if (ale->type == ACTTYPE_GPLAYER)
+                       gplayer_make_cfra_list(ale->key_data, &elems, 0);
                else 
                        make_cfra_list(ale->key_data, &elems);
        }
@@ -3170,11 +3410,20 @@ void column_select_action_keys (int mode)
        /* build list of columns */
        switch (mode) {
                case 1: /* list of selected keys */
-                       filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
-                       actdata_filter(&act_data, filter, data, datatype);
-                       
-                       for (ale= act_data.first; ale; ale= ale->next)
-                               make_sel_cfra_list(ale->key_data, &elems);
+                       if (datatype == ACTCONT_GPENCIL) {
+                               filter= (ACTFILTER_VISIBLE);
+                               actdata_filter(&act_data, filter, data, datatype);
+                               
+                               for (ale= act_data.first; ale; ale= ale->next)
+                                       gplayer_make_cfra_list(ale->data, &elems, 1);
+                       }
+                       else {
+                               filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
+                               actdata_filter(&act_data, filter, data, datatype);
+                               
+                               for (ale= act_data.first; ale; ale= ale->next)
+                                       make_sel_cfra_list(ale->key_data, &elems);
+                       }
                        
                        BLI_freelistN(&act_data);
                        break;
@@ -3202,19 +3451,34 @@ void column_select_action_keys (int mode)
        /* loop through all of the keys and select additional keyframes
         * based on the keys found to be selected above
         */
-       filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU);
+       if (datatype == ACTCONT_GPENCIL)
+               filter= (ACTFILTER_VISIBLE);
+       else
+               filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU);
        actdata_filter(&act_data, filter, data, datatype);
        
        for (ale= act_data.first; ale; ale= ale->next) {
                for (ce= elems.first; ce; ce= ce->next) {
-                       for (icu= ale->key_data; icu; icu= icu->next) {
-                               BezTriple *bezt;
-                               int verts = 0;
+                       /* select elements with frame number matching cfraelem */
+                       if (ale->type == ACTTYPE_GPLAYER) {
+                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
+                               bGPDframe *gpf;
                                
-                               for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) {
-                                       if (bezt) {
-                                               if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) )
-                                                       bezt->f2 |= 1;
+                               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
+                                       if ( (int)ce->cfra == gpf->framenum ) 
+                                               gpf->flag |= GP_FRAME_SELECT;
+                               }
+                       }
+                       else {
+                               for (icu= ale->key_data; icu; icu= icu->next) {
+                                       BezTriple *bezt;
+                                       int verts = 0;
+                                       
+                                       for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) {
+                                               if (bezt) {
+                                                       if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) )
+                                                               bezt->f2 |= 1;
+                                               }
                                        }
                                }
                        }
@@ -3243,7 +3507,7 @@ void borderselect_actionchannels (void)
        /* determine what type of data we are operating on */
        data = get_action_context(&datatype);
        if (data == NULL) return;
-       if (datatype != ACTCONT_ACTION) return;
+       if (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)==0) return;
        
        /* draw and handle the borderselect stuff (ui) and get the select rect */
        if ( (val = get_border(&rect, 3)) ) {
@@ -3315,6 +3579,16 @@ void borderselect_actionchannels (void)
                                                        icu->flag &= ~IPO_SELECT;
                                        }
                                                break;
+                                       case ACTTYPE_GPLAYER: /* grease-pencil layer */
+                                       {
+                                               bGPDlayer *gpl = (bGPDlayer *)ale->data;
+                                               
+                                               if (selectmode == SELECT_ADD)
+                                                       gpl->flag |= GP_LAYER_SELECT;
+                                               else
+                                                       gpl->flag &= ~GP_LAYER_SELECT;
+                                       }
+                                               break;
                                }
                                
                                /* select action-channel 'owner' */
@@ -3431,6 +3705,9 @@ void borderselect_action (void)
                                                        borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
                                        }
                                }
+                               else if (ale->type == ACTTYPE_GPLAYER) {
+                                       borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+                               }
                                break;
                        case ACTEDIT_BORDERSEL_CHA: /* all in channel(s) */
                                if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
@@ -3452,6 +3729,9 @@ void borderselect_action (void)
                                                                select_ipo_bezier_keys(conchan->ipo, selectmode);
                                                }
                                        }
+                                       else if (ale->type == ACTTYPE_GPLAYER) {
+                                               select_gpencil_frames(ale->data, selectmode);
+                                       }
                                }
                                break;
                        default: /* any keyframe inside region defined by region */
@@ -3474,6 +3754,9 @@ void borderselect_action (void)
                                                                borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
                                                }
                                        }
+                                       else if (ale->type == ACTTYPE_GPLAYER) {
+                                               borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+                                       }
                                }
                        }
                        
@@ -3504,6 +3787,8 @@ static void mouse_action (int selectmode)
        bActionChannel *achan= NULL;
        bConstraintChannel *conchan= NULL;
        IpoCurve *icu= NULL;
+       bGPdata *gpd = NULL;
+       bGPDlayer *gpl = NULL;
        TimeMarker *marker, *pmarker;
        
        void *act_channel;
@@ -3514,6 +3799,7 @@ static void mouse_action (int selectmode)
        data = get_action_context(&datatype);
        if (data == NULL) return;
        if (datatype == ACTCONT_ACTION) act= (bAction *)data;
+       if (datatype == ACTCONT_GPENCIL) gpd= (bGPdata *)data;
 
        act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan);
        marker= find_nearest_marker(SCE_MARKERS, 1);
@@ -3586,6 +3872,9 @@ static void mouse_action (int selectmode)
                        case ACTTYPE_GROUP:
                                agrp= (bActionGroup *)act_channel;
                                break;
+                       case ACTTYPE_GPLAYER:
+                               gpl= (bGPDlayer *)act_channel;
+                               break;
                        default:
                                return;
                }
@@ -3609,6 +3898,13 @@ static void mouse_action (int selectmode)
                                        set_active_actiongroup(act, agrp, 1);
                                }
                        }
+                       else if (datatype == ACTCONT_GPENCIL) {
+                               deselect_action_channels(0);
+                               
+                               /* Highlight gpencil layer */
+                               gpl->flag |= GP_LAYER_SELECT;
+                               gpencil_layer_setactive(gpd, gpl);
+                       }
                }
                
                if (icu)
@@ -3625,6 +3921,8 @@ static void mouse_action (int selectmode)
                                        select_ipo_key(conchan->ipo, selx, selectmode);
                        }
                }
+               else if (gpl)
+                       select_gpencil_frame(gpl, selx, selectmode);
                
                std_rmouse_transform(transform_action_keys);
                
@@ -3641,6 +3939,7 @@ static void mouse_action (int selectmode)
 static void mouse_actionchannels (short mval[])
 {
        bAction *act= G.saction->action;
+       bGPdata *gpd= G.saction->gpd;
        void *data, *act_channel;
        short datatype, chantype;
        
@@ -3672,17 +3971,8 @@ static void mouse_actionchannels (short mval[])
                                                select_action_group(act, agrp, SELECT_INVERT);
                                        }
                                        else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) {
-                                               bActionChannel *achan;
-                                               
                                                /* select all in group (and deselect everthing else) */ 
-                                               deselect_actionchannels(act, 0);
-                                               
-                                               for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
-                                                       select_channel(act, achan, SELECT_ADD);
-                                                       
-                                                       /* messy... set active bone */
-                                                       select_poseelement_by_name(achan->name, 1);
-                                               }
+                                               select_action_group_channels(act, agrp);
                                                select_action_group(act, agrp, SELECT_ADD);
                                        }
                                        else {
@@ -3796,6 +4086,24 @@ static void mouse_actionchannels (short mval[])
                                }
                        }
                                break;
+               case ACTTYPE_GPLAYER:
+                       {
+                               bGPDlayer *gpl= (bGPDlayer *)act_channel;
+                               
+                               if (mval[0] >= (NAMEWIDTH-16)) {
+                                       /* toggle lock */
+                                       gpl->flag ^= GP_LAYER_LOCKED;
+                               }
+                               else if (mval[0] >= (NAMEWIDTH-32)) {
+                                       /* toggle hide */
+                                       gpl->flag ^= GP_LAYER_HIDE;
+                               }
+                               else {
+                                       /* select/deselect */
+                                       select_gplayer_channel(gpd, gpl, SELECT_INVERT);
+                               }
+                       }
+                               break;
                default:
                        return;
        }
@@ -4462,7 +4770,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                case RIGHTMOUSE:
                        /* Clicking in the channel area */
                        if ((G.v2d->mask.xmin) && (mval[0] < NAMEWIDTH)) {
-                               if (datatype == ACTCONT_ACTION) {
+                               if (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)) {
                                        /* mouse is over action channels */
                                        if (G.qual == LR_CTRLKEY)
                                                numbuts_action();
@@ -4682,11 +4990,13 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        
                case NKEY:
                        if (G.qual==0) {
-                               numbuts_action();
-                               
-                               /* no panel (yet). current numbuts are not easy to put in panel... */
-                               //add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
-                               //scrarea_queue_winredraw(curarea);
+                               /* panel will not always show useful info! */
+                               if (mval[0] > ACTWIDTH) {
+                                       add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
+                                       scrarea_queue_winredraw(curarea);
+                               }
+                               else 
+                                       numbuts_action();
                        }
                        break;
                        
@@ -4810,8 +5120,12 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                case DELKEY:
                case XKEY:
                        if (okee("Erase selected")) {
-                               if (mval[0] < NAMEWIDTH)
-                                       delete_action_channels();
+                               if (mval[0] < NAMEWIDTH) {
+                                       if (datatype == ACTCONT_ACTION)
+                                               delete_action_channels();
+                                       else if (datatype == ACTCONT_GPENCIL)
+                                               delete_gpencil_layers();
+                               }
                                else
                                        delete_action_keys();