svn merge ^/trunk/blender -r47603:47611
authorCampbell Barton <ideasman42@gmail.com>
Fri, 8 Jun 2012 14:49:07 +0000 (14:49 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 8 Jun 2012 14:49:07 +0000 (14:49 +0000)
26 files changed:
source/blender/blenkernel/BKE_mask.h
source/blender/blenkernel/intern/mask.c
source/blender/blenkernel/intern/sequencer.c
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/keyframes_draw.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_gpencil.h
source/blender/editors/include/ED_keyframes_draw.h
source/blender/editors/include/ED_mask.h
source/blender/editors/mask/CMakeLists.txt
source/blender/editors/mask/mask_editaction.c [new file with mode: 0644]
source/blender/editors/mask/mask_ops.c
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_action/action_select.c
source/blender/editors/space_action/space_action.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/gpu/intern/gpu_draw.c
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_mask_types.h
source/blender/makesrna/intern/rna_mask.c
source/blender/makesrna/intern/rna_space.c

index 32f86bd3ebec6daf527a1f81e2346c257aa14a33..ec2eb82a9eb4c1ab030b8b2fd7fda0f11ad69632 100644 (file)
@@ -120,7 +120,7 @@ void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *u
 void BKE_mask_update_display(struct Mask *mask, float ctime);
 
 void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const int do_newframe);
-void BKE_mask_evaluate(struct Mask *mask, float ctime, const int do_newframe);
+void BKE_mask_evaluate(struct Mask *mask, const float ctime, const int do_newframe);
 void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene, const int do_newframe);
 void BKE_mask_parent_init(struct MaskParent *parent);
 void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u);
@@ -145,12 +145,13 @@ void BKE_mask_layer_shape_to_mask_interp(struct MaskLayer *masklay,
                                          struct MaskLayerShape *masklay_shape_b,
                                          const float fac);
 struct MaskLayerShape *BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, const int frame);
-int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const int frame,
+int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const float frame,
                                           struct MaskLayerShape **r_masklay_shape_a,
                                           struct MaskLayerShape **r_masklay_shape_b);
 struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame);
 void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape);
 struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, const int frame);
+struct MaskLayerShape *BKE_mask_layer_shape_duplicate(struct MaskLayerShape *masklay_shape);
 void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape);
 void BKE_mask_layer_shape_sort(struct MaskLayer *masklay);
 
index 1f1dc6a0cc83c8f0c97a1385376642ab34c70026..bb2940091e462752716801f7aba13f0a5eb20d0b 100644 (file)
@@ -1463,7 +1463,7 @@ void BKE_mask_spline_ensure_deform(MaskSpline *spline)
        }
 }
 
-void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe)
+void BKE_mask_evaluate(Mask *mask, const float ctime, const int do_newframe)
 {
        MaskLayer *masklay;
 
@@ -1475,7 +1475,7 @@ void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe)
                        MaskLayerShape *masklay_shape_b;
                        int found;
 
-                       if ((found = BKE_mask_layer_shape_find_frame_range(masklay, (int)ctime,
+                       if ((found = BKE_mask_layer_shape_find_frame_range(masklay, ctime,
                                                                           &masklay_shape_a, &masklay_shape_b)))
                        {
                                if (found == 1) {
@@ -1750,7 +1750,7 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int fr
 }
 
 /* when returning 2 - the frame isnt found but before/after frames are */
-int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const int frame,
+int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const float frame,
                                           MaskLayerShape **r_masklay_shape_a,
                                           MaskLayerShape **r_masklay_shape_b)
 {
@@ -1820,6 +1820,19 @@ MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, const int
        return masklay_shape;
 }
 
+MaskLayerShape *BKE_mask_layer_shape_duplicate(MaskLayerShape *masklay_shape)
+{
+       MaskLayerShape *masklay_shape_copy;
+
+       masklay_shape_copy = MEM_dupallocN(masklay_shape);
+
+       if (LIKELY(masklay_shape_copy->data)) {
+               masklay_shape_copy->data = MEM_dupallocN(masklay_shape_copy->data);
+       }
+
+       return masklay_shape_copy;
+}
+
 void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape)
 {
        BLI_remlink(&masklay->splines_shapes, masklay_shape);
index 4f47a7f6f443abde6a596a96fc3964ecbd783c2b..af5b7716bbcca41288dd5eba29119249973129ed 100644 (file)
@@ -2067,7 +2067,7 @@ static ImBuf *seq_render_mask_strip(
                return NULL;
        }
 
-       BKE_mask_evaluate(seq->mask, (int)(seq->mask->sfra + nr), TRUE);
+       BKE_mask_evaluate(seq->mask, seq->mask->sfra + nr, TRUE);
 
        maskbuf = MEM_callocN(sizeof(float) * context.rectx * context.recty, __func__);
 
index 7f7d269a7c3acebcb84de54da59ce1266000f698..f6b301c4594b61d5f175cc1d3750b77c4abfe0d6 100644 (file)
@@ -54,6 +54,7 @@
 #include "DNA_world_types.h"
 #include "DNA_gpencil_types.h"
 #include "DNA_speaker_types.h"
+#include "DNA_mask_types.h"
 
 #include "RNA_access.h"
 
@@ -2516,6 +2517,172 @@ static bAnimChannelType ACF_GPL =
        acf_gpl_setting_ptr             /* pointer for setting */
 };
 
+
+/* Mask Datablock ------------------------------------------- */
+
+/* get backdrop color for mask datablock widget */
+static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
+{
+       /* these are ID-blocks, but not exactly standalone... */
+       UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
+}
+
+// TODO: just get this from RNA?
+static int acf_mask_icon(bAnimListElem *UNUSED(ale))
+{
+       return ICON_GREASEPENCIL; // MASK_TODO - need real icon
+}
+
+/* check if some setting exists for this channel */
+static short acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+{
+       switch (setting) {
+               /* only select and expand supported */
+               case ACHANNEL_SETTING_SELECT:
+               case ACHANNEL_SETTING_EXPAND:
+                       return 1;
+
+               default:
+                       return 0;
+       }
+}
+
+/* get the appropriate flag(s) for the setting when it is valid  */
+static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+{
+       /* clear extra return data first */
+       *neg = 0;
+
+       switch (setting) {
+               case ACHANNEL_SETTING_SELECT: /* selected */
+                       return AGRP_SELECTED;
+
+               case ACHANNEL_SETTING_EXPAND: /* expanded */
+                       return MASK_ANIMF_EXPAND;
+       }
+
+       /* this shouldn't happen */
+       return 0;
+}
+
+/* get pointer to the setting */
+static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type)
+{
+       Mask *mask = (Mask *)ale->data;
+
+       /* all flags are just in mask->flag for now... */
+       return GET_ACF_FLAG_PTR(mask->flag, type);
+}
+
+/* mask datablock type define */
+static bAnimChannelType ACF_MASKDATA =
+{
+       "Mask Datablock",            /* type name */
+
+       acf_mask_color,                  /* backdrop color */
+       acf_group_backdrop,             /* backdrop */
+       acf_generic_indention_0,        /* indent level */
+       acf_generic_group_offset,       /* offset */
+
+       acf_generic_idblock_name,       /* name */
+       acf_generic_idfill_nameprop,    /* name prop */
+       acf_mask_icon,                   /* icon */
+
+       acf_mask_setting_valid,          /* has setting */
+       acf_mask_setting_flag,           /* flag for setting */
+       acf_mask_setting_ptr             /* pointer for setting */
+};
+
+/* Mask Layer ------------------------------------------- */
+
+/* name for grease pencil layer entries */
+static void acf_masklay_name(bAnimListElem *ale, char *name)
+{
+       MaskLayer *masklay = (MaskLayer *)ale->data;
+
+       if (masklay && name)
+               BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
+}
+
+/* name property for grease pencil layer entries */
+static short acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
+{
+       if (ale->data) {
+               RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
+               *prop = RNA_struct_name_property(ptr->type);
+
+               return (*prop != NULL);
+       }
+
+       return 0;
+}
+
+/* check if some setting exists for this channel */
+static short acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
+{
+       switch (setting) {
+               /* unsupported */
+               case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
+               case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
+                       return 0;
+
+               /* always available */
+               default:
+                       return 1;
+       }
+}
+
+/* get the appropriate flag(s) for the setting when it is valid  */
+static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
+{
+       /* clear extra return data first */
+       *neg = 0;
+
+       switch (setting) {
+               case ACHANNEL_SETTING_SELECT: /* selected */
+                       return MASK_LAYERFLAG_SELECT;
+
+//             case ACHANNEL_SETTING_MUTE: /* muted */
+//                     return GP_LAYER_HIDE;
+
+               case ACHANNEL_SETTING_PROTECT: /* protected */
+                       // *neg = 1; - if we change this to edtiability
+                       return MASK_LAYERFLAG_LOCKED;
+
+               default: /* unsupported */
+                       return 0;
+       }
+}
+
+/* get pointer to the setting */
+static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type)
+{
+       MaskLayer *masklay = (MaskLayer *)ale->data;
+
+       /* all flags are just in agrp->flag for now... */
+       return GET_ACF_FLAG_PTR(masklay->flag, type);
+}
+
+/* grease pencil layer type define */
+static bAnimChannelType ACF_MASKLAYER =
+{
+       "Mask Layer",                /* type name */
+
+       acf_generic_channel_color,      /* backdrop color */
+       acf_generic_channel_backdrop,   /* backdrop */
+       acf_generic_indention_flexible, /* indent level */
+       acf_generic_group_offset,       /* offset */
+
+       acf_masklay_name,                   /* name */
+       acf_masklay_name_prop,              /* name prop */
+       NULL,                           /* icon */
+
+       acf_masklay_setting_valid,          /* has setting */
+       acf_masklay_setting_flag,           /* flag for setting */
+       acf_masklay_setting_ptr             /* pointer for setting */
+};
+
+
 /* *********************************************** */
 /* Type Registration and General Access */
 
