From 554921c66ff7c65fdb18a7d2dec9950a0d3fe2a9 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 21 Jul 2026 11:13:47 +0300 Subject: [PATCH] fix(refedit): objects created during the session join the block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit REFCLOSE only wrote the temp copies made at REFEDIT entry back into the block, so anything drawn (or pasted / offset) during the session stayed behind in model space (#423). The session now captures a handle watermark at entry; on close, every current-space entity allocated at or above it joins the working set — Save folds it into the block through the same inverse transform, Discard removes it. Covers every creation path with no per-command hooks. Co-Authored-By: Claude Fable 5 --- src/app/commands/inquiry.rs | 53 +++++++++++++++++++++++++++--- src/modules/draw/modify/refedit.rs | 6 ++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/app/commands/inquiry.rs b/src/app/commands/inquiry.rs index b6558fcea..cb72e8b23 100644 --- a/src/app/commands/inquiry.rs +++ b/src/app/commands/inquiry.rs @@ -583,6 +583,13 @@ impl OpenCADStudio { temp_handles: vec![], forward, inverse, + // Everything allocated from here on is part of the session. + handle_watermark: self + .tabs[i] + .scene + .document + .next_handle() + .max(self.tabs[i].scene.document.header.handle_seed), }; self.push_undo_snapshot(i, "REFEDIT"); @@ -649,15 +656,35 @@ impl OpenCADStudio { self.push_undo_snapshot(i, "REFCLOSE"); + // The working set: the temp copies PLUS everything the user + // created in this space during the session (drawn / pasted / + // offset entities carry handles at or above the watermark) — + // those must fold into the block too, not stay behind in + // model space (#423). + let working: Vec = { + let space = self.tabs[i].scene.current_layout_block_handle_pub(); + let drawn = self.tabs[i].scene.document.entities().filter(|e| { + let c = e.common(); + c.owner_handle == space + && c.handle.value() >= session.handle_watermark + && !session.temp_handles.contains(&c.handle) + }); + session + .temp_handles + .iter() + .copied() + .chain(drawn.map(|e| e.common().handle)) + .collect() + }; + // Collect the edited temp entities. - let new_entities: Vec = session - .temp_handles + let new_entities: Vec = working .iter() .filter_map(|h| self.tabs[i].scene.document.get_entity(*h).cloned()) .collect(); // Remove temp entities from model space. - self.tabs[i].scene.erase_entities(&session.temp_handles); + self.tabs[i].scene.erase_entities(&working); // Apply inverse INSERT transform → block-local coordinates. let new_entities: Vec<_> = new_entities @@ -720,8 +747,24 @@ impl OpenCADStudio { return Some(Task::none()); } }; - // Remove temp entities without modifying the block. - self.tabs[i].scene.erase_entities(&session.temp_handles); + // Remove the working set without modifying the block — the + // temp copies plus anything created during the session (#423). + let working: Vec = { + let space = self.tabs[i].scene.current_layout_block_handle_pub(); + let drawn = self.tabs[i].scene.document.entities().filter(|e| { + let c = e.common(); + c.owner_handle == space + && c.handle.value() >= session.handle_watermark + && !session.temp_handles.contains(&c.handle) + }); + session + .temp_handles + .iter() + .copied() + .chain(drawn.map(|e| e.common().handle)) + .collect() + }; + self.tabs[i].scene.erase_entities(&working); self.tabs[i].scene.deselect_all(); // End the edit fade — restore the drawing to full brightness. self.tabs[i].scene.set_refedit_keep(None); diff --git a/src/modules/draw/modify/refedit.rs b/src/modules/draw/modify/refedit.rs index 14773e696..48f4d1299 100644 --- a/src/modules/draw/modify/refedit.rs +++ b/src/modules/draw/modify/refedit.rs @@ -55,6 +55,12 @@ pub struct RefEditSession { pub forward: acadrust::types::Transform, /// World → block-local, applied on SAVE to bring edits back. pub inverse: acadrust::types::Transform, + /// Handle watermark captured before the temp copies were created: every + /// entity allocated at or above it during the session (drawn, pasted, + /// offset, …) belongs to the working set, so Save folds it into the block + /// and Discard removes it (#423). Catches every creation path without + /// per-command hooks. + pub handle_watermark: u64, } // ── REFEDIT pick command ───────────────────────────────────────────────────