shapekeys for masks - this doesnt use existing shapekey code however.
authorCampbell Barton <ideasman42@gmail.com>
Thu, 24 May 2012 13:31:36 +0000 (13:31 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 24 May 2012 13:31:36 +0000 (13:31 +0000)
source/blender/blenkernel/BKE_mask.h
source/blender/blenkernel/intern/mask.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/mask/CMakeLists.txt
source/blender/editors/mask/mask_editor.c
source/blender/editors/mask/mask_intern.h
source/blender/editors/mask/mask_shapekey.c [new file with mode: 0755]
source/blender/makesdna/DNA_mask_types.h

index 361de2c38ce50e77b0ad5ca1b2cff9bc79623167..e09aa9d8355fa034dfcb80d2a355136a2db31a4a 100644 (file)
@@ -31,6 +31,7 @@ struct Main;
 struct Mask;
 struct MaskParent;
 struct MaskObject;
+struct MaskObjectShape;
 struct MaskSpline;
 struct MaskSplinePoint;
 struct MaskSplinePointUW;
@@ -83,8 +84,8 @@ void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *u
 
 /* parenting */
 
-void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime);
-void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene);
+void BKE_mask_evaluate_all_masks(struct Main *bmain, 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_length(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point);
 void BKE_mask_calc_handle_point(struct Mask *mask, struct MaskSpline *spline, struct MaskSplinePoint *point);
@@ -93,6 +94,22 @@ void BKE_mask_get_handle_point_adjacent(struct Mask *mask, struct MaskSpline *sp
                                         struct MaskSplinePoint **r_point_prev, struct MaskSplinePoint **r_point_next);
 void BKE_mask_calc_handles(struct Mask *mask);
 
+/* animation */
+int  BKE_mask_object_shape_totvert(struct MaskObject *maskobj);
+void BKE_mask_object_shape_from_mask(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape);
+void BKE_mask_object_shape_to_mask(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape);
+void BKE_mask_object_shape_to_mask_interp(struct MaskObject *maskobj,
+                                          struct MaskObjectShape *maskobj_shape_a,
+                                          struct MaskObjectShape *maskobj_shape_b,
+                                          const float fac);
+struct MaskObjectShape *BKE_mask_object_shape_find_frame(struct MaskObject *maskobj, int frame);
+int BKE_mask_object_shape_find_frame_range(struct MaskObject *maskobj, int frame,
+                                           struct MaskObjectShape **r_maskobj_shape_a,
+                                           struct MaskObjectShape **r_maskobj_shape_b);
+struct MaskObjectShape *BKE_mask_object_shape_varify_frame(struct MaskObject *maskobj, int frame);
+void BKE_mask_object_shape_unlink(struct MaskObject *maskobj, struct MaskObjectShape *maskobj_shape);
+void BKE_mask_object_shape_sort(struct MaskObject *maskobj);
+
 #define MASKPOINT_ISSEL(p)  ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT)
 #define MASKPOINT_SEL(p)    { (p)->bezt.f1 |=  SELECT; (p)->bezt.f2 |=  SELECT; (p)->bezt.f3 |=  SELECT; } (void)0
 #define MASKPOINT_DESEL(p)  { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0
index 70a83dd51045ad03bea899bebfcdfc1958abbfff..56bf90499e587b035c848ee6c48d1fc51392a461 100644 (file)
@@ -662,10 +662,20 @@ void BKE_mask_spline_free(MaskSpline *spline)
        MEM_freeN(spline);
 }
 
+void BKE_mask_object_shape_free(MaskObjectShape *maskobj_shape)
+{
+       MEM_freeN(maskobj_shape->data);
+
+       MEM_freeN(maskobj_shape);
+}
+
 void BKE_mask_object_free(MaskObject *maskobj)
 {
-       MaskSpline *spline = maskobj->splines.first;
+       MaskSpline *spline;
+       MaskObjectShape *maskobj_shape;
 
+       /* free splines */
+       spline = maskobj->splines.first;
        while (spline) {
                MaskSpline *next_spline = spline->next;
 
@@ -675,6 +685,17 @@ void BKE_mask_object_free(MaskObject *maskobj)
                spline = next_spline;
        }
 
+       /* free animation data */
+       maskobj_shape = maskobj->splines_shapes.first;
+       while (maskobj_shape) {
+               MaskObjectShape *next_maskobj_shape = maskobj_shape->next;
+
+               BLI_remlink(&maskobj->splines_shapes, maskobj_shape);
+               BKE_mask_object_shape_free(maskobj_shape);
+
+               maskobj_shape = next_maskobj_shape;
+       }
+
        MEM_freeN(maskobj);
 }
 