@@ -2566,6 +2733,9 @@ static void ANIM_init_channel_typeinfo_data(void)
                animchannelTypeInfo[type++] = &ACF_GPD;          /* Grease Pencil Datablock */
                animchannelTypeInfo[type++] = &ACF_GPL;          /* Grease Pencil Layer */
 
+               animchannelTypeInfo[type++] = &ACF_MASKDATA;     /* Mask Datablock */
+               animchannelTypeInfo[type++] = &ACF_MASKLAYER;    /* Mask Layer */
+
                // TODO: these types still need to be implemented!!!
                // probably need a few extra flags for these special cases...
                animchannelTypeInfo[type++] = NULL;              /* NLA Track */
index dc0886a473e420c6a5ffb4bf1e6deafcd9021887..5c57407d14e533b5f88c852347d7b77bf8e6be83 100644 (file)
@@ -43,6 +43,7 @@
 #include "DNA_scene_types.h"
 #include "DNA_key_types.h"
 #include "DNA_gpencil_types.h"
+#include "DNA_mask_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -51,6 +52,7 @@
 #include "BKE_fcurve.h"
 #include "BKE_gpencil.h"
 #include "BKE_context.h"
+#include "BKE_mask.h"
 #include "BKE_global.h"
 
 #include "UI_view2d.h"
@@ -258,6 +260,10 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                        if (ale->flag & GP_LAYER_SELECT)
                                                sel = ACHANNEL_SETFLAG_CLEAR;
                                        break;
+                               case ANIMTYPE_MASKLAYER:
+                                       if (ale->flag & MASK_LAYERFLAG_SELECT)
+                                               sel = ACHANNEL_SETFLAG_CLEAR;
+                                       break;
                        }
                }
        }
@@ -354,6 +360,14 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
                                ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT);
                        }
                        break;
+
+                       case ANIMTYPE_MASKLAYER:
+                       {
+                               MaskLayer *masklay = (MaskLayer *)ale->data;
+
+                               ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT);
+                       }
+                       break;
                }
        }
        
@@ -1055,6 +1069,10 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
                /* Grease Pencil channels */
                printf("Grease Pencil not supported for moving yet\n");
        }
+       else if (ac.datatype == ANIMCONT_MASK) {
+               /* Grease Pencil channels */
+               printf("Mask does not supported for moving yet\n");
+       }
        else if (ac.datatype == ANIMCONT_ACTION) {
                /* Directly rearrange action's channels */
                rearrange_action_channels(&ac, ac.data, mode);
@@ -1205,6 +1223,17 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
                                BLI_freelinkN(&gpd->layers, gpl);
                        }
                        break;
+
+                       case ANIMTYPE_MASKLAYER:
+                       {
+                               /* Grease Pencil layer */
+                               Mask *mask = (Mask *)ale->id;
+                               MaskLayer *masklay = (MaskLayer *)ale->data;
+
+                               /* try to delete the layer's data and the layer itself */
+                               BKE_mask_layer_remove(mask, masklay);
+                       }
+                       break;
                }
        }
        
@@ -2287,6 +2316,36 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
                        notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
                }
                break;
+               case ANIMTYPE_MASKDATABLOCK:
+               {
+                       Mask *mask = (Mask *)ale->data;
+
+                       /* toggle expand
+                        *      - although the triangle widget already allows this, the whole channel can also be used for this purpose
+                        */
+                       mask->flag ^= MASK_ANIMF_EXPAND;
+
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+               }
+               break;
+               case ANIMTYPE_MASKLAYER:
+               {
+                       MaskLayer *masklay = (MaskLayer *)ale->data;
+
+                       /* select/deselect */
+                       if (selectmode == SELECT_INVERT) {
+                               /* invert selection status of this layer only */
+                               masklay->flag ^= MASK_LAYERFLAG_SELECT;
+                       }
+                       else {
+                               /* select layer by itself */
+                               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               masklay->flag |= MASK_LAYERFLAG_SELECT;
+                       }
+
+                       notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+               }
+               break;
                default:
                        if (G.debug & G_DEBUG)
                                printf("Error: Invalid channel type in mouse_anim_channels()\n");
index 160e6957513c20592da9190bffa935c6eab54b2b..752e458ef789286aeaa27f1ab02084175c858e62 100644 (file)
@@ -56,6 +56,7 @@
 #include "DNA_lamp_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_key_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
@@ -86,6 +87,7 @@
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_node.h"
+#include "BKE_mask.h"
 #include "BKE_sequencer.h"
 #include "BKE_utildefines.h"
 
@@ -173,6 +175,22 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
                        ac->mode = saction->mode;
                        return 1;
                        
