shapekeys for masks - this doesnt use existing shapekey code however.

This commit is contained in:
Campbell Barton
2012-05-24 13:31:36 +00:00
parent c8e8a68543
commit 3e1df2d12e
10 changed files with 459 additions and 13 deletions

View 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

View 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);
}

View 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

View 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);
}
}
spline = spline->next;
link_list(fd, &maskobj->splines_shapes);
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);

View 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);
}
}
}

View File

@@ -42,6 +42,7 @@ set(SRC
mask_ops.c
mask_relationships.c
mask_select.c
mask_shapekey.c
mask_intern.h
)

View 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);
}

View 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__ */

View File

@@ -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;
}

View 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__