mask editing
authorCampbell Barton <ideasman42@gmail.com>
Tue, 5 Jun 2012 09:37:44 +0000 (09:37 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 5 Jun 2012 09:37:44 +0000 (09:37 +0000)
- clear feather weights (alt+s)
- fix for glitch where placing the feather would jitter.

release/scripts/startup/bl_ui/space_clip.py
source/blender/blenkernel/BKE_mask.h
source/blender/blenkernel/intern/mask.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/mask/mask_add.c
source/blender/editors/mask/mask_edit.c
source/blender/editors/mask/mask_intern.h
source/blender/editors/mask/mask_ops.c
source/blender/makesrna/intern/rna_mask.c

index e834712ffe97e3ff46db6fe59cd7ca2d7d98a21c..d09effc8ff3fb283b75183cf05d21756e9fac806 100644 (file)
@@ -63,9 +63,11 @@ class CLIP_HT_header(Header):
                     toolsettings = context.tool_settings
 
                     row = layout.row(align=True)
-                    row.prop(toolsettings, "use_proportional_edit_mask", text="", icon_only=True)
+                    row.prop(toolsettings, "use_proportional_edit_mask",
+                             text="", icon_only=True)
                     if toolsettings.use_proportional_edit_objects:
-                        row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
+                        row.prop(toolsettings, "proportional_edit_falloff",
+                                 text="", icon_only=True)
             elif sc.view == 'GRAPH':
                 row = layout.row(align=True)
 
@@ -289,7 +291,8 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel):
         col.prop(settings, "keyframe_b")
 
         col = layout.column(align=True)
-        col.active = tracking_object.is_camera and not settings.use_tripod_solver
+        col.active = (tracking_object.is_camera and
+                      not settings.use_tripod_solver)
         col.label(text="Refine:")
         col.prop(settings, "refine_intrinsics", text="")
 
@@ -723,13 +726,16 @@ class CLIP_PT_active_mask_point(Panel):
                 clip = parent.id
                 tracking = clip.tracking
 
-                col.prop_search(parent, "parent", tracking, "objects", icon='OBJECT_DATA', text="Object:")
+                col.prop_search(parent, "parent", tracking,
+                                "objects", icon='OBJECT_DATA', text="Object:")
 
                 if parent.parent and parent.parent in tracking.objects:
-                    object = clip.tracking.objects[parent.parent]
-                    col.prop_search(parent, "sub_parent", object, "tracks", icon='ANIM_DATA', text="Track:")
+                    object = tracking.objects[parent.parent]
+                    col.prop_search(parent, "sub_parent", object,
+                                    "tracks", icon='ANIM_DATA', text="Track:")
                 else:
-                    col.prop_search(parent, "sub_parent", clip.tracking, "tracks", icon='ANIM_DATA', text="Track:")
+                    col.prop_search(parent, "sub_parent", tracking,
+                                    "tracks", icon='ANIM_DATA', text="Track:")
 
 
 class CLIP_PT_display(CLIP_PT_clip_view_panel, Panel):
@@ -1210,6 +1216,7 @@ class CLIP_MT_mask(Menu):
         layout.separator()
         layout.operator("mask.cyclic_toggle")
         layout.operator("mask.switch_direction")
+        layout.operator("mask.feather_weight_clear")  # TODO, better place?
 
         layout.separator()
         layout.operator("mask.parent_clear")
index 3f837f995ce23d0bc0d80d5f442978dc8cdc40bc..f426d96cd5efd7981bac7ba18a91ee0cb41ba1e4 100644 (file)
@@ -69,7 +69,14 @@ float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feath
 
 void BKE_mask_point_direction_switch(struct MaskSplinePoint *point);
 void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline);
-float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float start_u, const float co[2]);
+
+typedef enum {
+       MASK_PROJ_NEG = -1,
+       MASK_PROJ_ANY = 0,
+       MASK_PROJ_POS = 1
+} eMaskSign;
+float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point,
+                                 float start_u, const float co[2], const eMaskSign sign);
 
 /* point */
 int BKE_mask_point_has_handle(struct MaskSplinePoint *point);
index b904b78ffddc7aefae74c00bf95b9b8a1a123ebe..99333411d8a1c53cef23c463ef6e1cb51ae7c290 100644 (file)
@@ -410,8 +410,6 @@ void BKE_mask_point_direction_switch(MaskSplinePoint *point)
        }
 }
 
-//typedef (float)[MASK_OBJECT_SHAPE_ELEM_SIZE] MaskLayerShapeElem;
-
 typedef struct MaskLayerShapeElem {
        float value[MASK_OBJECT_SHAPE_ELEM_SIZE];
 } MaskLayerShapeElem;
@@ -467,7 +465,8 @@ void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline)
 }
 
 