+               case SACTCONT_MASK: /* Grease Pencil */ // XXX review how this mode is handled...
+                       /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+{
+                       // TODO, other methods to get the mask
+                       // Sequence *seq = BKE_sequencer_active_get(ac->scene);
+                       //MovieClip *clip = ac->scene->clip;
+//                     struct Mask *mask = seq ? seq->mask : NULL;
+
+                       saction->ads.source = (ID *)ac->scene;;
+
+                       ac->datatype = ANIMCONT_MASK;
+                       ac->data = &saction->ads;
+
+                       ac->mode = saction->mode;
+                       return 1;
+}
                case SACTCONT_DOPESHEET: /* DopeSheet */
                        /* update scene-pointer (no need to check for pinning yet, as not implemented) */
                        saction->ads.source = (ID *)ac->scene;
@@ -807,7 +825,18 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
                                ale->datatype = ALE_GPFRAME;
                        }
                        break;
-                               
+
+                       case ANIMTYPE_MASKLAYER:
+                       {
+                               MaskLayer *masklay = (MaskLayer *)data;
+
+                               ale->flag = masklay->flag;
+
+                               ale->key_data = NULL;
+                               ale->datatype = ALE_MASKLAY;
+                       }
+                       break;
+
                        case ANIMTYPE_NLATRACK:
                        {
                                NlaTrack *nlt = (NlaTrack *)data;
@@ -1353,6 +1382,83 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i
        return items;
 }
 
+static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
+{
+       MaskLayer *masklay_act = BKE_mask_layer_active(mask);
+       MaskLayer *masklay;
+       size_t items = 0;
+
+       /* loop over layers as the conditions are acceptable */
+       for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+               /* only if selected */
+               if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay)) ) {
+                       /* only if editable */
+//                     if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+                               /* active... */
+                               if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
+                                       /* add to list */
+                                       ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask);
+
+
+//                                     if (filter_mode & ANIMFILTER_TMP_PEEK)
+//                                             return 1;
+//                                     else {
+//                                             bAnimListElem *ale = make_new_animlistelem(masklay, channel_type, (ID *)owner_id);
+//                                             if (ale) {
+//                                                     BLI_addtail(anim_data, ale);
+//                                                     items ++;
+//                                             }
+//                                     }
+
+                               }
+//                     }
+               }
+       }
+
+       return items;
+}
+
+static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int filter_mode)
+{
+       Mask *mask;
+       size_t items = 0;
+
+       /* for now, grab grease pencil datablocks directly from main */
+       // XXX: this is not good...
+       for (mask = G.main->mask.first; mask; mask = mask->id.next) {
+               ListBase tmp_data = {NULL, NULL};
+               size_t tmp_items = 0;
+
+               /* only show if gpd is used by something... */
+               if (ID_REAL_USERS(mask) < 1)
+                       continue;
+
+               /* add gpencil animation channels */
+               BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask))
+               {
+                       tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
+               }
+               END_ANIMFILTER_SUBCHANNELS;
+
+               /* did we find anything? */
+               if (tmp_items) {
+                       /* include data-expand widget first */
+                       if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+                               /* add gpd as channel too (if for drawing, and it has layers) */
+                               ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL);
+                       }
+
+                       /* now add the list of collected channels */
+                       BLI_movelisttolist(anim_data, &tmp_data);
+                       BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
+                       items += tmp_items;
+               }
+       }
+
+       /* return the number of items added to the list */
+       return items;
+}
+
 /* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */
 // TODO: how to handle group nodes is still unclear...
 static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
@@ -2280,7 +2386,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
                                        items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
                        }
                        break;
-                               
+
                        case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
                        {
                                /* the check for the DopeSheet summary is included here since the summary works here too */
@@ -2294,7 +2400,13 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
                                items = animdata_filter_gpencil(anim_data, data, filter_mode);
                        }
                        break;
-                               
+
+                       case ANIMCONT_MASK:
+                       {
+                               items = animdata_filter_mask(anim_data, data, filter_mode);
+                       }
+                       break;
+
                        case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
                        {
                                /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
index cee8d15a80767460b5f762bd614c1f4d76d63148..e6fc4d5a1682608afb91aada21d65bc377143048 100644 (file)
@@ -209,7 +209,7 @@ static DLRBT_Node *nalloc_ak_masklayshape(void *data)
 
        /* store settings based on state of BezTriple */
        ak->cfra = masklay_shape->frame;
-       ak->sel = (masklay_shape->flag & SELECT) ? SELECT : 0;
+       ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
 
        /* set 'modified', since this is used to identify long keyframes */
        ak->modified = 1;
@@ -224,7 +224,7 @@ static void nupdate_ak_masklayshape(void *node, void *data)
        MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
 
        /* set selection status and 'touched' status */
-       if (masklay_shape->flag & SELECT) ak->sel = SELECT;
+       if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT;
        ak->modified += 1;
 }
 
@@ -818,6 +818,21 @@ void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
        BLI_dlrbTree_free(&keys);
 }
 
+void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos)
+{
+       DLRBT_Tree keys;
+
+       BLI_dlrbTree_init(&keys);
+
+       mask_to_keylist(ads, masklay, &keys);
+
+       BLI_dlrbTree_linkedlist_sync(&keys);
+
+       draw_keylist(v2d, &keys, NULL, ypos, (masklay->flag & MASK_LAYERFLAG_LOCKED));
+
+       BLI_dlrbTree_free(&keys);
+}
+
 /* *************************** Keyframe List Conversions *************************** */
 
 void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
index d91b29bb2816849edcd683b98be1a3b7ffd3856d..24aa88a36bdfa497c134bd351b28e7b82eff199f 100644 (file)
@@ -97,7 +97,8 @@ typedef enum eAnimCont_Types {
        ANIMCONT_FCURVES   = 5, /* animation F-Curves (bDopesheet) */
        ANIMCONT_DRIVERS   = 6, /* drivers (bDopesheet) */
        ANIMCONT_NLA       = 7, /* nla (bDopesheet) */
-       ANIMCONT_CHANNEL   = 8  /* animation channel (bAnimListElem) */
+       ANIMCONT_CHANNEL   = 8, /* animation channel (bAnimListElem) */
+       ANIMCONT_MASK      = 9  /* mask dopesheet */
 } eAnimCont_Types;
 
 /* --------------- Channels -------------------- */