@@ -956,7 +977,7 @@ void BKE_mask_calc_handles(Mask *mask)
        }
 }
 
-void BKE_mask_evaluate(Mask *mask, float ctime)
+void BKE_mask_evaluate(Mask *mask, float ctime, const int do_newframe)
 {
        MaskObject *maskobj;
 
@@ -964,6 +985,40 @@ void BKE_mask_evaluate(Mask *mask, float ctime)
                MaskSpline *spline;
                int i;
 
+               /* animation if available */
+               if (do_newframe) {
+                       MaskObjectShape *maskobj_shape_a;
+                       MaskObjectShape *maskobj_shape_b;
+                       int found;
+
+                       if ((found = BKE_mask_object_shape_find_frame_range(maskobj, (int)ctime,
+                                                                           &maskobj_shape_a, &maskobj_shape_b)))
+                       {
+                               if (found == 1) {
+#if 0
+                                       printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&maskobj->splines_shapes),
+                                              maskobj_shape_a->frame);
+#endif
+
+                                       BKE_mask_object_shape_to_mask(maskobj, maskobj_shape_a);
+                               }
+                               else if (found == 2) {
+                                       float w = maskobj_shape_b->frame - maskobj_shape_a->frame;
+#if 0
+                                       printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&maskobj->splines_shapes),
+                                              maskobj_shape_a->frame, maskobj_shape_b->frame);
+#endif
+                                       BKE_mask_object_shape_to_mask_interp(maskobj, maskobj_shape_a, maskobj_shape_b,
+                                                                            (ctime - maskobj_shape_a->frame) / w);
+                               }
+                               else {
+                                       /* always fail, should never happen */
+                                       BLI_assert(found == 2);
+                               }
+                       }
+               }
+               /* animation done... */
+
                for (spline = maskobj->splines.first; spline; spline = spline->next) {
                        for (i = 0; i < spline->tot_point; i++) {
                                MaskSplinePoint *point = &spline->points[i];
@@ -984,22 +1039,22 @@ void BKE_mask_evaluate(Mask *mask, float ctime)
        BKE_mask_calc_handles(mask);
 }
 
-void BKE_mask_evaluate_all_masks(Main *bmain, float ctime)
+void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const int do_newframe)
 {
        Mask *mask;
 
        for (mask = bmain->mask.first; mask; mask = mask->id.next) {
-               BKE_mask_evaluate(mask, ctime);
+               BKE_mask_evaluate(mask, ctime, do_newframe);
        }
 }
 
-void BKE_mask_update_scene(Main *bmain, Scene *scene)
+void BKE_mask_update_scene(Main *bmain, Scene *scene, const int do_newframe)
 {
        Mask *mask;
 
        for (mask = bmain->mask.first; mask; mask = mask->id.next) {
                if (mask->id.flag & LIB_ID_RECALC) {
-                       BKE_mask_evaluate_all_masks(bmain, CFRA);
+                       BKE_mask_evaluate_all_masks(bmain, CFRA, do_newframe);
                }
        }
 }
@@ -1008,3 +1063,211 @@ void BKE_mask_parent_init(MaskParent *parent)
 {
        parent->id_type = ID_MC;
 }
