Merging r50522 through r50572 from trunk into soc-2011-tomato
[blender.git] / source / blender / editors / mask / mask_add.c
index 62675635b7b297a8f52354be08f43286ef8e0640..7fe1ac09df652e411881ae834c7d15c57f1f3f35 100644 (file)
 
 #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_scene_types.h"
+#include "DNA_screen_types.h"
 #include "DNA_mask_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 "ED_keyframing.h"
+#include "ED_mask.h"  /* own include */
 
 #include "RNA_access.h"
 #include "RNA_define.h"
 #include "mask_intern.h"  /* own include */
 
 
-static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather,
+static int find_nearest_diff_point(const bContext *C, Mask *mask, const float normal_co[2], int threshold, int feather,
                                    MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r,
-                                   float *u_r, float tangent[2])
+                                   float *u_r, float tangent[2],
+                                   const short use_deform)
 {
+       ScrArea *sa = CTX_wm_area(C);
+       ARegion *ar = CTX_wm_region(C);
+
        MaskLayer *masklay, *point_masklay;
        MaskSpline *point_spline;
        MaskSplinePoint *point = NULL;
        float dist, co[2];
        int width, height;
        float u;
-       float scalex, scaley, aspx, aspy;
+       float scalex, scaley;
 
-       ED_mask_size(C, &width, &height);
-       ED_mask_aspect(C, &aspx, &aspy);
-       ED_mask_pixelspace_factor(C, &scalex, &scaley);
+       ED_mask_get_size(sa, &width, &height);
+       ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
 
        co[0] = normal_co[0] * scalex;
        co[1] = normal_co[1] * scaley;
@@ -86,17 +84,21 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c
 
                for (spline = masklay->splines.first; spline; spline = spline->next) {
                        int i;
+                       MaskSplinePoint *cur_point;
 
-                       for (i = 0; i < spline->tot_point; i++) {
-                               MaskSplinePoint *cur_point = &spline->points[i];
+                       for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points;
+                            i < spline->tot_point;
+                            i++, cur_point++)
+                       {
                                float *diff_points;
-                               int tot_diff_point;
+                               unsigned int tot_diff_point;
 
                                diff_points = BKE_mask_point_segment_diff_with_resolution(spline, cur_point, width, height,
                                                                                          &tot_diff_point);
 
                                if (diff_points) {
-                                       int i, tot_feather_point, tot_point;
+                                       int i, tot_point;
+                                       unsigned int tot_feather_point;
                                        float *feather_points = NULL, *points;
 
                                        if (feather) {
@@ -129,7 +131,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c
 
                                                        point_masklay = masklay;
                                                        point_spline = spline;
-                                                       point = cur_point;
+                                                       point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point;
                                                        dist = cur_dist;
                                                        u = (float)i / tot_point;
 
@@ -156,7 +158,7 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c
                        *point_r = point;
 
                if (u_r) {
-                       u = BKE_mask_spline_project_co(point_spline, point, u, normal_co);
+                       u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
 
                        *u_r = u;
                }
@@ -178,22 +180,20 @@ static int find_nearest_diff_point(bContext *C, Mask *mask, const float normal_c
 
 /******************** add vertex *********************/
 
-static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point,
+static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point,
                                const float point_co[2], const float tangent[2], const float u,
-                               MaskSplinePoint *reference_point, const short reference_adjacent)
+                               MaskSplinePoint *reference_point, const short reference_adjacent,
+                               const float view_zoom)
 {
        MaskSplinePoint *prev_point = NULL;
        MaskSplinePoint *next_point = NULL;
        BezTriple *bezt;
-       int width, height;
        float co[3];
-       const float len = 20.0; /* default length of handle in pixel space */
+       const float len = 10.0; /* default length of handle in pixel space */
 
        copy_v2_v2(co, point_co);
        co[2] = 0.0f;
 
-       ED_mask_size(C, &width, &height);
-
        /* point coordinate */
        bezt = &new_point->bezt;
 
@@ -221,27 +221,21 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask
        /* initial offset for handles */
        if (spline->tot_point == 1) {
                /* first point of splien is aligned horizontally */
-               bezt->vec[0][0] -= len / width;
-               bezt->vec[2][0] += len / width;
+               bezt->vec[0][0] -= len * view_zoom;
+               bezt->vec[2][0] += len * view_zoom;
        }
        else if (tangent) {
                float vec[2];
 
                copy_v2_v2(vec, tangent);
 
-               vec[0] *= width;
-               vec[1] *= height;
-
-               mul_v2_fl(vec, len / len_v2(vec));
-
-               vec[0] /= width;
-               vec[1] /= height;
+               mul_v2_fl(vec, len);
 
                sub_v2_v2(bezt->vec[0], vec);
                add_v2_v2(bezt->vec[2], vec);
 
                if (reference_adjacent) {
-                       BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u);
+                       BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
                }
        }
        else {
@@ -293,8 +287,8 @@ static void setup_vertex_point(bContext *C, Mask *mask, MaskSpline *spline, Mask
                add_v2_v2(bezt->vec[0], vec);
                sub_v2_v2(bezt->vec[2], vec);
 #else
-               BKE_mask_calc_handle_point_auto(mask, spline, new_point, TRUE);
-               BKE_mask_calc_handle_adjacent_interp(mask, spline, new_point, u);
+               BKE_mask_calc_handle_point_auto(spline, new_point, TRUE);
+               BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
 
 #endif
        }
@@ -317,7 +311,8 @@ static void finSelectedSplinePoint(MaskLayer *masklay, MaskSpline **spline, Mask
        *point = NULL;
 
        if (check_active) {
-               if (masklay->act_spline && masklay->act_point) {
+               /* TODO, having an active point but no active spline is possible, why? */
+               if (masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {
                        *spline = masklay->act_spline;
                        *point = masklay->act_point;
                        return;
@@ -367,7 +362,7 @@ static void mask_spline_add_point_at_index(MaskSpline *spline, int point_index)
        spline->tot_point++;
 }
 
-static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2])
+static int add_vertex_subdivide(const bContext *C, Mask *mask, const float co[2])
 {
        MaskLayer *masklay;
        MaskSpline *spline;
@@ -376,7 +371,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2])
        float tangent[2];
        float u;
 
-       if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent)) {
+       if (find_nearest_diff_point(C, mask, co, threshold, FALSE, &masklay, &spline, &point, &u, tangent, TRUE)) {
                MaskSplinePoint *new_point;
                int point_index = point - spline->points;
 
@@ -386,7 +381,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2])
 
                new_point = &spline->points[point_index + 1];
 
-               setup_vertex_point(C, mask, spline, new_point, co, tangent, u, NULL, TRUE);
+               setup_vertex_point(mask, spline, new_point, co, tangent, u, NULL, TRUE, 1.0f);
 
                /* TODO - we could pass the spline! */
                BKE_mask_layer_shape_changed_add(masklay, BKE_mask_layer_shape_spline_to_index(masklay, spline) + point_index + 1, TRUE, TRUE);
@@ -401,7 +396,7 @@ static int add_vertex_subdivide(bContext *C, Mask *mask, const float co[2])
        return FALSE;
 }
 
-static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
+static int add_vertex_extrude(const bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
 {
        MaskSpline *spline;
        MaskSplinePoint *point;
@@ -415,8 +410,6 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
        int do_recalc_src = FALSE;  /* when extruding from endpoints only */
        int do_prev;                /* use prev point rather then next?? */
 
-       ED_mask_select_toggle_all(mask, SEL_DESELECT);
-
        if (!masklay) {
                return FALSE;
        }
@@ -424,6 +417,8 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
                finSelectedSplinePoint(masklay, &spline, &point, TRUE);
        }
 
+       ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
        point_index = (point - spline->points);
 
        MASKPOINT_DESEL_ALL(point);
@@ -431,7 +426,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
        if ((spline->flag & MASK_SPLINE_CYCLIC) ||
            (point_index > 0 && point_index != spline->tot_point - 1))
        {
-               BKE_mask_calc_tangent_polyline(mask, spline, point, tangent_point);
+               BKE_mask_calc_tangent_polyline(spline, point, tangent_point);
                sub_v2_v2v2(tangent_co, co, point->bezt.vec[1]);
 
                if (dot_v2v2(tangent_point, tangent_co) < 0.0f) {
@@ -450,6 +445,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
                do_recalc_src = TRUE;
        }
        else {
+               do_prev = FALSE;  /* quiet warning */
                /* should never get here */
                BLI_assert(0);
        }
@@ -484,7 +480,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
 
        masklay->act_point = new_point;
 
-       setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE);
+       setup_vertex_point(mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE, 1.0f);
 
        if (masklay->splines_shapes.first) {
                point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
@@ -493,7 +489,7 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
 
        if (do_recalc_src) {
                /* TODO, update keyframes in time */
-               BKE_mask_calc_handle_point_auto(mask, spline, ref_point, FALSE);
+               BKE_mask_calc_handle_point_auto(spline, ref_point, FALSE);
        }
 
        WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
@@ -501,13 +497,12 @@ static int add_vertex_extrude(bContext *C, Mask *mask, MaskLayer *masklay, const
        return TRUE;
 }
 
-static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
+static int add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, const float co[2])
 {
        MaskSpline *spline;
        MaskSplinePoint *point;
        MaskSplinePoint *new_point = NULL, *ref_point = NULL;
-
-       ED_mask_select_toggle_all(mask, SEL_DESELECT);
+       float view_zoom;
 
        if (!masklay) {
                /* if there's no masklay currently operationg on, create new one */
@@ -520,6 +515,8 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const flo
                finSelectedSplinePoint(masklay, &spline, &point, TRUE);
        }
 
+       ED_mask_select_toggle_all(mask, SEL_DESELECT);
+
        if (!spline) {
                /* no selected splines in active masklay, create new spline */
                spline = BKE_mask_spline_add(masklay);
@@ -530,7 +527,22 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const flo
 
        masklay->act_point = new_point;
 
-       setup_vertex_point(C, mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE);
+       {
+               ScrArea *sa = CTX_wm_area(C);
+               ARegion *ar = CTX_wm_region(C);
+
+               float zoom_x, zoom_y;
+               /* calc view zoom in a simplistic way */
+               ED_mask_zoom(sa, ar, &zoom_x, &zoom_y);
+
+               view_zoom = zoom_x + zoom_y / 2.0f;
+               view_zoom = 1.0f / view_zoom;
+
+               /* arbitrary but gives good results */
+               view_zoom /= 500.0f;
+       }
+
+       setup_vertex_point(mask, spline, new_point, co, NULL, 0.5f, ref_point, FALSE, view_zoom);
 
        {
                int point_index = (((int)(new_point - spline->points) + 0) % spline->tot_point);
@@ -544,6 +556,7 @@ static int add_vertex_new(bContext *C, Mask *mask, MaskLayer *masklay, const flo
 
 static int add_vertex_exec(bContext *C, wmOperator *op)
 {
+       Scene *scene = CTX_data_scene(C);
        Mask *mask = CTX_data_edit_mask(C);
        MaskLayer *masklay;
 
@@ -557,7 +570,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
 
        RNA_float_get_array(op->ptr, "location", co);
 
-       if (masklay && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {
+       /* TODO, having an active point but no active spline is possible, why? */
+       if (masklay && masklay->act_spline && masklay->act_point && MASKPOINT_ISSEL_ANY(masklay->act_point)) {
 
                /* cheap trick - double click for cyclic */
                MaskSpline *spline = masklay->act_spline;
@@ -578,11 +592,11 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
                                spline->flag |= MASK_SPLINE_CYCLIC;
 
                                /* TODO, update keyframes in time */
-                               BKE_mask_calc_handle_point_auto(mask, spline, point, FALSE);
-                               BKE_mask_calc_handle_point_auto(mask, spline, point_other, FALSE);
+                               BKE_mask_calc_handle_point_auto(spline, point, FALSE);
+                               BKE_mask_calc_handle_point_auto(spline, point_other, FALSE);
 
                                /* TODO: only update this spline */
-                               BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra);
+                               BKE_mask_update_display(mask, CFRA);
 
                                WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
                                return OPERATOR_FINISHED;
@@ -604,16 +618,19 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
        }
 
        /* TODO: only update this spline */
-       BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra);
+       BKE_mask_update_display(mask, CFRA);
 
        return OPERATOR_FINISHED;
 }
 
 static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
+       ScrArea *sa = CTX_wm_area(C);
+       ARegion *ar = CTX_wm_region(C);
+
        float co[2];
 
-       ED_mask_mouse_pos(C, event, co);
+       ED_mask_mouse_pos(sa, ar, event->mval, co);
 
        RNA_float_set_array(op->ptr, "location", co);
 
@@ -630,13 +647,13 @@ void MASK_OT_add_vertex(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = add_vertex_exec;
        ot->invoke = add_vertex_invoke;
-       ot->poll = ED_maskediting_mask_poll;
+       ot->poll = ED_maskedit_mask_poll;
 
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX,
+       RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
                             "Location", "Location of vertex in normalized space", -1.0f, 1.0f);
 }
 
@@ -657,9 +674,14 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
        if (point)
                return OPERATOR_FINISHED;
 
-       if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL)) {
+       if (find_nearest_diff_point(C, mask, co, threshold, TRUE, &masklay, &spline, &point, &u, NULL, TRUE)) {
                Scene *scene = CTX_data_scene(C);
                float w = BKE_mask_point_weight(spline, point, u);
+               float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u);
+
+               if (weight_scalar != 0.0f) {
+                       w = w / weight_scalar;
+               }
 
                BKE_mask_point_add_uw(point, u, w);
 
@@ -677,9 +699,12 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
 
 static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
+       ScrArea *sa = CTX_wm_area(C);
+       ARegion *ar = CTX_wm_region(C);
+
        float co[2];
 
-       ED_mask_mouse_pos(C, event, co);
+       ED_mask_mouse_pos(sa, ar, event->mval, co);
 
        RNA_float_set_array(op->ptr, "location", co);
 
@@ -696,12 +721,12 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = add_feather_vertex_exec;
        ot->invoke = add_feather_vertex_invoke;
-       ot->poll = ED_maskediting_mask_poll;
+       ot->poll = ED_maskedit_mask_poll;
 
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX,
+       RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
                             "Location", "Location of vertex in normalized space", -1.0f, 1.0f);
 }