@@ -160,6 +161,9 @@ typedef enum eAnim_ChannelType {
        
        ANIMTYPE_GPDATABLOCK,
        ANIMTYPE_GPLAYER,
+
+       ANIMTYPE_MASKDATABLOCK,
+       ANIMTYPE_MASKLAYER,
        
        ANIMTYPE_NLATRACK,
        ANIMTYPE_NLAACTION,
@@ -173,6 +177,7 @@ typedef enum eAnim_KeyType {
        ALE_NONE = 0,       /* no keyframe data */
        ALE_FCURVE,         /* F-Curve */
        ALE_GPFRAME,        /* Grease Pencil Frames */
+       ALE_MASKLAY,           /* Mask */
        ALE_NLASTRIP,       /* NLA Strips */
 
        ALE_ALL,            /* All channels summary */
@@ -279,6 +284,15 @@ typedef enum eAnimFilter_Flags {
 #define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0)
 #define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT)
 
+/* Mask Only */
+/* Grease Pencil datablock settings */
+#define EXPANDED_MASK(mask) (mask->flag & MASK_ANIMF_EXPAND)
+/* Grease Pencil Layer settings */
+#define EDITABLE_MASK(masklay) ((masklay->flag & MASK_LAYERFLAG_LOCKED) == 0)
+#define SEL_MASKLAY(masklay) (masklay->flag & SELECT)
+
+
+
 /* NLA only */
 #define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
 #define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0)
index 2040d4b9c32a9d693aa808c075e9cbe20cb2b795..80f7fb9d1ed0cc2080f6c595b423d0d85ccceca9 100644 (file)
@@ -83,7 +83,8 @@ void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion
 void gpencil_panel_standard(const struct bContext *C, struct Panel *pa);
 
 /* ----------- Grease-Pencil AnimEdit API ------------------ */
-short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, short (*gpf_cb)(struct bGPDframe *, struct Scene *));
+short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene,
+                            short (*gpf_cb)(struct bGPDframe *, struct Scene *));
 void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel);
 
 short is_gplayer_frame_selected(struct bGPDlayer *gpl);
@@ -93,7 +94,7 @@ void select_gpencil_frame(struct bGPDlayer *gpl, int selx, short select_mode);
 void borderselect_gplayer_frames(struct bGPDlayer *gpl, float min, float max, short select_mode);
 
 void delete_gplayer_frames(struct bGPDlayer *gpl);
-void duplicate_gplayer_frames(struct bGPDlayer *gpd);
+void duplicate_gplayer_frames(struct bGPDlayer *gpl);
 
 void free_gpcopybuf(void);
 void copy_gpdata(void);
index e24c21bc1331e334cf05445b6fdbc4b2d611b6a2..8a65699f4041b1f3e550463c1507bec1f62e4257 100644 (file)
@@ -123,6 +123,8 @@ void draw_summary_channel(struct View2D *v2d, struct bAnimContext *ac, float ypo
 /* Grease Pencil Layer */ 
 // XXX not restored 
 void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos);
+/* Mask Layer */
+void draw_masklay_channel(struct View2D *v2d, struct bDopeSheet *ads, struct MaskLayer *masklay, float ypos);
 
 /* Keydata Generation --------------- */
 /* F-Curve */
index 0c2f68076323a38469a23a12a96d325459990295..bbfc47c582aa9c200d551191d0d19c9b4031daad 100644 (file)
@@ -33,6 +33,7 @@
 
 struct wmKeyConfig;
 struct MaskLayer;
+struct MaskLayerShape;
 
 /* mask_editor.c */
 void ED_operatortypes_mask(void);
@@ -47,4 +48,25 @@ void ED_mask_layer_shape_auto_key(struct MaskLayer *masklay, const int frame);
 int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame);
 int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame);
 
-#endif /* ED_TEXT_H */
+/* ----------- Mask AnimEdit API ------------------ */
+short masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene,
+                              short (*masklay_shape_cb)(struct MaskLayerShape *, struct Scene *));
+void masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, short onlysel);
+
+short is_masklayer_frame_selected(struct MaskLayer *masklay);
+void set_masklayer_frame_selection(struct MaskLayer *masklay, short mode);
+void select_mask_frames(struct MaskLayer *masklay, short select_mode);
+void select_mask_frame(struct MaskLayer *masklay, int selx, short select_mode);
+void borderselect_masklayer_frames(struct MaskLayer *masklay, float min, float max, short select_mode);
+
+void delete_masklayer_frames(struct MaskLayer *masklay);
+void duplicate_masklayer_frames(struct MaskLayer *masklay);
+
+//void free_gpcopybuf(void);
+//void copy_gpdata(void);
+//void paste_gpdata(void);
+
+void snap_masklayer_frames(struct MaskLayer *masklay, short mode);
+void mirror_masklayer_frames(struct MaskLayer *masklay, short mode);
+
+#endif /* __ED_MASK_H__ */
index f15e9c27732cdaa63acf6d34441c04d8dc7f83ff..57be5a2234af9528b94a28d5a463007fb233d8cf 100644 (file)
@@ -40,6 +40,7 @@ set(SRC
        mask_add.c
        mask_draw.c
        mask_edit.c
+       mask_editaction.c
        mask_ops.c
        mask_relationships.c
        mask_select.c
diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c
new file mode 100644 (file)
index 0000000..c773e13
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mask/mask_editaction.c
+ *  \ingroup edgpencil
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_fcurve.h"
+#include "BKE_mask.h"
+
+#include "ED_anim_api.h"
+#include "ED_keyframes_edit.h"
+
+/* ***************************************** */
+/* NOTE ABOUT THIS FILE:
+ *  This file contains code for editing Grease Pencil data in the Action Editor
+ *  as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
+ *  Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
+ */
+/* ***************************************** */
+/* Generics - Loopers */
+
+/* Loops over the gp-frames for a gp-layer, and applies the given callback */
+short masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *))
+{
+       MaskLayerShape *masklay_shape;
+
+       /* error checker */
+       if (masklay == NULL)
+               return 0;
+
+       /* do loop */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+               /* execute callback */
+               if (masklay_shape_cb(masklay_shape, scene))
+                       return 1;
+       }
+
+       /* nothing to return */
+       return 0;
+}
+
+/* ****************************************** */
+/* Data Conversion Tools */
+
+/* make a listing all the gp-frames in a layer as cfraelems */
+void masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel)
+{
+       MaskLayerShape *masklay_shape;
+       CfraElem *ce;
+
+       /* error checking */
+       if (ELEM(NULL, masklay, elems))
+               return;
+
+       /* loop through gp-frames, adding */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+               if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
+                       ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
+
+                       ce->cfra = (float)masklay_shape->frame;
+                       ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0;
+
+                       BLI_addtail(elems, ce);
+               }
+       }
+}
+
+/* ***************************************** */
+/* Selection Tools */
+
+/* check if one of the frames in this layer is selected */
+short is_masklayer_frame_selected(MaskLayer *masklay)
+{
+       MaskLayerShape *masklay_shape;
+
+       /* error checking */
+       if (masklay == NULL)
+               return 0;
+
+       /* stop at the first one found */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+               if (masklay_shape->flag & MASK_SHAPE_SELECT)
+                       return 1;
+       }
+
+       /* not found */
+       return 0;
+}
+
+/* helper function - select gp-frame based on SELECT_* mode */
+static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode)
+{
+       if (masklay_shape == NULL)
+               return;
+
+       switch (select_mode) {
+               case SELECT_ADD:
+                       masklay_shape->flag |= MASK_SHAPE_SELECT;
+                       break;
+               case SELECT_SUBTRACT:
+                       masklay_shape->flag &= ~MASK_SHAPE_SELECT;
+                       break;
+               case SELECT_INVERT:
+                       masklay_shape->flag ^= MASK_SHAPE_SELECT;
+                       break;
+       }
+}
+
+/* set all/none/invert select (like above, but with SELECT_* modes) */
+void select_mask_frames(MaskLayer *masklay, short select_mode)
+{
+       MaskLayerShape *masklay_shape;
+
+       /* error checking */
+       if (masklay == NULL)
+               return;
+
+       /* handle according to mode */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+               masklayshape_select(masklay_shape, select_mode);
+       }
+}
+
+/* set all/none/invert select */
+void set_masklayer_frame_selection(MaskLayer *masklay, short mode)
+{
+       /* error checking */
+       if (masklay == NULL)
+               return;
+
+       /* now call the standard function */
+       select_mask_frames(masklay, mode);
+}
+
+/* select the frame in this layer that occurs on this frame (there should only be one at most) */
+void select_mask_frame(MaskLayer *masklay, int selx, short select_mode)
+{
+       MaskLayerShape *masklay_shape;
+
+       if (masklay == NULL)
+               return;
+
+       /* search through frames for a match */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+               /* there should only be one frame with this frame-number */
+               if (masklay_shape->frame == selx) {
+                       masklayshape_select(masklay_shape, select_mode);
+                       break;
+               }
+       }
+}
+
+/* select the frames in this layer that occur within the bounds specified */
+void borderselect_masklayer_frames(MaskLayer *masklay, float min, float max, short select_mode)
+{
+       MaskLayerShape *masklay_shape;
+
+       if (masklay == NULL)
+               return;
+
+       /* only select those frames which are in bounds */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
+               if (IN_RANGE(masklay_shape->frame, min, max))
+                       masklayshape_select(masklay_shape, select_mode);
+       }
+}
+
+/* ***************************************** */
+/* Frame Editing Tools */
+
+/* Delete selected frames */
+void delete_masklayer_frames(MaskLayer *masklay)
+{
+       MaskLayerShape *masklay_shape, *masklay_shape_next;
+
+       /* error checking */
+       if (masklay == NULL)
+               return;
+
+       /* check for frames to delete */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
+               masklay_shape_next = masklay_shape->next;
+
+               if (masklay_shape->flag & MASK_SHAPE_SELECT)
+                       BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+       }
+}
+
+/* Duplicate selected frames from given gp-layer */
+void duplicate_masklayer_frames(MaskLayer *masklay)
+{
+       MaskLayerShape *masklay_shape, *gpfn;
+
+       /* error checking */
+       if (masklay == NULL)
+               return;
+
+       /* duplicate selected frames  */
+       for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) {
+               gpfn = masklay_shape->next;
+
+               /* duplicate this frame */
+               if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+                       MaskLayerShape *mask_shape_dupe;
+
+                       /* duplicate frame, and deselect self */
+                       mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape);
+                       masklay_shape->flag &= ~MASK_SHAPE_SELECT;
+
+                       // XXX - how to handle duplicate frames?
+                       BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe);
+               }
+       }
+}
index 599f3371cac27c26db6d9e9a92390e2d00dacc29..67fd57ed50bd12d147110b7014d183dbc55bf6bd 100644 (file)
@@ -751,8 +751,6 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
                        if (event->val == KM_RELEASE) {
                                Scene *scene = CTX_data_scene(C);
 
-                               free_slide_point_data(op->customdata);
-
                                /* dont key sliding feather uw's */
                                if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) {
                                        if (IS_AUTOKEY_ON(scene)) {
@@ -760,6 +758,8 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
                                        }
                                }
 
