diff options
Diffstat (limited to 'source/blender/editors/transform/transform_mode_edge_slide.c')
-rw-r--r-- | source/blender/editors/transform/transform_mode_edge_slide.c | 383 |
1 files changed, 229 insertions, 154 deletions
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 9f9e5742ffe..4a648a77fe1 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -50,6 +50,7 @@ #include "BLT_translation.h" #include "transform.h" +#include "transform_constraints.h" #include "transform_convert.h" #include "transform_mode.h" #include "transform_snap.h" @@ -96,24 +97,28 @@ typedef struct EdgeSlideParams { } EdgeSlideParams; /** - * Get the first valid EdgeSlideData. + * Get the first valid TransDataContainer *. * * Note we cannot trust TRANS_DATA_CONTAINER_FIRST_OK because of multi-object that * may leave items with invalid custom data in the transform data container. */ -static EdgeSlideData *edgeSlideFirstGet(TransInfo *t) +static TransDataContainer *edge_slide_container_first_ok(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - if (sld == NULL) { - continue; + if (tc->custom.mode.data) { + return tc; } - return sld; } BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid"); return NULL; } +static EdgeSlideData *edgeSlideFirstGet(TransInfo *t) +{ + TransDataContainer *tc = edge_slide_container_first_ok(t); + return tc->custom.mode.data; +} + static void calcEdgeSlideCustomPoints(struct TransInfo *t) { EdgeSlideData *sld = edgeSlideFirstGet(t); @@ -276,15 +281,14 @@ static BMLoop *get_next_loop( copy_v3_v3(r_slide_vec, vec_accum); return l; } - else { - /* accumulate the normalized edge vector, - * normalize so some edges don't skew the result */ - float tvec[3]; - sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co); - vec_accum_len += normalize_v3(tvec); - add_v3_v3(vec_accum, tvec); - i += 1; - } + + /* accumulate the normalized edge vector, + * normalize so some edges don't skew the result */ + float tvec[3]; + sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co); + vec_accum_len += normalize_v3(tvec); + add_v3_v3(vec_accum, tvec); + i += 1; if (BM_loop_other_edge_loop(l, v)->e == e_next) { if (i) { @@ -519,7 +523,7 @@ static void calcEdgeSlide_even(TransInfo *t, } } -static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc) +static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc) { BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; @@ -554,8 +558,9 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t } if (numsel == 0 || numsel > 2) { + /* Invalid edge selection. */ MEM_freeN(sld); - return false; /* invalid edge selection */ + return NULL; } } } @@ -566,7 +571,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) { /* can edges with at least once face user */ MEM_freeN(sld); - return false; + return NULL; } } } @@ -595,7 +600,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t if (!j) { MEM_freeN(sld); MEM_freeN(sv_table); - return false; + return NULL; } sv_tot = j; } @@ -870,18 +875,16 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t calcEdgeSlide_even(t, tc, sld, mval); } - tc->custom.mode.data = sld; - MEM_freeN(sv_table); - return true; + return sld; } /** * A simple version of #createEdgeSlideVerts_double_side * Which assumes the longest unselected. */ -static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc) +static EdgeSlideData *createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc) { BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; @@ -933,7 +936,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *t if (!j) { MEM_freeN(sld); - return false; + return NULL; } sv_tot = j; @@ -1055,24 +1058,9 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *t calcEdgeSlide_even(t, tc, sld, mval); } - tc->custom.mode.data = sld; - MEM_freeN(sv_table); - return true; -} - -void projectEdgeSlideData(TransInfo *t, bool is_final) -{ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - - if (sld == NULL) { - continue; - } - - trans_mesh_customdata_correction_apply(tc, is_final); - } + return sld; } static void freeEdgeSlideVerts(TransInfo *UNUSED(t), @@ -1145,132 +1133,227 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven void drawEdgeSlide(TransInfo *t) { - if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) { - const EdgeSlideParams *slp = t->custom.mode.data; - EdgeSlideData *sld = edgeSlideFirstGet(t); - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (t->mode != TFM_EDGE_SLIDE) { + return; + } - /* Even mode */ - if ((slp->use_even == true) || (is_clamp == false)) { - const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + EdgeSlideData *sld = edgeSlideFirstGet(t); + if (sld == NULL) { + return; + } - GPU_depth_test(false); + const EdgeSlideParams *slp = t->custom.mode.data; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - GPU_blend(true); - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - GPU_matrix_push(); - GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_depth_test(false); - uint pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - if (slp->use_even == true) { - float co_a[3], co_b[3], co_mark[3]; - TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float fac = (slp->perc + 1.0f) / 2.0f; - const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - const float guide_size = ctrl_size - 0.5f; - const int alpha_shade = -30; + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); - add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - GPU_line_width(line_size); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBeginAtMost(GPU_PRIM_LINES, 4); - if (curr_sv->v_side[0]) { - immVertex3fv(pos, curr_sv->v_side[0]->co); - immVertex3fv(pos, curr_sv->v_co_orig); - } + if (slp->use_even == true) { + /* Even mode */ + float co_a[3], co_b[3], co_mark[3]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float fac = (slp->perc + 1.0f) / 2.0f; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float guide_size = ctrl_size - 0.5f; + const int alpha_shade = -30; + + add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); + add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GPU_PRIM_LINES, 4); + if (curr_sv->v_side[0]) { + immVertex3fv(pos, curr_sv->v_side[0]->co); + immVertex3fv(pos, curr_sv->v_co_orig); + } + if (curr_sv->v_side[1]) { + immVertex3fv(pos, curr_sv->v_side[1]->co); + immVertex3fv(pos, curr_sv->v_co_orig); + } + immEnd(); + + { + float *co_test = NULL; + if (slp->flipped) { if (curr_sv->v_side[1]) { - immVertex3fv(pos, curr_sv->v_side[1]->co); - immVertex3fv(pos, curr_sv->v_co_orig); + co_test = curr_sv->v_side[1]->co; } - immEnd(); - - { - float *co_test = NULL; - if (slp->flipped) { - if (curr_sv->v_side[1]) { - co_test = curr_sv->v_side[1]->co; - } - } - else { - if (curr_sv->v_side[0]) { - co_test = curr_sv->v_side[0]->co; - } - } - - if (co_test != NULL) { - immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); - GPU_point_size(ctrl_size); - immBegin(GPU_PRIM_POINTS, 1); - immVertex3fv(pos, co_test); - immEnd(); - } + } + else { + if (curr_sv->v_side[0]) { + co_test = curr_sv->v_side[0]->co; } + } - immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); - GPU_point_size(guide_size); + if (co_test != NULL) { + immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + GPU_point_size(ctrl_size); immBegin(GPU_PRIM_POINTS, 1); - interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); - immVertex3fv(pos, co_mark); + immVertex3fv(pos, co_test); immEnd(); } + } + + immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + GPU_point_size(guide_size); + immBegin(GPU_PRIM_POINTS, 1); + interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); + immVertex3fv(pos, co_mark); + immEnd(); + } + else if (is_clamp == false) { + const int side_index = sld->curr_side_unclamp; + TransDataEdgeSlideVert *sv; + int i; + const int alpha_shade = -160; + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); + + /* TODO(campbell): Loop over all verts */ + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(a, sv->dir_side[side_index]); + } else { - if (is_clamp == false) { - const int side_index = sld->curr_side_unclamp; - TransDataEdgeSlideVert *sv; - int i; - const int alpha_shade = -160; + copy_v3_v3(a, sv->dir_side[!side_index]); + } - GPU_line_width(line_size); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBegin(GPU_PRIM_LINES, sld->totsv * 2); + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->v_co_orig); + add_v3_v3(b, sv->v_co_orig); - /* TODO(campbell): Loop over all verts */ - sv = sld->sv; - for (i = 0; i < sld->totsv; i++, sv++) { - float a[3], b[3]; + immVertex3fv(pos, a); + immVertex3fv(pos, b); + } + immEnd(); + } + else { + /* Common case. */ + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const int alpha_shade = -160; + + float co_dir[3]; + add_v3_v3v3(co_dir, curr_sv->v_co_orig, curr_sv->dir_side[sld->curr_side_unclamp]); + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GPU_PRIM_LINES, 2); + immVertex3fv(pos, curr_sv->v_co_orig); + immVertex3fv(pos, co_dir); + immEnd(); + } - if (!is_zero_v3(sv->dir_side[side_index])) { - copy_v3_v3(a, sv->dir_side[side_index]); - } - else { - copy_v3_v3(a, sv->dir_side[!side_index]); - } + immUnbindProgram(); - mul_v3_fl(a, 100.0f); - negate_v3_v3(b, a); - add_v3_v3(a, sv->v_co_orig); - add_v3_v3(b, sv->v_co_orig); + GPU_matrix_pop(); - immVertex3fv(pos, a); - immVertex3fv(pos, b); - } - immEnd(); - } - else { - BLI_assert(0); - } - } + GPU_blend(false); - immUnbindProgram(); + GPU_depth_test(true); +} - GPU_matrix_pop(); +static void edge_slide_snap_apply(TransInfo *t, float *value) +{ + TransDataContainer *tc = edge_slide_container_first_ok(t); + EdgeSlideParams *slp = t->custom.mode.data; + EdgeSlideData *sld_active = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = &sld_active->sv[sld_active->curr_sv_index]; + float snap_point[3], co_orig[3], co_dest[2][3], dvec[3]; + + copy_v3_v3(co_orig, sv->v_co_orig); + add_v3_v3v3(co_dest[0], co_orig, sv->dir_side[0]); + add_v3_v3v3(co_dest[1], co_orig, sv->dir_side[1]); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, co_orig); + mul_m4_v3(tc->mat, co_dest[0]); + mul_m4_v3(tc->mat, co_dest[1]); + } - GPU_blend(false); + getSnapPoint(t, dvec); + sub_v3_v3(dvec, t->tsnap.snapTarget); + add_v3_v3v3(snap_point, co_orig, dvec); - GPU_depth_test(true); + float perc = *value; + int side_index; + float t_mid; + if (slp->use_even == false) { + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { + side_index = perc < 0.0f; } + else { + side_index = sld_active->curr_side_unclamp; + } + } + else { + /* Could be pre-calculated. */ + t_mid = line_point_factor_v3((float[3]){0.0f, 0.0f, 0.0f}, sv->dir_side[0], sv->dir_side[1]); + + float t_snap = line_point_factor_v3(snap_point, co_dest[0], co_dest[1]); + side_index = t_snap >= t_mid; } + + if (t->tsnap.snapElem & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) { + float co_dir[3]; + sub_v3_v3v3(co_dir, co_dest[side_index], co_orig); + normalize_v3(co_dir); + if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) { + transform_constraint_snap_axis_to_edge(t, co_dir, dvec); + } + else { + transform_constraint_snap_axis_to_face(t, co_dir, dvec); + } + add_v3_v3v3(snap_point, co_orig, dvec); + } + + perc = line_point_factor_v3(snap_point, co_orig, co_dest[side_index]); + if (slp->use_even == false) { + if (side_index) { + perc *= -1; + } + } + else { + if (!side_index) { + perc = (1.0f - perc) * t_mid; + } + else { + perc = perc * (1.0f - t_mid) + t_mid; + } + + if (slp->flipped) { + perc = 1.0f - perc; + } + + perc = (2 * perc) - 1.0f; + + if (!slp->flipped) { + perc *= -1; + } + } + + *value = perc; } -void doEdgeSlide(TransInfo *t, float perc) +static void doEdgeSlide(TransInfo *t, float perc) { EdgeSlideParams *slp = t->custom.mode.data; EdgeSlideData *sld_active = edgeSlideFirstGet(t); @@ -1381,6 +1464,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; + applySnapping(t, &final); snapGridIncrement(t, &final); /* only do this so out of range values are not displayed */ @@ -1429,6 +1513,8 @@ void initEdgeSlide_ex( t->mode = TFM_EDGE_SLIDE; t->transform = applyEdgeSlide; t->handleEvent = handleEventEdgeSlide; + t->tsnap.applySnap = edge_slide_snap_apply; + t->tsnap.distance = transform_snap_distance_len_squared_fn; { EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); @@ -1448,14 +1534,13 @@ void initEdgeSlide_ex( t->custom.mode.use_free = true; } - if (use_double_side) { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - ok |= createEdgeSlideVerts_double_side(t, tc); - } - } - else { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - ok |= createEdgeSlideVerts_single_side(t, tc); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + sld = use_double_side ? createEdgeSlideVerts_double_side(t, tc) : + createEdgeSlideVerts_single_side(t, tc); + if (sld) { + tc->custom.mode.data = sld; + tc->custom.mode.free_cb = freeEdgeSlideVerts; + ok = true; } } @@ -1464,16 +1549,6 @@ void initEdgeSlide_ex( return; } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - sld = tc->custom.mode.data; - if (!sld) { - continue; - } - tc->custom.mode.free_cb = freeEdgeSlideVerts; - } - - trans_mesh_customdata_correction_init(t); - /* set custom point first if you want value to be initialized by init */ calcEdgeSlideCustomPoints(t); initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP); |