+
+
+/* *** own animation/shapekey implimentation ***
+ * BKE_mask_object_shape_XXX */
+
+int BKE_mask_object_shape_totvert(MaskObject *maskobj)
+{
+       int tot = 0;
+       MaskSpline *spline;
+
+       for (spline = maskobj->splines.first; spline; spline = spline->next) {
+               tot += spline->tot_point;
+       }
+
+       return tot;
+}
+
+/* these functions match. copy is swapped */
+void BKE_mask_object_shape_from_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape)
+{
+       int tot = BKE_mask_object_shape_totvert(maskobj);
+
+       if (maskobj_shape->tot_vert == tot) {
+               float *fp = maskobj_shape->data;
+
+               MaskSpline *spline;
+               for (spline = maskobj->splines.first; spline; spline = spline->next) {
+                       int i;
+                       for (i = 0; i < spline->tot_point; i++) {
+                               BezTriple *bezt = &spline->points[i].bezt;
+                               /* *** BKE_mask_object_shape_to_mask - swapped *** */
+                               copy_v2_v2(fp, bezt->vec[0]); fp += 2;
+                               copy_v2_v2(fp, bezt->vec[1]); fp += 2;
+                               copy_v2_v2(fp, bezt->vec[2]); fp += 2;
+                               fp[0] = bezt->weight;
+                               fp[1] = bezt->radius;         fp += 2;
+                       }
+               }
+       }
+       else {
+               printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot);
+       }
+}
+
+void BKE_mask_object_shape_to_mask(MaskObject *maskobj, MaskObjectShape *maskobj_shape)
+{
+       int tot = BKE_mask_object_shape_totvert(maskobj);
+
+       if (maskobj_shape->tot_vert == tot) {
+               float *fp = maskobj_shape->data;
+
+               MaskSpline *spline;
+               for (spline = maskobj->splines.first; spline; spline = spline->next) {
+                       int i;
+                       for (i = 0; i < spline->tot_point; i++) {
+                               BezTriple *bezt = &spline->points[i].bezt;
+                               /* *** BKE_mask_object_shape_from_mask - swapped *** */
+                               copy_v2_v2(bezt->vec[0], fp); fp += 2;
+                               copy_v2_v2(bezt->vec[1], fp); fp += 2;
+                               copy_v2_v2(bezt->vec[2], fp); fp += 2;
+                               bezt->weight = fp[0];
+                               bezt->radius = fp[1];         fp += 2;
+                       }
+               }
+       }
+       else {
+               printf("%s: vert mismatch %d != %d\n", __func__, maskobj_shape->tot_vert, tot);
+       }
+}
+
+BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const float b[2],
+                              const float t, const float s)
+{
+       target[0] = s * a[0] + t * b[0];
+       target[1] = s * a[1] + t * b[1];
+}
+
+/* linear interpolation only */
+void BKE_mask_object_shape_to_mask_interp(MaskObject *maskobj,
+                                          MaskObjectShape *maskobj_shape_a,
+                                          MaskObjectShape *maskobj_shape_b,
+                                          const float fac)
+{
+       int tot = BKE_mask_object_shape_totvert(maskobj);
+       printf("%.6f\n", fac);
+       if (maskobj_shape_a->tot_vert == tot && maskobj_shape_b->tot_vert == tot) {
+               float *fp_a = maskobj_shape_a->data;
+               float *fp_b = maskobj_shape_b->data;
+               const float ifac = 1.0f - fac;
+
+               MaskSpline *spline;
+               for (spline = maskobj->splines.first; spline; spline = spline->next) {
+                       int i;
+                       for (i = 0; i < spline->tot_point; i++) {
+                               BezTriple *bezt = &spline->points[i].bezt;
+                               /* *** BKE_mask_object_shape_from_mask - swapped *** */
+                               interp_v2_v2v2_flfl(bezt->vec[0], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2;
+                               interp_v2_v2v2_flfl(bezt->vec[1], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2;
+                               interp_v2_v2v2_flfl(bezt->vec[2], fp_a, fp_b, fac, ifac); fp_a += 2; fp_b += 2;
+                               bezt->weight = (fp_a[0] * ifac) + (fp_b[0] * fac);
+                               bezt->radius = (fp_a[1] * ifac) + (fp_b[1] * fac); fp_a += 2; fp_b += 2;
+                       }
+               }
+       }
+       else {
+               printf("%s: vert mismatch %d != %d != %d\n",
+                      __func__, maskobj_shape_a->tot_vert, maskobj_shape_b->tot_vert, tot);
+       }
+}
+
+MaskObjectShape *BKE_mask_object_shape_find_frame(MaskObject *maskobj, int frame)
+{
+       MaskObjectShape *maskobj_shape;
+
+       for (maskobj_shape = maskobj->splines_shapes.first;
+            maskobj_shape;
+            maskobj_shape = maskobj_shape->next)
+       {
+               if (frame == maskobj_shape->frame) {
+                       return maskobj_shape;
+               }
+               else if (frame > maskobj_shape->frame) {
+                       break;
+               }
+       }
+
+       return NULL;
+}
+
+/* when returning 2 - the frame isnt found but before/after frames are */
+int BKE_mask_object_shape_find_frame_range(MaskObject *maskobj, int frame,
+                                           MaskObjectShape **r_maskobj_shape_a,
+                                           MaskObjectShape **r_maskobj_shape_b)
+{
+       MaskObjectShape *maskobj_shape;
+
+       for (maskobj_shape = maskobj->splines_shapes.first;
+            maskobj_shape;
+            maskobj_shape = maskobj_shape->next)
+       {
+               if (frame == maskobj_shape->frame) {
+                       *r_maskobj_shape_a = maskobj_shape;
+                       *r_maskobj_shape_b = NULL;
+                       return 1;
+               }
+               else if (frame < maskobj_shape->frame) {
+                       if (maskobj_shape->prev) {
+                               *r_maskobj_shape_a = maskobj_shape->prev;
+                               *r_maskobj_shape_b = maskobj_shape;
+                               return 2;
+                       }
+                       else {
+                               *r_maskobj_shape_a = maskobj_shape;
+                               *r_maskobj_shape_b = NULL;
+                               return 1;
+                       }
+               }
+       }
+
+       *r_maskobj_shape_a = NULL;
+       *r_maskobj_shape_b = NULL;
+
+       return 0;
+}
+
+MaskObjectShape *BKE_mask_object_shape_varify_frame(MaskObject *maskobj, int frame)
+{
+       MaskObjectShape *maskobj_shape;
+
+       maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame);
+
+       if (maskobj_shape == NULL) {
+               int tot_vert = BKE_mask_object_shape_totvert(maskobj);
+
+               maskobj_shape = MEM_mallocN(sizeof(MaskObjectShape), __func__);
+               maskobj_shape->frame = frame;
+               maskobj_shape->tot_vert = tot_vert;
+               maskobj_shape->data = MEM_mallocN(tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__);
+
+               BLI_addtail(&maskobj->splines_shapes, maskobj_shape);
+
+               BKE_mask_object_shape_sort(maskobj);
+       }
+
+       return maskobj_shape;
+}
+
+void BKE_mask_object_shape_unlink(MaskObject *maskobj, MaskObjectShape *maskobj_shape)
+{
+       BLI_remlink(&maskobj->splines_shapes, maskobj_shape);
+
+       BKE_mask_object_shape_free(maskobj_shape);
+}
+
+static int mask_object_shape_sort_cb(void *maskobj_shape_a_ptr, void *maskobj_shape_b_ptr)
+{
+       MaskObjectShape *maskobj_shape_a = (MaskObjectShape *)maskobj_shape_a_ptr;
+       MaskObjectShape *maskobj_shape_b = (MaskObjectShape *)maskobj_shape_b_ptr;
+
+       if      (maskobj_shape_a->frame < maskobj_shape_b->frame)  return -1;
+       else if (maskobj_shape_a->frame > maskobj_shape_b->frame)  return  1;
+       else                                                       return  0;
+}
+
+void BKE_mask_object_shape_sort(MaskObject *maskobj)
+{
+       BLI_sortlist(&maskobj->splines_shapes, mask_object_shape_sort_cb);
+}
index ee791ff0a0ac5bd337f76c83f6f1f1af4061c1d3..752203a5453be066fc3da4c17c560e3ba653bc6e 100644 (file)
@@ -1004,7 +1004,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen
        sound_update_scene(scene);
 
        /* update masking curves */
-       BKE_mask_update_scene(bmain, scene);
+       BKE_mask_update_scene(bmain, scene, FALSE);
 }
 
 /* this is called in main loop, doing tagged updates before redraw */