+                               free_slide_point_data(op->customdata);
+
                                WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
                                DAG_id_tag_update(&data->mask->id, 0);
 
index 84ff038a050615bc5fed6ce2b0dc991b029e956b..edec57d9e93eb22b7cb47e645f3b7ac98ef20dca 100644 (file)
@@ -285,6 +285,18 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
                                        else glColor4ub(col2[0], col2[1], col2[2], 0x22);
                                        glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF);
                                        
+                                       /* frames one and higher get a saturated background */
+                                       if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
+                                       else glColor4ub(col2[0], col2[1], col2[2], 0x44);
+                                       glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD,  (float)y + ACHANNEL_HEIGHT_HALF);
+                               }
+                               else if (ac->datatype == ANIMCONT_MASK) {
+                                       /* TODO --- this is a copy of gpencil */
+                                       /* frames less than one get less saturated background */
+                                       if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
+                                       else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+                                       glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF);
+
                                        /* frames one and higher get a saturated background */
                                        if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
                                        else glColor4ub(col2[0], col2[1], col2[2], 0x44);
@@ -340,6 +352,9 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
                                        case ALE_GPFRAME:
                                                draw_gpl_channel(v2d, ads, ale->data, y);
                                                break;
+                                       case ALE_MASKLAY:
+                                               draw_masklay_channel(v2d, ads, ale->data, y);
+                                               break;
                                }
                        }
                }
index 0c32ebe549d0564063b67cf9450549b7eb4ddae9..8b26461cc4f9acb4f920e27237542456d58b40bf 100644 (file)
@@ -44,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"
@@ -64,6 +65,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"
@@ -256,6 +258,19 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
                                        *max = MAX2(*max, gpf->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)
+                               {
+                                       *min = MIN2(*min, masklay_shape->frame);
+                                       *max = MAX2(*max, masklay_shape->frame);
+                               }
+                       }
                        else {
                                FCurve *fcu = (FCurve *)ale->key_data;
                                float tmin, tmax;
@@ -476,11 +491,16 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        
        /* copy keyframes */
-       if (ac.datatype == ANIMCONT_GPENCIL) {
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
                // 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)) {    
                        BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
@@ -521,9 +541,9 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
        ac.reports = op->reports;
        
        /* paste keyframes */
-       if (ac.datatype == ANIMCONT_GPENCIL) {
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
                // FIXME...
-               BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode");
+               BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil or Mask mode");
                return OPERATOR_CANCELLED;
        }
        else {
@@ -625,7 +645,7 @@ 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? */
@@ -671,7 +691,7 @@ static void duplicate_action_keys(bAnimContext *ac)
        int filter;
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       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);
@@ -681,8 +701,12 @@ static void duplicate_action_keys(bAnimContext *ac)
        for (ale = anim_data.first; ale; ale = ale->next) {
                if (ale->type == ANIMTYPE_FCURVE)
                        duplicate_fcurve_keys((FCurve *)ale->key_data);
-               else
+               else if (ale->type == ANIMTYPE_GPLAYER)
                        duplicate_gplayer_frames((bGPDlayer *)ale->data);
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       duplicate_masklayer_frames((MaskLayer *)ale->data);
+               else
+                       BLI_assert(0);
        }
        
        /* free filtered list */
@@ -703,7 +727,7 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
        duplicate_action_keys(&ac);
        
        /* validate keyframes after editing */
-       if (ac.datatype != ANIMCONT_GPENCIL)
+       if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
@@ -744,7 +768,7 @@ static void delete_action_keys(bAnimContext *ac)
        int filter;
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       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);
@@ -752,7 +776,13 @@ static void delete_action_keys(bAnimContext *ac)
        
        /* loop through filtered data and delete selected keys */
        for (ale = anim_data.first; ale; ale = ale->next) {
-               if (ale->type != ANIMTYPE_GPLAYER) {
+               if (ale->type == ANIMTYPE_GPLAYER) {
+                       delete_gplayer_frames((bGPDlayer *)ale->data);
+               }
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       delete_masklayer_frames((MaskLayer *)ale->data);
+               }
+               else {
                        FCurve *fcu = (FCurve *)ale->key_data;
                        AnimData *adt = ale->adt;
                        
@@ -763,8 +793,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 */
@@ -785,7 +813,7 @@ static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
        delete_action_keys(&ac);
        
        /* validate keyframes after editing */
-       if (ac.datatype != ANIMCONT_GPENCIL)
+       if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                ANIM_editkeyframes_refresh(&ac);
        
        /* set notifier that keyframes have changed */
@@ -840,7 +868,7 @@ 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 */
@@ -907,7 +935,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 */
@@ -1014,7 +1042,7 @@ 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 */
@@ -1085,7 +1113,7 @@ 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 */
@@ -1165,7 +1193,7 @@ 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 */
@@ -1236,7 +1264,7 @@ 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 */
@@ -1359,7 +1387,7 @@ static void snap_action_keys(bAnimContext *ac, short mode)
        KeyframeEditFunc edit_cb;
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       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);
@@ -1404,7 +1432,7 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
                
        // XXX...
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get snapping mode */
@@ -1482,7 +1510,7 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
        }
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       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);
@@ -1518,7 +1546,7 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
                
        // XXX...
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                return OPERATOR_PASS_THROUGH;
                
        /* get mirroring mode */
