fix(grips): a grip lands on the snap marker it shows

While a grip drags, the edited entity is hidden from snapping and its
drag-start shape got a reference-only pass: the marker appeared on the
old edge's midpoint or corner, but the grip stayed at the raw cursor,
and the pass ran only with object snap tracking on. The reference pass
now always runs, still limited to discrete points (never nearest-style,
so the point cannot be pulled back onto the old shape) and skipping the
grip's own start point, and when no snap on the rest of the drawing wins
it places the grip too.

Fixes #1528

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-29 09:12:31 +03:00
1 parent 80372abf2c
commit 07f25f4bca
1 file changed
+13 -12
+13 -12
View File
@@ -1439,13 +1439,14 @@ impl OpenCADStudio {
construction_ray, construction_ray,
); );
// The frozen pre-drag geometry gets a SECOND, reference-only snap pass. // The frozen pre-drag geometry gets a SECOND snap pass, limited to
// // its discrete points: a corner can be dropped on the old midpoint
// Its result is never used to place/move the grip. It exists only so the // of its own edge, or acquired for OTRACK, while nearest/tangent-
// user can hover an endpoint/midpoint/etc. of the original geometry and // style snaps can never pull the point back onto the old shape.
// acquire it for OTRACK exactly like ordinary drawing geometry. // The grip's own starting point is skipped so it does not stick
// where the drag began.
let reference_snap_hit = let reference_snap_hit =
if self.snapper.tracking_active() && !self.grip_reference_wires.is_empty() { if !self.grip_reference_wires.is_empty() {
self.snapper self.snapper
.snap( .snap(
raw, raw,
@@ -1469,21 +1470,21 @@ impl OpenCADStudio {
| crate::snap::SnapType::Intersection | crate::snap::SnapType::Intersection
| crate::snap::SnapType::Insertion | crate::snap::SnapType::Insertion
| crate::snap::SnapType::ApparentIntersection | crate::snap::SnapType::ApparentIntersection
) ) && hit.world.distance(grip.origin_world) > 1e-9
}) })
} else { } else {
None None
}; };
// The visible marker should normally describe the real snap that is driving // A real object snap on the rest of the drawing wins; otherwise the
// the cursor. However, when there is no real object snap (or only Grid), show // reference point both shows and places the grip, so the marker is
// the reference snap marker so the user can see what point is being acquired. // always the point the grip lands on.
let display_snap_hit = match snap_hit { let snap_hit = match snap_hit {
Some(hit) if hit.snap_type != crate::snap::SnapType::Grid => Some(hit), Some(hit) if hit.snap_type != crate::snap::SnapType::Grid => Some(hit),
_ => reference_snap_hit.or(snap_hit), _ => reference_snap_hit.or(snap_hit),
}; };
self.tabs[i].snap_result = display_snap_hit; self.tabs[i].snap_result = snap_hit;
// OTRACK acquisition needs access to the original wire geometry so, once a // OTRACK acquisition needs access to the original wire geometry so, once a
// reference point has dwelt long enough, it can capture the segment directions // reference point has dwelt long enough, it can capture the segment directions