@@ -1075,7 +1075,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
         * so don't call within 'scene_update_tagged_recursive' */
        DAG_scene_update_flags(bmain, sce, lay, TRUE);   // only stuff that moves or needs display still
 
-       BKE_mask_evaluate_all_masks(bmain, ctime);
+       BKE_mask_evaluate_all_masks(bmain, ctime, TRUE);
 
        /* All 'standard' (i.e. without any dependencies) animation is handled here,
         * with an 'local' to 'macro' order of evaluation. This should ensure that
index edea4ccab5bd1cbf8f65347d56321f8119c741d5..4ea7da44f11e4d577dccf408e2ae81fbbfc13b38 100644 (file)
@@ -6197,11 +6197,11 @@ static void direct_link_mask(FileData *fd, Mask *mask)
 
        for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) {
                MaskSpline *spline;
+               MaskObjectShape *maskobj_shape;
 
                link_list(fd, &maskobj->splines);
 
-               spline = maskobj->splines.first;
-               while (spline) {
+               for (spline = maskobj->splines.first; spline; spline = spline->next) {
                        int i;
 
                        spline->points = newdataadr(fd, spline->points);
@@ -6212,8 +6212,12 @@ static void direct_link_mask(FileData *fd, Mask *mask)
                                if (point->tot_uw)
                                        point->uw = newdataadr(fd, point->uw);
                        }
+               }
+
+               link_list(fd, &maskobj->splines_shapes);
 
-                       spline = spline->next;
+               for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) {
+                       maskobj_shape->data = newdataadr(fd, maskobj_shape->data);
                }
 
                maskobj->act_spline = newdataadr(fd, maskobj->act_spline);
index 29cfd7f7f5c95bd34200861803d8a0271d874b3d..7c9945ef51738a986393db7f0499dd33caee8fb2 100644 (file)
@@ -2771,6 +2771,7 @@ static void write_masks(WriteData *wd, ListBase *idbase)
 
                        for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) {
                                MaskSpline *spline;
+                               MaskObjectShape *maskobj_shape;
 
                                writestruct(wd, DATA, "MaskObject", 1, maskobj);
 
@@ -2787,6 +2788,11 @@ static void write_masks(WriteData *wd, ListBase *idbase)
                                                        writestruct(wd, DATA, "MaskSplinePointUW", point->tot_uw, point->uw);
                                        }
                                }
+
+                               for (maskobj_shape = maskobj->splines_shapes.first; maskobj_shape; maskobj_shape = maskobj_shape->next) {
+                                       writestruct(wd, DATA, "MaskObjectShape", 1, maskobj_shape);
+                                       writedata(wd, DATA, maskobj_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, maskobj_shape->data);
+                               }
                        }
                }
 
index 55c31e355363f13d3b25ab0898681f5bda278925..e6f26e32c06ecbdfe0f7fe2db1fd8ca7f3564051 100644 (file)
@@ -42,6 +42,7 @@ set(SRC
        mask_ops.c
        mask_relationships.c
        mask_select.c
+       mask_shapekey.c
 
        mask_intern.h
 )
index eaeb0ab9b7f93b403e538912fc9c0c8f87c7c2e9..749c2c0237e2bd144bc8d13ab5fc72515130cada 100644 (file)
@@ -167,6 +167,10 @@ void ED_operatortypes_mask(void)
        /* relationships */
        WM_operatortype_append(MASK_OT_parent_set);
        WM_operatortype_append(MASK_OT_parent_clear);