index 0c6b0f5eb3d19776bbbfdaf8b70491e0867bbe60..bd73e35815b1a15569b230cbede037d066ab502f 100644 (file)
@@ -43,6 +43,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"
@@ -55,6 +56,7 @@
 
 #include "ED_anim_api.h"
 #include "ED_gpencil.h"
+#include "ED_mask.h"
 #include "ED_keyframes_draw.h"
 #include "ED_keyframes_edit.h"
 #include "ED_markers.h"
@@ -92,7 +94,7 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
        KeyframeEditFunc test_cb, sel_cb;
        
        /* determine type-based settings */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
        else
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
@@ -112,6 +114,12 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
                                        break;
                                }
                        }
+                       else if (ale->type == ANIMTYPE_MASKLAYER) {
+                               if (is_masklayer_frame_selected(ale->data)) {
+                                       sel = SELECT_SUBTRACT;
+                                       break;
+                               }
+                       }
                        else {
                                if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
                                        sel = SELECT_SUBTRACT;
@@ -128,6 +136,8 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
        for (ale = anim_data.first; ale; ale = ale->next) {
                if (ale->type == ANIMTYPE_GPLAYER)
                        set_gplayer_frame_selection(ale->data, sel);
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       set_masklayer_frame_selection(ale->data, sel);
                else
                        ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); 
        }
@@ -250,6 +260,8 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s
                        /* loop over data selecting */
                        if (ale->type == ANIMTYPE_GPLAYER)
                                borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+                       else if (ale->type == ANIMTYPE_MASKLAYER)
+                               borderselect_masklayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
                        else
                                ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
                }
@@ -400,6 +412,9 @@ static void markers_selectkeys_between(bAnimContext *ac)
                else if (ale->type == ANIMTYPE_GPLAYER) {
                        borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
                }
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       borderselect_masklayer_frames(ale->data, min, max, SELECT_ADD);
+               }
                else {
                        ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                }
@@ -467,7 +482,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
        /* loop through all of the keys and select additional keyframes
         * based on the keys found to be selected above
         */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
        else
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
@@ -489,6 +504,8 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
                        /* select elements with frame number matching cfraelem */
                        if (ale->type == ANIMTYPE_GPLAYER)
                                select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD);
+                       else if (ale->type == ANIMTYPE_MASKLAYER)
+                               select_mask_frame(ale->data, ce->cfra, SELECT_ADD);
                        else
                                ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                }
@@ -755,7 +772,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
        }
        
        /* filter data */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
        else
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
@@ -772,6 +789,8 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
                }
                else if (ale->type == ANIMTYPE_GPLAYER) 
                        borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode);
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       borderselect_masklayer_frames(ale->data, ked.f1, ked.f2, select_mode);
                else
                        ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
        }
@@ -909,6 +928,8 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
        /* select the nominated keyframe on the given frame */
        if (ale->type == ANIMTYPE_GPLAYER)
                select_gpencil_frame(ale->data, selx, select_mode);
+       else if (ale->type == ANIMTYPE_MASKLAYER)
+               select_mask_frame(ale->data, selx, select_mode);
        else
                ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
 }
@@ -933,7 +954,7 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
        /* loop through all of the keys and select additional keyframes
         * based on the keys found to be selected above
         */
-       if (ac->datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
        else
                filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
@@ -951,7 +972,9 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
                /* select elements with frame number matching cfra */
                if (ale->type == ANIMTYPE_GPLAYER)
                        select_gpencil_frame(ale->key_data, selx, select_mode);
-               else 
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       select_mask_frame(ale->key_data, selx, select_mode);
+               else
                        ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
        }
        
@@ -1051,7 +1074,12 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
                        bGPDlayer *gpl = (bGPDlayer *)ale->data;
                        gpl_to_keylist(ads, gpl, &anim_keys);
                }
-               
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       // TODO: why don't we just give masklayers key_data too?
+                       MaskLayer *masklay = (MaskLayer *)ale->data;
+                       mask_to_keylist(ads, masklay, &anim_keys);
+               }
+
                /* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */
                for (ak = anim_keys.root; ak; ak = akn) {
                        if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
@@ -1120,6 +1148,18 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
                                //gpencil_layer_setactive(gpd, gpl);
                        }
                }
+               else if (ac->datatype == ANIMCONT_MASK) {
+                       /* deselect all other channels first */
+                       ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+
+                       /* Highlight GPencil Layer */
+                       if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
+                               MaskLayer *masklay = ale->data;
+
+                               masklay->flag |= MASK_LAYERFLAG_SELECT;
+                               //gpencil_layer_setactive(gpd, gpl);
+                       }
+               }
        }
        
        /* only select keyframes if we clicked on a valid channel and hit something */
index ae4020aaaba1f0f1ee01e8f8d16bbe992bf39275..c8660179945fd6dada876ca87af3382fb64df5e0 100644 (file)
@@ -361,7 +361,7 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn)
                case NC_SCREEN:
                        if (wmn->data == ND_GPENCIL) {
                                /* only handle this event in GPencil mode for performance considerations */
-                               if (saction->mode == SACTCONT_GPENCIL)  
+                               if (saction->mode == SACTCONT_GPENCIL)
                                        ED_area_tag_redraw(sa);
                        }
                        break;
@@ -405,6 +405,18 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn)
                                        break;
                        }
                        break;
+               case NC_MASK:
+                       if (saction->mode == SACTCONT_MASK) {
+                               switch (wmn->data) {
+                                       case ND_DATA:
+                                               ED_area_tag_refresh(sa);
+                                               break;
+                                       default: /* just redrawing the view will do */
+                                               ED_area_tag_redraw(sa);
+                                               break;
+                               }
+                       }
+                       break;
                case NC_NODE:
                        if (wmn->action == NA_SELECTED) {
                                /* selection changed, so force refresh to flush (needs flag set to do syncing) */
index 32a4d4ab1a37a682d932c3db661f0eca9ccbbeff..fdc09c1bed0cde90ad1086080d35e78f7fe65044 100644 (file)
@@ -555,7 +555,7 @@ struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
 /*********************** transform_conversions.c ********** */
 struct ListBase;
 
-void flushTransGPactionData(TransInfo *t);
+void flushTransIntFrameActionData(TransInfo *t);
 void flushTransGraphData(TransInfo *t);
 void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
 void flushTransUVs(TransInfo *t);
index 429a3b3d86ac47291463f2285ddbbb462ebd7ef7..007ec3c5250745490114cdd5e44db8761e7fa0e3 100644 (file)
@@ -2797,6 +2797,99 @@ static void posttrans_gpd_clean (bGPdata *gpd)
        }
 }
 
