Fix #128637: Gizmo line tool not snapping to exactly 45 degrees

Due to rounding errors in `wm_gesture_straightline_do_angle_snap`, it
could give out a snapped result that's meant to be 45 degrees but does
not have equal X/Y distances after converted to integer. Since 45
degrees can be used to make a equal length structure, it's best to make
sure that resulting X/Y values are the same if the angle is multiple of
45 degrees.

This fix would be effective for all tools that uses this "straight line
gizmo".

Pull Request: https://projects.blender.org/blender/blender/pulls/128683
This commit is contained in:
YimingWu
2024-10-14 07:01:45 +02:00
parent e3f9d210d1
commit dc45169acd

View File

@@ -1052,6 +1052,22 @@ static void wm_gesture_straightline_do_angle_snap(rcti *rect, float snap_angle)
rect->xmax = int(line_snapped_end[0]);
rect->ymax = int(line_snapped_end[1]);
/* Check whether `angle_snapped` is a multiple of 45 degrees, if so ensure X and Y directions
* are the same length (there could be an off-by-one due to rounding error). */
const float fract_45 = fractf(angle_snapped / DEG2RADF(45.0f));
const float fract_90 = fractf(angle_snapped / DEG2RADF(90.0f));
/* Check if it's a multiple of 45 but not 90 degrees. */
if ((compare_ff(fract_45, 0.0f, 1e-6) || compare_ff(fabsf(fract_45), 1.0f, 1e-6)) &&
(!(compare_ff(fract_90, 0.0f, 1e-6) || compare_ff(fabsf(fract_90), 1.0f, 1e-6))))
{
int xlen = abs(rect->xmax - rect->xmin);
int ylen = rect->ymax - rect->ymin;
if (abs(ylen) != xlen) {
ylen = xlen * (ylen >= 0 ? 1 : -1);
rect->ymax = rect->ymin + ylen;
}
}
}
int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)