+
+       /* shapekeys */
+       WM_operatortype_append(MASK_OT_shape_key_insert);
+       WM_operatortype_append(MASK_OT_shape_key_clear);
 }
 
 void ED_keymap_mask(wmKeyConfig *keyconf)
@@ -210,6 +214,10 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "MASK_OT_parent_clear", PKEY, KM_PRESS, KM_ALT, 0);
 
+       WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0);
+
+
        transform_keymap_for_space(keyconf, keymap, SPACE_CLIP);
 }
 
index 623ef5fd5333ff9cfdfa69606b28f2fbe29ff3cf..fee4b63529d748dd627baf87de0987d949b31604 100644 (file)
@@ -88,4 +88,8 @@ void ED_mask_aspect(struct bContext *C, float *aspx, float *aspy);
 void ED_mask_pixelspace_factor(struct bContext *C, float *scalex, float *scaley);
 void ED_mask_mouse_pos(struct bContext *C, struct wmEvent *event, float co[2]);
 
+/* mask_shapekey.c */
+void MASK_OT_shape_key_insert(struct wmOperatorType *ot);
+void MASK_OT_shape_key_clear(struct wmOperatorType *ot);
+
 #endif /* __MASK_INTERN_H__ */
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
new file mode 100755 (executable)
index 0000000..80ba605
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * ***** 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ *                 Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mask/mask_shapekey.c
+ *  \ingroup edmask
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_mask.h"
+
+#include "DNA_mask_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"  /* SELECT */
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_mask.h"
+#include "ED_clip.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "mask_intern.h"  /* own include */
+
+static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Scene *scene = CTX_data_scene(C);
+       const int frame = CFRA;
+       Mask *mask = CTX_data_edit_mask(C);
+       MaskObject *maskobj;
+
+       for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) {
+               MaskObjectShape *maskobj_shape;
+
+               maskobj_shape = BKE_mask_object_shape_varify_frame(maskobj, frame);
+               BKE_mask_object_shape_from_mask(maskobj, maskobj_shape);
+       }
+
+       WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+       DAG_id_tag_update(&mask->id, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void MASK_OT_shape_key_insert(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Insert Shape Key";
+       ot->description = "";
+       ot->idname = "MASK_OT_shape_key_insert";
+
+       /* api callbacks */
+       ot->exec = mask_shape_key_insert_exec;
+       ot->poll = ED_maskediting_mask_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Scene *scene = CTX_data_scene(C);
+       const int frame = CFRA;
+       Mask *mask = CTX_data_edit_mask(C);
+       MaskObject *maskobj;
+
+       for (maskobj = mask->maskobjs.first; maskobj; maskobj = maskobj->next) {
+               MaskObjectShape *maskobj_shape;
+
+               maskobj_shape = BKE_mask_object_shape_find_frame(maskobj, frame);
+
+               if (maskobj_shape) {
+                       BKE_mask_object_shape_unlink(maskobj, maskobj_shape);
+               }
+       }
+
+       WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
+       DAG_id_tag_update(&mask->id, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void MASK_OT_shape_key_clear(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Clear Shape Key";
+       ot->description = "";
+       ot->idname = "MASK_OT_shape_key_clear";
+
+       /* api callbacks */
+       ot->exec = mask_shape_key_clear_exec;
+       ot->poll = ED_maskediting_mask_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
index 7fb2196e82c51bf350037c5f581c016412e633d0..9f163adc77bbe3a994cfd1efe9615bbfd6658d71 100644 (file)
@@ -85,12 +85,23 @@ typedef struct MaskSpline {
        int weight_interp, pad;  /* weight interpolation */
 } MaskSpline;
 
+/* one per frame */
+typedef struct MaskObjectShape {
+       struct MaskObjectShape *next, *prev;
+
+       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 */
+} MaskObjectShape;
+
 typedef struct MaskObject {
        struct MaskObject *next, *prev;
 
        char name[64];                     /* name of the mask object (64 = MAD_ID_NAME - 2) */
 
        ListBase splines;                  /* list of splines which defines this mask object */
+       ListBase splines_shapes;
+
        struct MaskSpline *act_spline;     /* active spline */
        struct MaskSplinePoint *act_point; /* active point */
 } MaskObject;
@@ -105,4 +116,6 @@ typedef struct MaskObject {
 #define MASK_SPLINE_INTERP_LINEAR   1
 #define MASK_SPLINE_INTERP_EASE     2
 
+#define MASK_OBJECT_SHAPE_ELEM_SIZE 8 /* 3x 2D points + weight + radius == 8 */
+
 #endif // __DNA_MASK_TYPES_H__