forked from 1b-agent/opencadstudio-upstream
ATTSYNC: rebuild attributes from the definitions
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d583d9d421
commit
eaa44cccc1
1 file changed
+37
-18
@@ -160,13 +160,16 @@ impl OpenCADStudio {
|
|||||||
glam::DVec3::new(base.x, base.y, base.z)
|
glam::DVec3::new(base.x, base.y, base.z)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconcile every editable reference of `block` with the block's
|
/// Rebuild the attributes of every editable reference of `block` from the
|
||||||
/// attribute definitions: attributes whose tag is gone are dropped, new
|
/// block's attribute definitions, in their order: each attribute takes
|
||||||
/// ones are added with their default value, and the values of the rest
|
/// its definition's placement and text settings through the reference's
|
||||||
/// are kept.
|
/// transform, keeps the value it had (new ones take the default), and
|
||||||
|
/// attributes whose definition is gone are dropped. Constant definitions
|
||||||
|
/// carry no attribute.
|
||||||
pub(in crate::app) fn attsync_block(&mut self, i: usize, block: &str) {
|
pub(in crate::app) fn attsync_block(&mut self, i: usize, block: &str) {
|
||||||
|
use codec::Entity as _;
|
||||||
let doc = &self.tabs[i].scene.document;
|
let doc = &self.tabs[i].scene.document;
|
||||||
let attdefs: Vec<(String, String)> = doc
|
let attdefs: Vec<codec::entities::AttributeDefinition> = doc
|
||||||
.block_records
|
.block_records
|
||||||
.get(block)
|
.get(block)
|
||||||
.map(|br| {
|
.map(|br| {
|
||||||
@@ -174,14 +177,15 @@ impl OpenCADStudio {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|h| doc.get_entity(*h))
|
.filter_map(|h| doc.get_entity(*h))
|
||||||
.filter_map(|e| match e {
|
.filter_map(|e| match e {
|
||||||
codec::EntityType::AttributeDefinition(a) => {
|
codec::EntityType::AttributeDefinition(a) if !a.flags.constant => {
|
||||||
Some((a.tag.clone(), a.default_value.clone()))
|
Some(a.clone())
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
let base = crate::scene::render_graph::block_base_point(doc, block);
|
||||||
let inserts: Vec<_> = doc
|
let inserts: Vec<_> = doc
|
||||||
.entities()
|
.entities()
|
||||||
.filter_map(|entity| match entity {
|
.filter_map(|entity| match entity {
|
||||||
@@ -200,22 +204,37 @@ impl OpenCADStudio {
|
|||||||
self.push_undo_snapshot(i, "ATTSYNC");
|
self.push_undo_snapshot(i, "ATTSYNC");
|
||||||
let mut changes = Vec::new();
|
let mut changes = Vec::new();
|
||||||
for handle in inserts {
|
for handle in inserts {
|
||||||
let Some(codec::EntityType::Insert(ins)) =
|
let Some(codec::EntityType::Insert(ins)) = self.tabs[i].scene.document.get_entity(handle)
|
||||||
self.tabs[i].scene.document.get_entity_mut(handle)
|
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
ins.attributes
|
let transform = crate::scene::render_graph::insert_transform_with_base(ins, base);
|
||||||
.retain(|a| attdefs.iter().any(|(t, _)| t.eq_ignore_ascii_case(&a.tag)));
|
let mut rebuilt = Vec::with_capacity(attdefs.len());
|
||||||
for (tag, default) in &attdefs {
|
for def in &attdefs {
|
||||||
if !ins.attributes.iter().any(|a| a.tag.eq_ignore_ascii_case(tag)) {
|
let previous = ins
|
||||||
ins.attributes.push(codec::entities::AttributeEntity::new(
|
.attributes
|
||||||
tag.clone(),
|
.iter()
|
||||||
default.clone(),
|
.find(|a| a.tag.eq_ignore_ascii_case(&def.tag));
|
||||||
));
|
let mut attribute = codec::entities::AttributeEntity::from_definition(
|
||||||
|
def,
|
||||||
|
previous.map(|a| a.value.clone()),
|
||||||
|
);
|
||||||
|
attribute.apply_transform(&transform);
|
||||||
|
attribute.common.handle = previous.map_or(codec::Handle::NULL, |a| a.common.handle);
|
||||||
|
attribute.common.owner_handle = handle;
|
||||||
|
rebuilt.push(attribute);
|
||||||
|
}
|
||||||
|
for attribute in &mut rebuilt {
|
||||||
|
if attribute.common.handle.is_null() {
|
||||||
|
attribute.common.handle = self.tabs[i].scene.document.allocate_handle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changes.push((ins.common.handle, crate::scene::ChangeKind::Modified));
|
if let Some(codec::EntityType::Insert(ins)) =
|
||||||
|
self.tabs[i].scene.document.get_entity_mut(handle)
|
||||||
|
{
|
||||||
|
ins.attributes = rebuilt;
|
||||||
|
changes.push((handle, crate::scene::ChangeKind::Modified));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.tabs[i].scene.bump_entities(&changes);
|
self.tabs[i].scene.bump_entities(&changes);
|
||||||
self.tabs[i].dirty = true;
|
self.tabs[i].dirty = true;
|
||||||
|
|||||||
Reference in new issue
Block a user