forked from 1b-agent/opencadstudio-upstream
feat(otrack): draw both vectors of an intersection lock
An OTRACK crossing is the meeting of two tracking vectors, but
`OtrackHit` carried only the one a typed distance is measured along, so
the overlay had a single guide to draw. Snapping to the crossing of two
vectors worked and looked like an unexplained point on one line.
Carry the crossed ray out of `otrack_snap` as `OtrackHit::cross`, keep it
on the app beside `otrack_active`, and let the overlay take a list of
guides rather than one. `otrack_active` still drives typed-distance
entry on its own, so distance entry is unchanged.
Fixes HakanSeven12/OpenCADStudio#1313
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQzYZsXBwPZ5HwBaGitEUV
(cherry picked from commit 2f6caacece)
This commit is contained in:
1 parent
41101efaa5
commit
033319a4e3
7 files changed
+183
-23
No files matched your search
@@ -104,6 +104,7 @@ impl OpenCADStudio {
|
||||
self.snapper.from_point = None;
|
||||
self.snapper.clear_tracking();
|
||||
self.otrack_active = None;
|
||||
self.otrack_cross = None;
|
||||
self.otrack_kind = None;
|
||||
self.axis_lock_dir = None;
|
||||
self.dyn_user_reshaped = false;
|
||||
|
||||
@@ -502,6 +502,11 @@ pub(super) struct OpenCADStudio {
|
||||
/// cursor is on a tracking ray. Lets a typed distance place a point along
|
||||
/// the ray from the tracking point (issue #69). `None` when not aligned.
|
||||
otrack_active: Option<(glam::DVec3, glam::DVec3)>,
|
||||
/// The vector `otrack_active` crosses, when the lock is the meeting of two
|
||||
/// tracking vectors. Drawn beside the first so the user can see that the
|
||||
/// point is their intersection; a typed distance still runs along
|
||||
/// `otrack_active` alone. `None` for a single-ray alignment. (#1313)
|
||||
otrack_cross: Option<(glam::DVec3, glam::DVec3)>,
|
||||
/// Active OTRACK ray kind, separate from typed-distance geometry.
|
||||
otrack_kind: Option<crate::snap::TrackingKind>,
|
||||
/// Whether Tangent snap was enabled before a tangent-pick command started.
|
||||
@@ -3868,6 +3873,7 @@ impl OpenCADStudio {
|
||||
annotation_auto_scale: -4,
|
||||
last_saved_config: None,
|
||||
otrack_active: None,
|
||||
otrack_cross: None,
|
||||
otrack_kind: None,
|
||||
clean_screen: false,
|
||||
quick_properties: false,
|
||||
|
||||
@@ -366,6 +366,7 @@ impl OpenCADStudio {
|
||||
{
|
||||
self.snapper.clear_tracking();
|
||||
self.otrack_active = None;
|
||||
self.otrack_cross = None;
|
||||
self.otrack_kind = None;
|
||||
}
|
||||
if let Some((started, tab_id, before)) = perf_edit_before {
|
||||
@@ -402,6 +403,7 @@ impl OpenCADStudio {
|
||||
pub(in crate::app) fn reset_tracking_after_point(&mut self) {
|
||||
self.snapper.clear_tracking();
|
||||
self.otrack_active = None;
|
||||
self.otrack_cross = None;
|
||||
self.otrack_kind = None;
|
||||
}
|
||||
|
||||
@@ -3982,6 +3984,7 @@ impl OpenCADStudio {
|
||||
if !self.snapper.otrack_enabled {
|
||||
self.snapper.clear_tracking();
|
||||
self.otrack_active = None;
|
||||
self.otrack_cross = None;
|
||||
self.otrack_kind = None;
|
||||
}
|
||||
Task::none()
|
||||
|
||||
@@ -1479,6 +1479,7 @@ impl OpenCADStudio {
|
||||
Some((base, dir))
|
||||
});
|
||||
self.otrack_active = otrack_hit.map(|hit| (hit.base, hit.dir)).or(drafting_guide);
|
||||
self.otrack_cross = otrack_hit.and_then(|hit| hit.cross);
|
||||
|
||||
self.otrack_kind = otrack_hit.map(|hit| hit.kind);
|
||||
|
||||
@@ -2190,6 +2191,7 @@ impl OpenCADStudio {
|
||||
None
|
||||
};
|
||||
self.otrack_active = otrack_hit.map(|h| (h.base, h.dir));
|
||||
self.otrack_cross = otrack_hit.and_then(|h| h.cross);
|
||||
self.otrack_kind = otrack_hit.map(|h| h.kind);
|
||||
|
||||
// Parallel snap: with nothing else snapped or tracked, lock
|
||||
@@ -2208,6 +2210,7 @@ impl OpenCADStudio {
|
||||
(self.last_point, self.snapper.parallel_ref)
|
||||
{
|
||||
self.otrack_active = Some((base, dir.as_dvec3()));
|
||||
self.otrack_cross = None;
|
||||
}
|
||||
self.tabs[i].snap_result = Some(par);
|
||||
}
|
||||
|
||||
+17
-10
@@ -770,15 +770,22 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
// The active alignment vector: a dashed guide from the acquired
|
||||
// tracking point through the locked cursor, so the user sees the
|
||||
// extension / tracking line they are snapped to (#219).
|
||||
let otrack_line: Option<(iced::Point, iced::Point)> =
|
||||
match (otrack_proj, self.otrack_active) {
|
||||
(Some((view_rot, eye, ob)), Some((base, _dir))) => {
|
||||
let b = ost_project(base, view_rot, eye, ob);
|
||||
let a = ost_project(tab.last_cursor_world, view_rot, eye, ob);
|
||||
(b.x.is_finite() && a.x.is_finite()).then_some((b, a))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
// An intersection lock is the meeting of two tracking vectors, so
|
||||
// both are drawn — one guide alone hides what the point is (#1313).
|
||||
let otrack_lines: Vec<(iced::Point, iced::Point)> = match otrack_proj {
|
||||
Some((view_rot, eye, ob)) => {
|
||||
let a = ost_project(tab.last_cursor_world, view_rot, eye, ob);
|
||||
self.otrack_active
|
||||
.into_iter()
|
||||
.chain(self.otrack_cross)
|
||||
.filter_map(|(base, _dir)| {
|
||||
let b = ost_project(base, view_rot, eye, ob);
|
||||
(b.x.is_finite() && a.x.is_finite()).then_some((b, a))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
None => vec![],
|
||||
};
|
||||
// The acquired Parallel-snap reference, marked on its line (#277).
|
||||
let parallel_ref_marker: Option<iced::Point> =
|
||||
match (otrack_proj, self.snapper.parallel_ref) {
|
||||
@@ -894,7 +901,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
grip_clip,
|
||||
ucs_icons,
|
||||
ost_points,
|
||||
otrack_line,
|
||||
otrack_lines,
|
||||
parallel_ref_marker,
|
||||
// ViewCube hover region matches the drawn cube — gone when hidden.
|
||||
!is_paper && viewcube_visible,
|
||||
|
||||
Reference in new issue
Block a user