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 | 323 |
1 files changed, 211 insertions, 112 deletions
diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 42f75f041b9..ed22afc404e 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); @@ -1129,132 +1134,226 @@ 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); + 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); @@ -1365,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 */ @@ -1413,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__); @@ -1432,16 +1534,13 @@ void initEdgeSlide_ex( t->custom.mode.use_free = true; } - if (use_double_side) { - 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; - trans_mesh_customdata_correction_init(t, tc); - ok = true; - } + 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; } } |