+
+/* Called by special_aftertrans_update to make sure selected gp-frames replace
+ * any other gp-frames which may reside on that frame (that are not selected).
+ * It also makes sure sorted are still stored in chronological order after
+ * transform.
+ */
+static void posttrans_mask_clean(Mask *mask)
+{
+       MaskLayer *masklay;
+
+       for (masklay = mask->masklayers.first; masklay; masklay= masklay->next) {
+               ListBase sel_buffer = {NULL, NULL};
+               MaskLayerShape *masklay_shape, *masklay_shape_new;
+               MaskLayerShape *masklay_shape_sort, *masklay_shape_sort_new;
+
+               /* loop 1: loop through and isolate selected gp-frames to buffer
+                * (these need to be sorted as they are isolated)
+                */
+               for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape_new) {
+                       short added= 0;
+                       masklay_shape_new= masklay_shape->next;
+
+                       if (masklay_shape->flag & GP_FRAME_SELECT) {
+                               BLI_remlink(&masklay->splines_shapes, masklay_shape);
+
+                               /* find place to add them in buffer
+                                * - go backwards as most frames will still be in order,
+                                *   so doing it this way will be faster
+                                */
+                               for (masklay_shape_sort= sel_buffer.last; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort->prev) {
+                                       /* if current (masklay_shape) occurs after this one in buffer, add! */
+                                       if (masklay_shape_sort->frame < masklay_shape->frame) {
+                                               BLI_insertlinkafter(&sel_buffer, masklay_shape_sort, masklay_shape);
+                                               added= 1;
+                                               break;
+                                       }
+                               }
+                               if (added == 0)
+                                       BLI_addhead(&sel_buffer, masklay_shape);
+                       }
+               }
+
+               /* error checking: it is unlikely, but may be possible to have none selected */
+               if (sel_buffer.first == NULL)
+                       continue;
+
+               /* if all were selected (i.e. masklay->splines_shapes is empty), then just transfer sel-buf over */
+               if (masklay->splines_shapes.first == NULL) {
+                       masklay->splines_shapes.first= sel_buffer.first;
+                       masklay->splines_shapes.last= sel_buffer.last;
+
+                       continue;
+               }
+
+               /* loop 2: remove duplicates of splines_shapes in buffers */
+               for (masklay_shape= masklay->splines_shapes.first; masklay_shape && sel_buffer.first; masklay_shape= masklay_shape_new) {
+                       masklay_shape_new= masklay_shape->next;
+
+                       /* loop through sel_buffer, emptying stuff from front of buffer if ok */
+                       for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort && masklay_shape; masklay_shape_sort= masklay_shape_sort_new) {
+                               masklay_shape_sort_new= masklay_shape_sort->next;
+
+                               /* if this buffer frame needs to go before current, add it! */
+                               if (masklay_shape_sort->frame < masklay_shape->frame) {
+                                       /* transfer buffer frame to splines_shapes list (before current) */
+                                       BLI_remlink(&sel_buffer, masklay_shape_sort);
+                                       BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort);
+                               }
+                               /* if this buffer frame is on same frame, replace current with it and stop */
+                               else if (masklay_shape_sort->frame == masklay_shape->frame) {
+                                       /* transfer buffer frame to splines_shapes list (before current) */
+                                       BLI_remlink(&sel_buffer, masklay_shape_sort);
+                                       BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort);
+
+                                       /* get rid of current frame */
+                                       BKE_mask_layer_shape_unlink(masklay, masklay_shape);
+                               }
+                       }
+               }
+
+               /* if anything is still in buffer, append to end */
+               for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort_new) {
+                       masklay_shape_sort_new= masklay_shape_sort->next;
+
+                       BLI_remlink(&sel_buffer, masklay_shape_sort);
+                       BLI_addtail(&masklay->splines_shapes, masklay_shape_sort);
+               }
+
+               /* NOTE: this is the only difference to grease pencil code above */
+               BKE_mask_layer_shape_sort(masklay);
+       }
+}
+
 /* Called during special_aftertrans_update to make sure selected keyframes replace
  * any other keyframes which may reside on that frame (that is not selected).
  */
@@ -2936,6 +3029,27 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra)
        return count;
 }
 
+/* fully select selected beztriples, but only include if it's on the right side of cfra */
+static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra)
+{
+       MaskLayerShape *masklayer_shape;
+       int count = 0;
+
+       if (masklay == NULL)
+               return count;
+
+       /* only include points that occur on the right side of cfra */
+       for (masklayer_shape= masklay->splines_shapes.first; masklayer_shape; masklayer_shape= masklayer_shape->next) {
+               if (masklayer_shape->flag & MASK_SHAPE_SELECT) {
+                       if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra))
+                               count++;
+               }
+       }
+
+       return count;
+}
+
+
 /* This function assigns the information to transdata */
 static void TimeToTransData(TransData *td, float *time, AnimData *adt)
 {
@@ -2998,7 +3112,7 @@ typedef struct tGPFtransdata {
 } tGPFtransdata;
 
 /* This function helps flush transdata written to tempdata into the gp-frames  */
-void flushTransGPactionData(TransInfo *t)
+void flushTransIntFrameActionData(TransInfo *t)
 {
        tGPFtransdata *tfd;
        int i;
@@ -3049,6 +3163,35 @@ static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl
        return count;
 }
 
+/* refer to comment above #GPLayerToTransData, this is the same but for masks */
+static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra)
+{
+       MaskLayerShape *masklay_shape;
+       int count= 0;
+
+       /* check for select frames on right side of current frame */
+       for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape->next) {
+               if (masklay_shape->flag & MASK_SHAPE_SELECT) {
+                       if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
+                               /* memory is calloc'ed, so that should zero everything nicely for us */
+                               td->val= &tfd->val;
+                               td->ival= (float)masklay_shape->frame;
+
+                               tfd->val= (float)masklay_shape->frame;
+                               tfd->sdata= &masklay_shape->frame;
+
+                               /* advance td now */
+                               td++;
+                               tfd++;
+                               count++;
+                       }
+               }
+       }
+
+       return count;
+}
+
+
 static void createTransActionData(bContext *C, TransInfo *t)
 {
        Scene *scene= t->scene;
@@ -3069,7 +3212,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
                return;
        
        /* filter data */
-       if (ac.datatype == ANIMCONT_GPENCIL)
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
        else
                filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
@@ -3102,8 +3245,12 @@ static void createTransActionData(bContext *C, TransInfo *t)
                
                if (ale->type == ANIMTYPE_FCURVE)
                        count += count_fcurve_keys(ale->key_data, t->frame_side, cfra);
-               else
+               else if (ale->type == ANIMTYPE_GPLAYER)
                        count += count_gplayer_frames(ale->data, t->frame_side, cfra);
+               else if (ale->type == ANIMTYPE_MASKLAYER)
+                       count += count_masklayer_frames(ale->data, t->frame_side, cfra);
+               else
+                       BLI_assert(0);
        }
        
        /* stop if trying to build list if nothing selected */
