diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-10-30 13:38:45 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-03-28 15:54:38 +0400 |
commit | 1af69b6df3c538bd329201520abaa5058a1ff0ca (patch) | |
tree | 9e926a25b1175d3ae61db584b2d5dde2dd9131e9 /source/blender/editors/mask/mask_draw.c | |
parent | 6e5e3b73f37f952420d87a3d8acd07a7f68dd5a3 (diff) |
Implement asymmetric and free handles type for masks
Summary:
The title actually says it all, it's just possible to
have independent free handles for mask splines. Also
it's now possible to have aligned handles displayed
as independent handles.
Required changes in quite a few places, but they're
rather straightforward.
From user perspective there's one really visible change
which is removed Handle Type menu from the panel. With
asymmetric handles it's not clear which handle type to
display there. So now the only way to change handle type
is via V-key menu.
Rewrote normal evaluation function to make it deal
with new type of handles we support. Now it works in
the following way:
- Offset the original spline by maximal weight
- Calculate vector between corresponding U positions
on offset and original spline
- Normalize this vector.
Seems to be giving more adequate results and doesn't
tend to self-intersect as much as old behavior used to,
There're still some changes which needed to be done, but
which are planned for further patch:
- Support colors and handle size via themes.
- Make handles color-coded, just the same as done for
regular bezier splines in 3D viewport.
Additional changes to make roto workflow even better:
- Use circles to draw handles
- Support AA for handles
- Change click-create-drag to change curvature of the
spline instead of adjusting point position.
Reviewers: campbellbarton
CC: sebastian_k, hype, cronk
Differential Revision: http://developer.blender.org/D121
Diffstat (limited to 'source/blender/editors/mask/mask_draw.c')
-rw-r--r-- | source/blender/editors/mask/mask_draw.c | 192 |
1 files changed, 141 insertions, 51 deletions
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 24fcbd19fc1..12fcd3c1459 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -132,29 +132,122 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co); } +static void draw_circle(const float x, const float y, + const float size, const float xscale, const float yscale) +{ + static GLuint displist = 0; + + /* Initialize round circle shape. */ + if (displist == 0) { + GLUquadricObj *qobj; + + displist = glGenLists(1); + glNewList(displist, GL_COMPILE); + + qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + gluDisk(qobj, 0, 0.7, 8, 1); + gluDeleteQuadric(qobj); + + glEndList(); + } + + glPushMatrix(); + glTranslatef(x, y, 0.0f); + glScalef(1.0f / xscale * size, 1.0f / yscale * size, 1.0f); + glCallList(displist); + glPopMatrix(); +} + +static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point, + const eMaskWhichHandle which_handle, const int draw_type, + const float handle_size, const float xscale, const float yscale, + const float point_pos[2], const float handle_pos[2]) +{ + const BezTriple *bezt = &point->bezt; + char handle_type; + + if (which_handle == MASK_WHICH_HANDLE_STICK || which_handle == MASK_WHICH_HANDLE_LEFT) { + handle_type = bezt->h1; + } + else { + handle_type = bezt->h2; + } + + if (handle_type == HD_VECT) { + return; + } + + /* this could be split into its own loop */ + if (draw_type == MASK_DT_OUTLINE) { + const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff}; + glLineWidth(3); + glColor4ubv(rgb_gray); + glBegin(GL_LINES); + glVertex2fv(point_pos); + glVertex2fv(handle_pos); + glEnd(); + glLineWidth(1); + } + + switch (handle_type) { + case HD_FREE: + UI_ThemeColor(TH_HANDLE_FREE); + break; + case HD_AUTO: + UI_ThemeColor(TH_HANDLE_AUTO); + break; + case HD_ALIGN: + case HD_ALIGN_DOUBLESIDE: + UI_ThemeColor(TH_HANDLE_ALIGN); + break; + } + + glBegin(GL_LINES); + glVertex2fv(point_pos); + glVertex2fv(handle_pos); + glEnd(); + + /* draw handle points */ + if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) { + if (point == mask_layer->act_point) + glColor3f(1.0f, 1.0f, 1.0f); + else + glColor3f(1.0f, 1.0f, 0.0f); + } + else { + glColor3f(0.5f, 0.5f, 0.0f); + } + + draw_circle(handle_pos[0], handle_pos[1], handle_size, xscale, yscale); +} + /* return non-zero if spline is selected */ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline, - const char UNUSED(draw_flag), const char draw_type) + const char draw_flag, const char draw_type, + const float xscale, const float yscale) { const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; + const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; + unsigned char rgb_spline[4]; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); SpaceClip *sc = CTX_wm_space_clip(C); - int undistort = FALSE; + bool undistort = false; - int i, hsize, tot_feather_point; + int i, handle_size, tot_feather_point; float (*feather_points)[2], (*fp)[2]; if (!spline->tot_point) return; if (sc) - undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; + undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; /* TODO, add this to sequence editor */ - hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */ + handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; - glPointSize(hsize); + glPointSize(handle_size); mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline); @@ -202,6 +295,12 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline } MEM_freeN(feather_points); + if (is_smooth) { + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + /* control points */ for (i = 0; i < spline->tot_point; i++) { @@ -210,38 +309,36 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline MaskSplinePoint *point_deform = &points_array[i]; BezTriple *bezt = &point_deform->bezt; - float handle[2]; float vert[2]; - const bool has_handle = BKE_mask_point_has_handle(point); copy_v2_v2(vert, bezt->vec[1]); - BKE_mask_point_handle(point_deform, handle); if (undistort) { mask_point_undistort_pos(sc, vert, vert); - mask_point_undistort_pos(sc, handle, handle); } /* draw handle segment */ - if (has_handle) { - - /* this could be split into its own loop */ - if (draw_type == MASK_DT_OUTLINE) { - const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff}; - glLineWidth(3); - glColor4ubv(rgb_gray); - glBegin(GL_LINES); - glVertex2fv(vert); - glVertex2fv(handle); - glEnd(); - glLineWidth(1); + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + float handle[2]; + BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_STICK, handle); + if (undistort) { + mask_point_undistort_pos(sc, handle, handle); } - - glColor3ubv(rgb_spline); - glBegin(GL_LINES); - glVertex2fv(vert); - glVertex2fv(handle); - glEnd(); + draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK, + draw_type, handle_size, xscale, yscale, vert, handle); + } + else { + float handle_left[2], handle_right[2]; + BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_LEFT, handle_left); + BKE_mask_point_handle(point_deform, MASK_WHICH_HANDLE_RIGHT, handle_right); + if (undistort) { + mask_point_undistort_pos(sc, handle_left, handle_left); + mask_point_undistort_pos(sc, handle_left, handle_left); + } + draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT, + draw_type, handle_size, xscale, yscale, vert, handle_left); + draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT, + draw_type, handle_size, xscale, yscale, vert, handle_right); } /* draw CV point */ @@ -257,26 +354,14 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline glBegin(GL_POINTS); glVertex2fv(vert); glEnd(); - - /* draw handle points */ - if (has_handle) { - if (MASKPOINT_ISSEL_HANDLE(point)) { - if (point == masklay->act_point) - glColor3f(1.0f, 1.0f, 1.0f); - else - glColor3f(1.0f, 1.0f, 0.0f); - } - else { - glColor3f(0.5f, 0.5f, 0.0f); - } - - glBegin(GL_POINTS); - glVertex2fv(handle); - glEnd(); - } } glPointSize(1.0f); + + if (is_smooth) { + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + } } /* #define USE_XOR */ @@ -408,7 +493,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (* static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline *spline, const char draw_flag, const char draw_type, const bool is_active, - int width, int height) + const int width, const int height) { const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height), BKE_mask_spline_resolution(spline, width, height)); @@ -482,7 +567,7 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline } static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type, - int width, int height) + const int width, const int height, const float xscale, const float yscale) { MaskLayer *masklay; int i; @@ -504,7 +589,7 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) { /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(C, masklay, spline, draw_flag, draw_type); + draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale); } /* show undeform for testing */ @@ -514,7 +599,7 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c spline->points_deform = NULL; draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height); // draw_spline_parents(masklay, spline); - draw_spline_points(C, masklay, spline, draw_flag, draw_type); + draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale); spline->points_deform = back; } } @@ -525,16 +610,21 @@ void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type) { ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); Mask *mask = CTX_data_edit_mask(C); int width, height; + float aspx, aspy; + float xscale, yscale; if (!mask) return; ED_mask_get_size(sa, &width, &height); + ED_mask_get_aspect(sa, ar, &aspx, &aspy); + UI_view2d_getscale(&ar->v2d, &xscale, &yscale); - draw_masklays(C, mask, draw_flag, draw_type, width, height); + draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy); } typedef struct ThreadedMaskRasterizeState { @@ -719,7 +809,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, } /* draw! */ - draw_masklays(C, mask, draw_flag, draw_type, width, height); + draw_masklays(C, mask, draw_flag, draw_type, width, height, maxdim * zoomx, maxdim * zoomy); if (do_draw_cb) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); |