forked from 1b-agent/opencadstudio-upstream
feat(annotation): integrate object contexts
This commit is contained in:
1 parent
f39481ac49
commit
e03e091b3c
37 files changed
+2823
-584
No files matched your search
+122
-2
@@ -3155,7 +3155,11 @@ impl OpenCADStudio {
|
||||
self.tabs[i].scene.add_entity_clone(entity)
|
||||
})
|
||||
.collect();
|
||||
self.merge_clipboard_ext_objects(i, &by_index);
|
||||
let annotation_delta = match translate {
|
||||
Some(crate::command::EntityTransform::Translate(delta)) => delta,
|
||||
_ => glam::DVec3::ZERO,
|
||||
};
|
||||
self.merge_clipboard_ext_objects(i, &by_index, annotation_delta);
|
||||
// Recreate any group whose whole membership was copied, so a pasted
|
||||
// group stays grouped — cross-drawing too, since the groups were
|
||||
// snapshotted into the clipboard at copy time. `by_index` is aligned
|
||||
@@ -3187,7 +3191,12 @@ impl OpenCADStudio {
|
||||
/// references, and re-pointing the pasted entity's `xdictionary_handle` at
|
||||
/// the new root. `by_index` is the paste's new entity handles, aligned with
|
||||
/// the clipboard order (NULL where the add failed). No-op without captures.
|
||||
pub(super) fn merge_clipboard_ext_objects(&mut self, i: usize, by_index: &[Handle]) {
|
||||
pub(super) fn merge_clipboard_ext_objects(
|
||||
&mut self,
|
||||
i: usize,
|
||||
by_index: &[Handle],
|
||||
annotation_delta: glam::DVec3,
|
||||
) {
|
||||
if self.clipboard_deps.ext_objects.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -3204,6 +3213,11 @@ impl OpenCADStudio {
|
||||
if let Some(e) = doc.get_entity_mut(new_entity) {
|
||||
e.common_mut().xdictionary_handle = Some(new_root);
|
||||
}
|
||||
crate::scene::annotative::translate_annotation_contexts(
|
||||
doc,
|
||||
new_entity,
|
||||
annotation_delta,
|
||||
);
|
||||
}
|
||||
}
|
||||
// The wires were tessellated before the filters existed; refresh only
|
||||
@@ -3270,6 +3284,10 @@ fn recreate_ext_subtree(
|
||||
if let Some(eh) = entity_handle {
|
||||
remap.insert(cap.src_entity_handle, eh);
|
||||
}
|
||||
for (old, scale) in &cap.annotation_scales {
|
||||
let target = crate::scene::annotative::ensure_scale_object(doc, scale);
|
||||
remap.insert(*old, target);
|
||||
}
|
||||
for (old, _) in &cap.objects {
|
||||
remap.insert(*old, doc.allocate_handle());
|
||||
}
|
||||
@@ -3282,6 +3300,50 @@ fn recreate_ext_subtree(
|
||||
remap.get(&cap.root).copied()
|
||||
}
|
||||
|
||||
/// Replace references to a clipboard entity inside one recreated extension
|
||||
/// dictionary graph after its final block-owned handle becomes known.
|
||||
pub(crate) fn remap_ext_subtree_reference(
|
||||
doc: &mut acadrust::CadDocument,
|
||||
root: Handle,
|
||||
source_entity: Handle,
|
||||
target_entity: Handle,
|
||||
) {
|
||||
use acadrust::objects::ObjectType;
|
||||
use rustc_hash::FxHashSet;
|
||||
use std::collections::HashMap;
|
||||
|
||||
let remap = HashMap::from([(source_entity, target_entity)]);
|
||||
let mut seen = FxHashSet::default();
|
||||
let mut pending = vec![root];
|
||||
while let Some(handle) = pending.pop() {
|
||||
if handle.is_null() || !seen.insert(handle) {
|
||||
continue;
|
||||
}
|
||||
let children = match doc.objects.get(&handle) {
|
||||
Some(ObjectType::Dictionary(dictionary)) => {
|
||||
let mut children: Vec<_> =
|
||||
dictionary.entries.iter().map(|(_, child)| *child).collect();
|
||||
if let Some(extension) = dictionary.xdictionary_handle {
|
||||
children.push(extension);
|
||||
}
|
||||
children
|
||||
}
|
||||
Some(ObjectType::DictionaryWithDefault(dictionary)) => {
|
||||
let mut children: Vec<_> =
|
||||
dictionary.entries.iter().map(|(_, child)| *child).collect();
|
||||
children.push(dictionary.default_handle);
|
||||
children
|
||||
}
|
||||
_ => Vec::new(),
|
||||
};
|
||||
pending.extend(children);
|
||||
if let Some(mut object) = doc.objects.remove(&handle) {
|
||||
remap_object(&mut object, handle, &remap);
|
||||
doc.objects.insert(handle, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Rewrite a cloned extension-dictionary object onto fresh handles: set its own
|
||||
/// handle to `new_handle` and remap its owner and any handle references it holds
|
||||
/// through `remap` (a handle still in the source space stays unchanged, which is
|
||||
@@ -3326,6 +3388,11 @@ fn remap_object(
|
||||
ObjectType::XRecord(x) => {
|
||||
x.handle = new_handle;
|
||||
x.owner = map(x.owner);
|
||||
for entry in &mut x.entries {
|
||||
if let acadrust::objects::XRecordValue::Handle(handle) = &mut entry.value {
|
||||
*handle = map(*handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectType::Group(g) => {
|
||||
g.handle = new_handle;
|
||||
@@ -3334,6 +3401,59 @@ fn remap_object(
|
||||
*h = map(*h);
|
||||
}
|
||||
}
|
||||
ObjectType::ObjectContextData(context) => {
|
||||
context.handle = new_handle;
|
||||
context.owner_handle = map(context.owner_handle);
|
||||
for reactor in &mut context.reactors {
|
||||
*reactor = map(*reactor);
|
||||
}
|
||||
if let Some(dictionary) = &mut context.xdictionary_handle {
|
||||
*dictionary = map(*dictionary);
|
||||
}
|
||||
context.scale = map(context.scale);
|
||||
match &mut context.kind {
|
||||
acadrust::objects::ObjectContextKind::Dim(dimension) => {
|
||||
dimension.block = map(dimension.block);
|
||||
}
|
||||
acadrust::objects::ObjectContextKind::HatchView(hatch) => {
|
||||
hatch.view = map(hatch.view);
|
||||
}
|
||||
acadrust::objects::ObjectContextKind::MTextAttribute(attribute) => {
|
||||
if let Some(embedded) = &mut attribute.context {
|
||||
embedded.owner_handle = map(embedded.owner_handle);
|
||||
for reactor in &mut embedded.reactors {
|
||||
*reactor = map(*reactor);
|
||||
}
|
||||
if let Some(dictionary) = &mut embedded.xdictionary_handle {
|
||||
*dictionary = map(*dictionary);
|
||||
}
|
||||
embedded.scale = map(embedded.scale);
|
||||
}
|
||||
}
|
||||
acadrust::objects::ObjectContextKind::MLeader(mleader) => {
|
||||
if let Some(handle) = &mut mleader.text_style_handle {
|
||||
*handle = map(*handle);
|
||||
}
|
||||
if let Some(handle) = &mut mleader.block_content_handle {
|
||||
*handle = map(*handle);
|
||||
}
|
||||
if let Some(handle) = &mut mleader.scale_handle {
|
||||
*handle = map(*handle);
|
||||
}
|
||||
for root in &mut mleader.leader_roots {
|
||||
for line in &mut root.lines {
|
||||
if let Some(handle) = &mut line.line_type_handle {
|
||||
*handle = map(*handle);
|
||||
}
|
||||
if let Some(handle) = &mut line.arrowhead_handle {
|
||||
*handle = map(*handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// Other leaf object kinds don't appear in an entity xdictionary; if one
|
||||
// does, it's inserted with the fresh handle below via the caller's key,
|
||||
// but its internal owner is left as-is (best effort).
|
||||
|
||||
Reference in new issue
Block a user