Implement asymmetric and free handles type for masks
[blender.git] / source / blender / editors / mask / mask_draw.c
index 24fcbd19fc1f6c51cd70abe23b8ab287b0b83f3b..12fcd3c14598e5dcabcaa6ba2753086f8b64de60 100644 (file)
@@ -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);