Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/mask/mask_add.c24
-rw-r--r--source/blender/editors/mask/mask_edit.c2
-rw-r--r--source/blender/editors/mask/mask_intern.h12
-rw-r--r--source/blender/editors/mask/mask_ops.c248
4 files changed, 278 insertions, 8 deletions
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index ecaa73754ba..d2c1d844326 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -54,10 +54,16 @@
#include "mask_intern.h" /* own include */
-static bool find_nearest_diff_point(const bContext *C, Mask *mask, const float normal_co[2], int threshold, bool feather,
- MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r,
- float *u_r, float tangent[2],
- const bool use_deform)
+bool ED_mask_find_nearest_diff_point(const bContext *C,
+ struct Mask *mask,
+ const float normal_co[2],
+ int threshold, bool feather,
+ MaskLayer **masklay_r,
+ MaskSpline **spline_r,
+ MaskSplinePoint **point_r,
+ float *u_r, float tangent[2],
+ const bool use_deform,
+ const bool use_project)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -135,7 +141,6 @@ static bool find_nearest_diff_point(const bContext *C, Mask *mask, const float n
point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point;
dist = cur_dist;
u = (float)j / tot_point;
-
}
}
@@ -159,7 +164,10 @@ static bool find_nearest_diff_point(const bContext *C, Mask *mask, const float n
*point_r = point;
if (u_r) {
- u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
+ /* TODO(sergey): Projection fails in some weirdo cases.. */
+ if (use_project) {
+ u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY);
+ }
*u_r = u;
}
@@ -332,7 +340,7 @@ static bool add_vertex_subdivide(const 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, true)) {
+ if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, false, &masklay, &spline, &point, &u, tangent, true, true)) {
MaskSplinePoint *new_point;
int point_index = point - spline->points;
@@ -617,7 +625,7 @@ 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, true)) {
+ if (ED_mask_find_nearest_diff_point(C, mask, co, threshold, true, &masklay, &spline, &point, &u, NULL, true, 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);
diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c
index e27f36e5a4c..d94a1906a84 100644
--- a/source/blender/editors/mask/mask_edit.c
+++ b/source/blender/editors/mask/mask_edit.c
@@ -438,6 +438,7 @@ void ED_operatortypes_mask(void)
/* shape */
WM_operatortype_append(MASK_OT_slide_point);
+ WM_operatortype_append(MASK_OT_slide_spline_curvature);
WM_operatortype_append(MASK_OT_cyclic_toggle);
WM_operatortype_append(MASK_OT_handle_type_set);
@@ -534,6 +535,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf)
/* shape */
WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "MASK_OT_slide_point", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MASK_OT_slide_spline_curvature", ACTIONMOUSE, 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_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
// WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h
index 369d3aa1c6e..6899cf7e6f5 100644
--- a/source/blender/editors/mask/mask_intern.h
+++ b/source/blender/editors/mask/mask_intern.h
@@ -40,6 +40,17 @@ struct wmOperatorType;
/* internal exports only */
/* mask_add.c */
+bool ED_mask_find_nearest_diff_point(const struct bContext *C,
+ struct Mask *mask,
+ const float normal_co[2],
+ int threshold, bool feather,
+ struct MaskLayer **masklay_r,
+ struct MaskSpline **spline_r,
+ struct MaskSplinePoint **point_r,
+ float *u_r, float tangent[2],
+ const bool use_deform,
+ const bool use_project);
+
void MASK_OT_add_vertex(struct wmOperatorType *ot);
void MASK_OT_add_feather_vertex(struct wmOperatorType *ot);
void MASK_OT_primitive_circle_add(struct wmOperatorType *ot);
@@ -55,6 +66,7 @@ void MASK_OT_layer_remove(struct wmOperatorType *ot);
void MASK_OT_cyclic_toggle(struct wmOperatorType *ot);
void MASK_OT_slide_point(struct wmOperatorType *ot);
+void MASK_OT_slide_spline_curvature(struct wmOperatorType *ot);
void MASK_OT_delete(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 775859ba1ef..e16c747e75c 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -1031,6 +1031,254 @@ void MASK_OT_slide_point(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/******************** slide spline curvature *********************/
+
+typedef struct SlideSplineCurvatureData {
+ Mask *mask;
+ MaskSpline *spline;
+ MaskSplinePoint *point;
+ float u;
+ bool accurate;
+
+ BezTriple *adjust_bezt;
+ BezTriple bezt_backup;
+ float initial_coord[2];
+
+ float P0[2], P1[2], P2[2], P3[3];
+} SlideSplineCurvatureData;
+
+static void cancel_slide_spline_curvature(SlideSplineCurvatureData *slide_data)
+{
+ *slide_data->adjust_bezt = slide_data->bezt_backup;
+}
+
+
+static void free_slide_spline_curvature_data(SlideSplineCurvatureData *slide_data)
+{
+ MEM_freeN(slide_data);
+}
+
+static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ float co[2];
+ const float threshold = 19;
+
+ ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
+
+ if (ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL)) {
+ return false;
+ }
+
+ if (ED_mask_feather_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL, NULL)) {
+ return false;
+ }
+
+ return true;
+}
+
+static SlideSplineCurvatureData *slide_spline_curvature_customdata(
+ bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const float threshold = 19;
+
+ Mask *mask = CTX_data_edit_mask(C);
+ SlideSplineCurvatureData *slide_data;
+ MaskLayer *mask_layer;
+ MaskSpline *spline;
+ MaskSplinePoint *point;
+ float u, co[2];
+ BezTriple *next_bezt;
+
+ (void) op;
+
+ ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
+
+ if (!ED_mask_find_nearest_diff_point(C, mask, co, threshold, false,
+ &mask_layer, &spline, &point, &u,
+ NULL, true, false))
+ {
+ return NULL;
+ }
+
+ next_bezt = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
+ if (next_bezt == NULL) {
+ return NULL;
+ }
+
+ slide_data = MEM_callocN(sizeof(SlideSplineCurvatureData), "slide curvature slide");
+ slide_data->mask = mask;
+ slide_data->spline = spline;
+ slide_data->point = point;
+ slide_data->u = u;
+ copy_v2_v2(slide_data->initial_coord, co);
+
+ copy_v2_v2(slide_data->P0, point->bezt.vec[1]);
+ copy_v2_v2(slide_data->P1, point->bezt.vec[2]);
+ copy_v2_v2(slide_data->P2, next_bezt->vec[0]);
+ copy_v2_v2(slide_data->P3, next_bezt->vec[1]);
+
+ /* Depending to which end we're closer to adjust either left or right side of the spline. */
+ if (u <= 0.5f) {
+ slide_data->adjust_bezt = &point->bezt;
+ }
+ else {
+ slide_data->adjust_bezt = next_bezt;
+ }
+
+ /* Data needed for restoring state. */
+ slide_data->bezt_backup = *slide_data->adjust_bezt;
+
+ /* Let's dont touch other side of the point for now, so set handle to FREE. */
+ if (u < 0.5f) {
+ if (slide_data->adjust_bezt->h2 <= HD_VECT) {
+ slide_data->adjust_bezt->h2 = HD_FREE;
+ }
+ }
+ else {
+ if (slide_data->adjust_bezt->h1 < HD_VECT) {
+ slide_data->adjust_bezt->h1 = HD_FREE;
+ }
+ }
+
+ /* Change selection */
+ ED_mask_select_toggle_all(mask, SEL_DESELECT);
+ slide_data->adjust_bezt->f2 |= SELECT;
+ if (u < 0.5f) {
+ slide_data->adjust_bezt->f3 |= SELECT;
+ }
+ else {
+ slide_data->adjust_bezt->f1 |= SELECT;
+ }
+ mask_layer->act_spline = spline;
+ mask_layer->act_point = point;
+ ED_mask_select_flush_all(mask);
+
+ return slide_data;
+}
+
+static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Mask *mask = CTX_data_edit_mask(C);
+ SlideSplineCurvatureData *slide_data;
+
+ if (mask == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Be sure we don't conflict with point slide here. */
+ if (!slide_spline_curvature_check(C, event)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ slide_data = slide_spline_curvature_customdata(C, op, event);
+ if (slide_data != NULL) {
+ op->customdata = slide_data;
+ WM_event_add_modal_handler(C, op);
+ WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SlideSplineCurvatureData *slide_data = (SlideSplineCurvatureData *) op->customdata;
+
+ switch (event->type) {
+ case LEFTSHIFTKEY:
+ case RIGHTSHIFTKEY:
+ if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
+ slide_data->accurate = (event->val == KM_PRESS);
+
+ /* fall-through */ /* update CV position */
+ case MOUSEMOVE:
+ {
+ float B[2];
+ float u = slide_data->u;
+ float u2 = slide_data->u * slide_data->u;
+ float u3 = slide_data->u * slide_data->u * slide_data->u;
+ float v = 1.0f - slide_data->u;
+ float v2 = v * v, v3 = v * v * v;;
+
+ /* Get coordinate spline is expected to go through. */
+ ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, B);
+
+ /* Apply accurate flag if needed. */
+ if (slide_data->accurate) {
+ float delta[2];
+ sub_v2_v2v2(delta, B, slide_data->initial_coord);
+ mul_v2_fl(delta, 0.2f);
+ add_v2_v2v2(B, slide_data->initial_coord, delta);
+ }
+
+ if (u < 0.5f) {
+ slide_data->adjust_bezt->vec[2][0] =
+ -(v3 * slide_data->P0[0] + 3.0f * v * u2 * slide_data->P2[0] + u3 * slide_data->P3[0] - B[0]) /
+ (3.0f * v2 * u);
+
+ slide_data->adjust_bezt->vec[2][1] =
+ -(v3 * slide_data->P0[1] + 3.0f * v * u2 * slide_data->P2[1] + u3 * slide_data->P3[1] - B[1]) /
+ (3.0f * v2 * u);
+ }
+ else {
+ slide_data->adjust_bezt->vec[0][0] =
+ -(v3 * slide_data->P0[0] + 3.0f * v2 * u * slide_data->P1[0] + u3 * slide_data->P3[0] - B[0]) /
+ (3.0f * v * u2);
+
+ slide_data->adjust_bezt->vec[0][1] =
+ -(v3 * slide_data->P0[1] + 3.0f * v2 * u * slide_data->P1[1] + u3 * slide_data->P3[1] - B[1]) /
+ (3.0f * v * u2);
+ }
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
+ DAG_id_tag_update(&slide_data->mask->id, 0);
+
+ break;
+ }
+
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
+ DAG_id_tag_update(&slide_data->mask->id, 0);
+
+ free_slide_spline_curvature_data(slide_data); /* keep this last! */
+ return OPERATOR_FINISHED;
+ }
+
+ break;
+
+ case ESCKEY:
+ cancel_slide_spline_curvature(slide_data);
+
+ WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
+ DAG_id_tag_update(&slide_data->mask->id, 0);
+
+ free_slide_spline_curvature_data(op->customdata); /* keep this last! */
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void MASK_OT_slide_spline_curvature(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Slide Spline Curvature";
+ ot->description = "Slide a point on the spline to define it's curvature";
+ ot->idname = "MASK_OT_slide_spline_curvature";
+
+ /* api callbacks */
+ ot->invoke = slide_spline_curvature_invoke;
+ ot->modal = slide_spline_curvature_modal;
+ ot->poll = ED_operator_mask;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
/******************** toggle cyclic *********************/
static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))