From d041bea32ad0d4ef99b8cb82f1467789ab9c0249 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Wed, 17 Jun 2026 04:56:42 +0300 Subject: [PATCH] =?UTF-8?q?fix(snap):=20shrink=20OSNAP=20pickup=20radius?= =?UTF-8?q?=20to=20=C2=BC=20of=20crosshair=20arm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OSNAP registered snapping over the full crosshair-arm radius (60 px), making it too easy to snap and leaving little room to click just outside a snap point. Split out a dedicated osnap_radius_px (¼ of the arm) used only for object-snap matching; tracking, polar and extension pickup keep the larger snap_radius_px. Closes #108 Co-Authored-By: Claude Opus 4.8 --- src/snap/mod.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/snap/mod.rs b/src/snap/mod.rs index 0bed7f700..62f835021 100644 --- a/src/snap/mod.rs +++ b/src/snap/mod.rs @@ -87,8 +87,11 @@ pub struct Snapper { pub enabled: HashSet, /// World-space grid spacing. pub grid_spacing: f32, - /// Pixel-radius threshold. + /// Pixel-radius threshold for tracking / polar / extension pickup. pub snap_radius_px: f32, + /// Pixel-radius threshold for object snapping (OSNAP). Kept smaller than + /// `snap_radius_px` so it is easy to click just outside a snap point. + pub osnap_radius_px: f32, /// Object Snap Tracking on/off (F11). pub otrack_enabled: bool, /// Acquired OST points (world XZ, Y=0 plane). @@ -114,6 +117,7 @@ impl Default for Snapper { enabled, grid_spacing: 1.0, snap_radius_px: CROSSHAIR_ARM, + osnap_radius_px: CROSSHAIR_ARM * 0.25, otrack_enabled: false, tracking_points: Vec::new(), last_snap_world: None, @@ -302,6 +306,7 @@ impl Snapper { }, grid_spacing: self.grid_spacing, snap_radius_px: self.snap_radius_px, + osnap_radius_px: self.osnap_radius_px, otrack_enabled: false, tracking_points: Vec::new(), last_snap_world: None, @@ -323,7 +328,7 @@ impl Snapper { return None; } let mut best: Option = None; - let mut best_d2 = self.snap_radius_px * self.snap_radius_px; + let mut best_d2 = self.osnap_radius_px * self.osnap_radius_px; // World-space snap radius — derived from the view scale so wires whose // entire extent is clearly outside the snap circle can be skipped cheaply @@ -333,7 +338,7 @@ impl Snapper { let world_snap_r = { let s = view_proj.col(0).x.abs() * bounds.width * 0.5; if s > 1e-6 { - self.snap_radius_px / s + self.osnap_radius_px / s } else { f32::MAX } @@ -514,7 +519,7 @@ impl Snapper { p0 - p1, view_proj, bounds, - self.snap_radius_px, + self.osnap_radius_px, ) { try_pt(ext, SnapType::Extension); } @@ -529,7 +534,7 @@ impl Snapper { p_last - p_prev, view_proj, bounds, - self.snap_radius_px, + self.osnap_radius_px, ) { try_pt(ext, SnapType::Extension); }