-float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2])
+float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point,
+                                 float start_u, const float co[2], const eMaskSign sign)
 {
        const float proj_eps         = 1e-3;
        const float proj_eps_squared = proj_eps * proj_eps;
@@ -475,6 +474,8 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, flo
        float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u;
        float ang = -1.0f;
 
+       BLI_assert(ABS(sign) <= 1); /* (-1, 0, 1) */
+
        while (u1 > 0.0f || u2 < 1.0f) {
                float n1[2], n2[2], co1[2], co2[2];
                float v1[2], v2[2];
@@ -485,20 +486,26 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, flo
                        BKE_mask_point_normal(spline, point, u1, n1);
                        sub_v2_v2v2(v1, co, co1);
 
-                       if (len_squared_v2(v1) > proj_eps_squared) {
-                               ang1 = angle_v2v2(v1, n1);
-                               if (ang1 > M_PI / 2.0f)
-                                       ang1 = M_PI  - ang1;
+                       if ((sign == MASK_PROJ_ANY) ||
+                           ((sign == MASK_PROJ_NEG) && (dot_v2v2(v1, n1) <= 0.0f)) ||
+                           ((sign == MASK_PROJ_POS) && (dot_v2v2(v1, n1) >= 0.0f)))
+                       {
 
-                               if (ang < 0.0f || ang1 < ang) {
-                                       ang = ang1;
+                               if (len_squared_v2(v1) > proj_eps_squared) {
+                                       ang1 = angle_v2v2(v1, n1);
+                                       if (ang1 > M_PI / 2.0f)
+                                               ang1 = M_PI  - ang1;
+
+                                       if (ang < 0.0f || ang1 < ang) {
+                                               ang = ang1;
+                                               u = u1;
+                                       }
+                               }
+                               else {
                                        u = u1;
+                                       break;
                                }
                        }
-                       else {
-                               u = u1;
-                               break;
-                       }
                }
 
                if (u2 <= 1.0f) {
@@ -506,20 +513,26 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, flo
                        BKE_mask_point_normal(spline, point, u2, n2);
                        sub_v2_v2v2(v2, co, co2);
 
-                       if (len_squared_v2(v2) > proj_eps_squared) {
-                               ang2 = angle_v2v2(v2, n2);
-                               if (ang2 > M_PI / 2.0f)
-                                       ang2 = M_PI  - ang2;
+                       if ((sign == MASK_PROJ_ANY) ||
+                           ((sign == MASK_PROJ_NEG) && (dot_v2v2(v2, n2) <= 0.0f)) ||
+                           ((sign == MASK_PROJ_POS) && (dot_v2v2(v2, n2) >= 0.0f)))
+                       {
+
+                               if (len_squared_v2(v2) > proj_eps_squared) {
+                                       ang2 = angle_v2v2(v2, n2);
+                                       if (ang2 > M_PI / 2.0f)
+                                               ang2 = M_PI  - ang2;
 
-                               if (ang2 < ang) {
-                                       ang = ang2;
+                                       if (ang2 < ang) {
+                                               ang = ang2;
+                                               u = u2;
+                                       }
+                               }
+                               else {
                                        u = u2;
+                                       break;
                                }
                        }
-                       else {
-                               u = u2;
-                               break;
-                       }
                }
 
                u1 -= du;
index daba096696c7da6bfda440194c6978b81e547c64..2d9c6ee76572e89e4b13283bfe722c33bc7cc0ee 100644 (file)
@@ -2242,7 +2242,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
                }
        }
        else if (itemptr->type == &RNA_MaskLayer) {
-               split = uiLayoutSplit(sub, 0.66f, 0);
+               split = uiLayoutSplit(sub, 0.5f, 0);
 
                uiItemL(split, name, icon);
 
index cdfdde4ef319c50541c6ad76c6206dd6dcd6333d..82f82862577909030fc38b857d1ecbcc4faa4e8b 100644 (file)
@@ -150,7 +150,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;
                }
index 9a32cff04c302b42af8ede92d33edb440f73bdbc..34d297155f981123ff7910f6c1597d1ca106263f 100644 (file)
@@ -212,6 +212,9 @@ void ED_operatortypes_mask(void)
        WM_operatortype_append(MASK_OT_hide_view_clear);
        WM_operatortype_append(MASK_OT_hide_view_set);
 
+       /* feather */
+       WM_operatortype_append(MASK_OT_feather_weight_clear);
+
        /* shape */
        WM_operatortype_append(MASK_OT_slide_point);
        WM_operatortype_append(MASK_OT_cyclic_toggle);
@@ -293,6 +296,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
        WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0);
        WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0);
        WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0);
 
        /* relationships */
        WM_keymap_add_item(keymap, "MASK_OT_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
index d2efab8613a1d2af327adc46137b6c6d97cf9675..9ac55f22fd9557d388a00bf99a3ca68f6f7b3403 100644 (file)
@@ -54,6 +54,7 @@ void MASK_OT_delete(struct wmOperatorType *ot);
 
 void MASK_OT_hide_view_clear(struct wmOperatorType *ot);
 void MASK_OT_hide_view_set(struct wmOperatorType *ot);
+void MASK_OT_feather_weight_clear(struct wmOperatorType *ot);
 void MASK_OT_switch_direction(struct wmOperatorType *ot);
 
 void MASK_OT_handle_type_set(struct wmOperatorType *ot);
index a0c79f4c2c993847deca5b14058d05839c881cc7..dea5345c69fdb8ca007d1d37b3a28173aab7f9a9 100644 (file)
@@ -355,10 +355,12 @@ void MASK_OT_layer_remove(wmOperatorType *ot)
 
 /******************** slide *********************/
 
-#define SLIDE_ACTION_NONE       0
-#define SLIDE_ACTION_POINT      1
-#define SLIDE_ACTION_HANDLE     2
-#define SLIDE_ACTION_FEATHER    3
+enum {
+       SLIDE_ACTION_NONE    = 0,
+       SLIDE_ACTION_POINT   = 1,
+       SLIDE_ACTION_HANDLE  = 2,
+       SLIDE_ACTION_FEATHER = 3
+};
 
 typedef struct SlidePointData {
        int action;
@@ -648,7 +650,29 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
                                add_v2_v2v2(offco, data->feather, dco);
 
                                if (data->uw) {
-                                       float u = BKE_mask_spline_project_co(data->spline, data->point, data->uw->u, offco);
+                                       /* project on both sides and find the closest one,
+                                        * prevents flickering when projecting onto both sides can happen */
+                                       const float u_pos = BKE_mask_spline_project_co(data->spline, data->point,
+                                                                                      data->uw->u, offco, MASK_PROJ_NEG);
+                                       const float u_neg = BKE_mask_spline_project_co(data->spline, data->point,
+                                                                                      data->uw->u, offco, MASK_PROJ_POS);
+                                       float dist_pos = FLT_MAX;
+                                       float dist_neg = FLT_MAX;
+                                       float co_pos[2];
+                                       float co_neg[2];
+                                       float u;
+
+                                       if (u_pos > 0.0f && u_pos < 1.0f) {
+                                               BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
+                                               dist_pos = len_squared_v2v2(offco, co_pos);
+                                       }
+
+                                       if (u_neg > 0.0f && u_neg < 1.0f) {
+                                               BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
+                                               dist_neg = len_squared_v2v2(offco, co_neg);
+                                       }
+
+                                       u = dist_pos < dist_neg ? u_pos : u_neg;
 
                                        if (u > 0.0f && u < 1.0f) {
                                                data->uw->u = u;
@@ -1165,5 +1189,61 @@ void MASK_OT_hide_view_set(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
+}
+
+
+static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Mask *mask = CTX_data_edit_mask(C);
+       MaskLayer *masklay;
+       int changed = FALSE;
+       int i;
+
+       for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+               MaskSpline *spline;
+
+               if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) {
+                       continue;
+               }
+
+               for (spline = masklay->splines.first; spline; spline = spline->next) {
+                       for (i = 0; i < spline->tot_point; i++) {
+                               MaskSplinePoint *point = &spline->points[i];
+
+                               if (MASKPOINT_ISSEL_ANY(point)) {
+                                       BezTriple *bezt = &point->bezt;
+                                       bezt->weight = 0.0f;
+                                       changed = TRUE;
+                               }
+                       }
+               }
+       }
+
+       if (changed) {
+               /* TODO: only update edited splines */
+               BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra);
 
+               WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
+               DAG_id_tag_update(&mask->id, 0);
+
+               return OPERATOR_FINISHED;
+       }
+       else {
+               return OPERATOR_CANCELLED;
+       }
+}
+
+void MASK_OT_feather_weight_clear(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Clear Feather Weight";
+       ot->description = "Reset the feather weight to zero";
+       ot->idname = "MASK_OT_feather_weight_clear";
+
+       /* api callbacks */
+       ot->exec = mask_feather_weight_clear_exec;
+       ot->poll = ED_maskedit_mask_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
index 1532e2e71998ebad0b838bfb5a1e24fc7b6e2542..51d370d5a886548a75427cc08bc4884149751efd 100644 (file)
@@ -583,7 +583,7 @@ static void rna_def_mask_layer(BlenderRNA *brna)
 
        prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MASK_BLENDFLAG_INVERT);
-       RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport");
+       RNA_def_property_ui_text(prop, "Restrict View", "Invert the mask black/white");
        RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL);
 
 }