feat(grip): Esc cancels an in-progress grip drag

The grip drag mutates the document live (so grips and the properties panel
track the cursor), which meant Esc left the entity at its dragged position.
Back up the edited entity when the drag starts (the same first-move point
that hides it for the overlay preview) and, on Esc, restore that backup
before un-hiding and re-tessellating — reverting the entity to where it was
when the drag began. A normal release drops the backup and keeps the
dragged geometry.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-05 10:44:31 +03:00
1 parent 8df9bef6f8
commit 55022ae60e
2 files changed
+22 -5

No files matched your search

+6
View File
@@ -237,6 +237,11 @@ pub(super) struct OpenCADStudio {
/// updates only the overlay rather than re-tessellating the whole model.
/// Committed (un-hidden + one re-tess) when the drag ends. `None` = idle.
grip_preview_handle: Option<acadrust::Handle>,
/// Snapshot of the edited entity taken at the start of a grip drag, used to
/// restore it if the user presses Esc to cancel the drag. The drag mutates
/// the document live (so grips / properties track), so cancel reverts from
/// this backup. Dropped (kept) on a normal commit.
grip_original: Option<acadrust::EntityType>,
/// Open Quick Select panel state. `None` = panel closed. Filters are
/// applied via `Message::QSelectApply`; the panel is dismissed on
/// Apply / Cancel / Esc / outside-click.
@@ -1279,6 +1284,7 @@ impl OpenCADStudio {
grip_pending: None,
grip_add_provisional: None,
grip_preview_handle: None,
grip_original: None,
qselect: None,
show_ucs_icon: true,
show_viewcube: true,
+16 -5
View File
@@ -1313,13 +1313,20 @@ impl OpenCADStudio {
self.tabs[i].scene.bump_geometry();
self.refresh_selected_grips();
}
// Commit/cleanup an in-progress grip drag: un-hide the
// edited entity, re-tessellate once, drop the preview.
// Cancel an in-progress grip drag: restore the edited
// entity from its pre-drag backup, un-hide it, re-tessellate
// once, and drop the preview.
if let Some(h) = self.grip_preview_handle.take() {
let i = self.active_tab;
if let Some(orig) = self.grip_original.take() {
if let Some(e) = self.tabs[i].scene.document.get_entity_mut(h) {
*e = orig;
}
}
self.tabs[i].scene.hidden.remove(&h);
self.tabs[i].scene.clear_preview_wire();
self.tabs[i].scene.bump_geometry();
self.refresh_selected_grips();
}
self.tabs[self.active_tab].snap_result = None;
self.refresh_properties();
@@ -2116,6 +2123,9 @@ impl OpenCADStudio {
if let Some(prev) = self.grip_preview_handle.take() {
self.tabs[i].scene.hidden.remove(&prev);
}
// Back up the original geometry so Esc can cancel the drag.
self.grip_original =
self.tabs[i].scene.document.get_entity(grip.handle).cloned();
self.tabs[i].scene.hidden.insert(grip.handle);
self.tabs[i].scene.bump_geometry();
self.grip_preview_handle = Some(grip.handle);
@@ -2633,10 +2643,11 @@ impl OpenCADStudio {
return Task::none();
}
self.tabs[i].active_grip = None;
// Commit the grip drag: un-hide the edited entity and
// re-tessellate the base once with its final geometry,
// dropping the overlay preview.
// Commit the grip drag: keep the doc's dragged geometry
// (drop the cancel backup), un-hide the edited entity and
// re-tessellate the base once, dropping the overlay preview.
if let Some(h) = self.grip_preview_handle.take() {
self.grip_original = None;
self.tabs[i].scene.hidden.remove(&h);
self.tabs[i].scene.clear_preview_wire();
self.tabs[i].scene.bump_geometry();