forked from 1b-agent/opencadstudio-upstream
fix(clipboard): preserve pasted content
Reset cross-document ownership, include non-wire and locked objects, and rebuild image caches for embedded OLE content. Refs #934
This commit is contained in:
1 parent
4fc8446df7
commit
217f20d8bc
5 files changed
+71
-26
No files matched your search
@@ -72,7 +72,6 @@ impl OpenCADStudio {
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(h, _)| h)
|
||||
.filter(|handle| !self.tabs[i].scene.is_layer_locked(*handle))
|
||||
.collect();
|
||||
if handles.is_empty() {
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
@@ -108,7 +107,6 @@ impl OpenCADStudio {
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(h, _)| h)
|
||||
.filter(|handle| !self.tabs[i].scene.is_layer_locked(*handle))
|
||||
.collect();
|
||||
if handles.is_empty() {
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
@@ -135,7 +133,6 @@ impl OpenCADStudio {
|
||||
.selected_entities()
|
||||
.into_iter()
|
||||
.map(|(h, _)| h)
|
||||
.filter(|handle| !self.tabs[i].scene.is_layer_locked(*handle))
|
||||
.collect();
|
||||
if coords.len() == 3 && !handles.is_empty() {
|
||||
let base = glam::DVec3::new(coords[0], coords[1], coords[2]);
|
||||
|
||||
@@ -10,17 +10,7 @@ impl OpenCADStudio {
|
||||
|
||||
// ── Selection utilities ───────────────────────────────────────
|
||||
"SELECTALL" => {
|
||||
use crate::scene::Scene;
|
||||
let handles: Vec<acadrust::Handle> = self.tabs[i]
|
||||
.scene
|
||||
.entity_wires()
|
||||
.iter()
|
||||
.filter_map(|w| Scene::handle_from_wire_name(&w.name))
|
||||
.collect();
|
||||
let count = handles.len();
|
||||
for h in handles {
|
||||
self.tabs[i].scene.select_entity(h, false);
|
||||
}
|
||||
let count = self.tabs[i].scene.select_all_visible();
|
||||
self.command_line
|
||||
.push_output(crate::tf!("SELECTALL: {} object(s) selected.", count).as_ref());
|
||||
self.refresh_properties();
|
||||
|
||||
+6
-8
@@ -2123,16 +2123,14 @@ impl Scene {
|
||||
.collect();
|
||||
}
|
||||
|
||||
/// Tessellate all `Solid3D` entities in the current document into
|
||||
/// GPU-ready `MeshModel`s and store them in `self.meshes`.
|
||||
///
|
||||
/// Called after loading a document or after undo/redo so that every
|
||||
/// `Solid3D` entity is represented in the mesh cache.
|
||||
/// ImageModel for an edited image-bearing entity (RasterImage, or a PDF
|
||||
/// UNDERLAY resolved through its definition object). `None` for others.
|
||||
fn image_seed_for(&self, entity: &acadrust::entities::EntityType) -> Option<ImageModel> {
|
||||
/// ImageModel for an image-bearing entity. `None` when it cannot decode.
|
||||
pub(super) fn image_seed_for(
|
||||
&self,
|
||||
entity: &acadrust::entities::EntityType,
|
||||
) -> Option<ImageModel> {
|
||||
match entity {
|
||||
EntityType::RasterImage(img) => ImageModel::from_raster_image(img),
|
||||
EntityType::Ole2Frame(ole) => ImageModel::from_ole2frame(ole),
|
||||
EntityType::Underlay(u) => match self.document.objects.get(&u.definition_handle) {
|
||||
Some(acadrust::objects::ObjectType::UnderlayDefinition(def)) => {
|
||||
ImageModel::from_underlay(u, def)
|
||||
|
||||
+31
-4
@@ -245,6 +245,24 @@ impl Scene {
|
||||
self.hatches.insert(h, model);
|
||||
}
|
||||
}
|
||||
let image_bearing = self.document.get_entity(h).is_some_and(|entity| {
|
||||
matches!(
|
||||
entity,
|
||||
EntityType::RasterImage(_)
|
||||
| EntityType::Ole2Frame(_)
|
||||
| EntityType::Underlay(_)
|
||||
)
|
||||
});
|
||||
if image_bearing {
|
||||
let model = self
|
||||
.document
|
||||
.get_entity(h)
|
||||
.and_then(|entity| self.image_seed_for(entity));
|
||||
self.images.remove(&h);
|
||||
if let Some(model) = model {
|
||||
self.images.insert(h, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
if preserve_text_orientation {
|
||||
for (h, o) in text_orient_backup {
|
||||
@@ -458,12 +476,21 @@ impl Scene {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a freshly-cloned entity, allocating a new handle for it *and* every
|
||||
/// inline sub-entity so the copy never shares a handle with its source.
|
||||
/// Use this (not `add_entity`) whenever inserting a duplicate. (#129)
|
||||
/// Add a clone to the active space with fresh top-level and inline handles.
|
||||
/// Source owner handles are document-local and must not cross drawings.
|
||||
/// (#129, #934)
|
||||
pub fn add_entity_clone(&mut self, mut entity: EntityType) -> Handle {
|
||||
Self::reset_clone_subhandles(&mut self.document, &mut entity);
|
||||
entity.common_mut().handle = Handle::NULL;
|
||||
let common = entity.common_mut();
|
||||
common.handle = Handle::NULL;
|
||||
common.owner_handle = Handle::NULL;
|
||||
common.entity_mode = Some(
|
||||
if self.current_layout != "Model" && self.active_viewport.is_none() {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
},
|
||||
);
|
||||
self.add_entity(entity)
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,39 @@ impl Scene {
|
||||
self.bump_selection_set();
|
||||
}
|
||||
|
||||
pub fn select_all_visible(&mut self) -> usize {
|
||||
let block = self.interaction_block_handle();
|
||||
let frozen: Option<HashSet<Handle>> = self
|
||||
.interaction_viewport_frozen_layers()
|
||||
.map(|layers| layers.iter().copied().collect());
|
||||
let annotation_scale = self.displayed_annotation_scale_handle();
|
||||
let all_visible = self.annotation_all_visible();
|
||||
let handles = self
|
||||
.document
|
||||
.block_records
|
||||
.iter()
|
||||
.find(|record| record.handle == block)
|
||||
.map(|record| record.entity_handles.clone())
|
||||
.unwrap_or_default();
|
||||
let selected = handles
|
||||
.into_iter()
|
||||
.filter(|handle| self.passes_selection_filter(*handle))
|
||||
.filter(|handle| {
|
||||
self.document.get_entity(*handle).is_some_and(|entity| {
|
||||
self.resident_entity_visible(
|
||||
entity,
|
||||
block,
|
||||
frozen.as_ref(),
|
||||
annotation_scale,
|
||||
all_visible,
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
self.replace_selection(selected);
|
||||
self.selected.len()
|
||||
}
|
||||
|
||||
pub(crate) fn selection_fingerprint(&mut self) -> u64 {
|
||||
if self.selection_fingerprint_dirty {
|
||||
let mut fingerprint = self.selected.len() as u64;
|
||||
|
||||
Reference in new issue
Block a user