diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index 1972e1501b5..9a82296bfc0 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -96,24 +96,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); @@ -1254,6 +1258,71 @@ void drawEdgeSlide(TransInfo *t) } } +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]); + } + + getSnapPoint(t, dvec); + sub_v3_v3(dvec, t->tsnap.snapTarget); + add_v3_v3v3(snap_point, co_orig, dvec); + + float perc = *value; + int side_index; + 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; + } + perc = line_point_factor_v3(snap_point, co_orig, co_dest[side_index]); + if (side_index) { + perc *= -1; + } + } + else { + /* Could be pre-calculated. */ + float 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; + perc = line_point_factor_v3(snap_point, co_orig, co_dest[side_index]); + 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) { EdgeSlideParams *slp = t->custom.mode.data; @@ -1365,6 +1434,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 +1483,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__); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index a9b3b7448ef..aaf5b55c4e3 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -127,6 +127,9 @@ bool transformModeUseSnap(const TransInfo *t) if (t->mode == TFM_VERT_SLIDE) { return true; } + if (t->mode == TFM_EDGE_SLIDE) { + return true; + } return false; }