@@ -3121,7 +3268,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
        td= t->data;
        td2d = t->data2d;
        
-       if (ac.datatype == ANIMCONT_GPENCIL) {
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
                if (t->mode == TFM_TIME_SLIDE) {
                        t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata");
                        tfd= (tGPFtransdata *)((float *)(t->customData) + 2);
@@ -3144,6 +3291,14 @@ static void createTransActionData(bContext *C, TransInfo *t)
                        td += i;
                        tfd += i;
                }
+               else if (ale->type == ANIMTYPE_MASKLAYER) {
+                       MaskLayer *masklay = (MaskLayer *)ale->data;
+                       int i;
+
+                       i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra);
+                       td += i;
+                       tfd += i;
+               }
                else {
                        AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
                        FCurve *fcu= (FCurve *)ale->key_data;
@@ -5004,6 +5159,26 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
                                }
                        }
                }
+               else if (ac.datatype == ANIMCONT_MASK) {
+                       /* remove duplicate frames and also make sure points are in order! */
+                               /* 3 cases here for curve cleanups:
+                                * 1) NOTRANSKEYCULL on     -> cleanup of duplicates shouldn't be done
+                                * 2) canceled == 0        -> user confirmed the transform, so duplicates should be removed
+                                * 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
+                                */
+                       if ((saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
+                               ((canceled == 0) || (duplicate)))
+                       {
+                               Mask *mask;
+
+                               // XXX: BAD! this get gpencil datablocks directly from main db...
+                               // but that's how this currently works :/
+                               for (mask = G.main->mask.first; mask; mask = mask->id.next) {
+                                       if (ID_REAL_USERS(mask))
+                                               posttrans_mask_clean(mask);
+                               }
+                       }
+               }
                
                /* marker transform, not especially nice but we may want to move markers
                 * at the same time as keyframes in the dope sheet. 
@@ -5027,7 +5202,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
                }
                
                /* make sure all F-Curves are set correctly */
-               if (ac.datatype != ANIMCONT_GPENCIL)
+               if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
                        ANIM_editkeyframes_refresh(&ac);
                
                /* clear flag that was set for time-slide drawing */
index 46ee80aff5b0b3b08cadf54cf7affcbad6bfa8d5..1b8cc14ecacb6e1acf0454dc666f663c27d74316 100644 (file)
@@ -350,9 +350,9 @@ static void recalcData_actedit(TransInfo *t)
        ANIM_animdata_context_getdata(&ac);
        
        /* perform flush */
-       if (ac.datatype == ANIMCONT_GPENCIL) {
+       if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
                /* flush transform values back to actual coordinates */
-               flushTransGPactionData(t);
+               flushTransIntFrameActionData(t);
        }
        else {
                /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
index 7ae4aa550f96b451c2231d6e1d9417716c617fc9..3e53f2f3836d62759f336bb16ddebe05d5f06d09 100644 (file)
@@ -230,11 +230,12 @@ static struct GPUTextureState {
        Image *ima, *curima;
 
        int domipmap, linearmipmap;
+       int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */
 
        int alphablend;
        float anisotropic;
        MTFace *lasttface;
-} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, 1.f, NULL};
+} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.f, NULL};
 
 /* Mipmap settings */
 
@@ -256,7 +257,7 @@ void GPU_set_linear_mipmap(int linear)
 
 static int gpu_get_mipmap(void)
 {
-       return GTS.domipmap;
+       return GTS.domipmap && !GTS.texpaint;
 }
 
 static GLenum gpu_get_mipmap_filter(int mag)
@@ -730,6 +731,8 @@ void GPU_paint_set_mipmap(int mipmap)
        if (!GTS.domipmap)
                return;
 
+       GTS.texpaint = !mipmap;
+
        if (mipmap) {
                for (ima=G.main->image.first; ima; ima=ima->id.next) {
                        if (ima->bindcode) {
index b61916f7bfabd65ae9411a406f34c09ceb0d0b9a..08d5743bb888113a2dac143ce2a1d5074ed6872c 100644 (file)
@@ -632,7 +632,9 @@ typedef enum eAnimEdit_Context {
        /* editing of gpencil data */
        SACTCONT_GPENCIL = 2,
        /* dopesheet (default) */
-       SACTCONT_DOPESHEET = 3
+       SACTCONT_DOPESHEET = 3,
+       /* mask */
+       SACTCONT_MASK = 4
 } eAnimEdit_Context;
 
 /* SpaceAction AutoSnap Settings (also used by other Animation Editors) */
index e4c27a57d855221067472008510d8cd895a866d3..20701f9adc0bcb8bb91277e23a891976b4d9c037 100644 (file)
@@ -48,6 +48,9 @@ typedef struct Mask {
        int masklay_tot;      /* total number of mask layers */
 
        int sfra, efra;       /* frames, used by the sequencer */
+
+       int flag;  /* for anim info */
+       int pad;
 } Mask;
 
 typedef struct MaskParent {
@@ -96,7 +99,7 @@ typedef struct MaskLayerShape {
        float *data;             /* u coordinate along spline segment and weight of this point */
        int    tot_vert;         /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */
        int    frame;            /* different flags of this point */
-       char   flag;
+       char   flag;             /* animation flag */
        char   pad[7];
 } MaskLayerShape;
 
@@ -125,9 +128,8 @@ typedef struct MaskLayer {
        char   blend;
        char   blend_flag;
 
-       //char   flag;             /* not used yet */
+       char   flag;             /* for animation */
        char   restrictflag;     /* matching 'Object' flag of the same name - eventually use in the outliner  */
-       char   pad[1];
 } MaskLayer;
 
 /* MaskParent->flag */
@@ -169,4 +171,21 @@ enum {
        MASK_BLENDFLAG_INVERT = (1 << 0)
 };
 
+/* masklay->flag */
+enum {
+       MASK_LAYERFLAG_LOCKED = (1 << 4),
+       MASK_LAYERFLAG_SELECT = (1 << 5)
+};
+
+/* masklay_shape->flag */
+enum {
+       MASK_SHAPE_SELECT = (1 << 0)
+};
+
+
+/* mask->flag */
+enum {
+       MASK_ANIMF_EXPAND = (1 << 4)
+};
+
 #endif // __DNA_MASK_TYPES_H__
index 42c893eca16d08a6d37e555ddac4e9eb1b99c73a..64f1663a52471643faeb0247af6af8df9e7c9513 100644 (file)
@@ -582,6 +582,12 @@ static void rna_def_mask_layer(BlenderRNA *brna)
        RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
        RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
 
+       /* select (for dopesheet)*/
+       prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", MASK_LAYERFLAG_SELECT);
+       RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the DopeSheet");
+//     RNA_def_property_update(prop, NC_SCREEN | ND_MASK, NULL);
+
        /* render settings */
        prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "alpha");
index a57c39967fc8abf4dde5ba809bddca40f8d0c926..6755f7b7e78e2922f10bd261a733582f3b9c89fa 100644 (file)
@@ -2229,6 +2229,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
                {SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"},
                {SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"},
                {SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"},
+               {SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask Editor"},
                {0, NULL, 0, NULL, NULL}
        };