diff --git a/src/app/command_driver.rs b/src/app/command_driver.rs index 67d1831d..dd0431a1 100644 --- a/src/app/command_driver.rs +++ b/src/app/command_driver.rs @@ -493,6 +493,14 @@ impl OpenCADStudio { matches!(result, CmdResult::Relaunch(..) | CmdResult::Dispatch(..)); let task = self.apply_cmd_result_inner(result); let i = self.active_tab; + let preview_hidden = self.tabs[i] + .active_cmd + .as_ref() + .map(|command| command.preview_hidden_handles().to_vec()) + .unwrap_or_default(); + self.tabs[i] + .scene + .set_command_preview_hidden(&preview_hidden); if was_active && !preserve_selection && self.tabs[i].active_cmd.is_none() diff --git a/src/command.rs b/src/command.rs index 5199b296..0a2f7797 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1400,6 +1400,13 @@ pub trait CadCommand: Send { self.on_mouse_move(pt).into_iter().collect() } + /// Source entities replaced by the current live preview. The host removes + /// these from the resident render until the command commits or cancels. + /// Commands such as COPY keep their sources visible and use the default. + fn preview_hidden_handles(&self) -> &[Handle] { + &[] + } + /// Returns `true` when the command is waiting for text typed in the command line. fn wants_text_input(&self) -> bool { false diff --git a/src/modules/draw/modify/translate.rs b/src/modules/draw/modify/translate.rs index 90e71e0c..c9959fa4 100644 --- a/src/modules/draw/modify/translate.rs +++ b/src/modules/draw/modify/translate.rs @@ -109,4 +109,11 @@ impl CadCommand for MoveCommand { )); out } + + fn preview_hidden_handles(&self) -> &[Handle] { + match self.step { + Step::Base => &[], + Step::Target(_) => &self.handles, + } + } } diff --git a/src/scene/mod.rs b/src/scene/mod.rs index b823cec0..a4d16b11 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -1532,10 +1532,13 @@ pub struct Scene { /// Session-only ISOLATEOBJECTS / HIDEOBJECTS state. Never written to DWG/DXF. pub object_isolation: ObjectIsolationState, /// Entity handles temporarily removed from the base render while an - /// interactive preview (currently grip drag) draws their live replacement. + /// interactive grip preview draws their live replacement. /// Separate from object isolation so a grip can never activate the /// isolation status or be captured in its undo state. pub preview_hidden: HashSet, + /// Source handles replaced by an active command preview. Kept separate + /// from grip state so either interaction can clean up only its own hides. + command_preview_hidden: HashSet, /// During in-place block edit (REFEDIT), the handles of the entities being /// edited. Everything else is rendered faded toward the background so the /// edited geometry stands out while the surrounding drawing stays visible @@ -1931,6 +1934,7 @@ impl Scene { selected: HashSet::default(), object_isolation: ObjectIsolationState::default(), preview_hidden: HashSet::default(), + command_preview_hidden: HashSet::default(), refedit_keep: None, hover_highlight: None, transparency_display: true, @@ -4173,7 +4177,28 @@ impl Scene { /// True when a top-level entity must be omitted for a session-only object /// visibility command or an interactive replacement preview. fn entity_temporarily_hidden(&self, handle: Handle) -> bool { - self.object_isolation.hides(handle) || self.preview_hidden.contains(&handle) + self.object_isolation.hides(handle) + || self.preview_hidden.contains(&handle) + || self.command_preview_hidden.contains(&handle) + } + + /// Replace the command-owned source hide set and refresh only handles whose + /// visibility changed. An empty slice restores every source on completion. + pub fn set_command_preview_hidden(&mut self, handles: &[Handle]) { + let desired: HashSet<_> = handles.iter().copied().collect(); + if desired == self.command_preview_hidden { + return; + } + let changes: Vec<_> = self + .command_preview_hidden + .symmetric_difference(&desired) + .copied() + .map(|handle| (handle, ChangeKind::Modified)) + .collect(); + self.command_preview_hidden = desired; + if !changes.is_empty() { + self.bump_entities(&changes); + } } /// Set (or clear) the previewed entity that renders with the selection @@ -4274,6 +4299,7 @@ impl Scene { pub fn reset_transient_visibility(&mut self) { self.object_isolation = ObjectIsolationState::default(); self.preview_hidden.clear(); + self.command_preview_hidden.clear(); } /// True if any currently selected entity is a Viewport.