Merge upstream main; follow the boxed MText codec type and the updated palette branch

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-10-16 16:56:46 +03:00
commit 8f20f0aef6
119 files changed
+560 -1020

No files matched your search

+2 -2
View File
@@ -1128,7 +1128,7 @@ impl OpenCADStudio {
.filter(|br| reload_keys.contains(&br.handle.value()))
.map(|br| br.handle)
.collect();
let (infos, _dropped) = crate::io::xref::resolve_xrefs_for_keys(
let infos = crate::io::xref::resolve_xrefs_for_keys(
&mut self.tabs[i].scene.document,
base_dir,
&handles,
@@ -1674,7 +1674,7 @@ impl OpenCADStudio {
self.tabs[i].xref_unloaded.remove(key);
self.tabs[i].xref_stat_cache.remove(key);
}
let (infos, _dropped) = crate::io::xref::resolve_xrefs(
let infos = crate::io::xref::resolve_xrefs(
&mut self.tabs[i].scene.document,
&base_dir,
);
+1 -1
View File
@@ -294,7 +294,7 @@ impl OpenCADStudio {
} else {
line.layer
};
scene.add_entity(codec::EntityType::MText(mtext));
scene.add_entity(codec::EntityType::MText(Box::new(mtext)));
erase.extend(line.handles);
}
erase.sort();
+1 -1
View File
@@ -2389,7 +2389,7 @@ impl OpenCADStudio {
Vector3::new(mv.center.x - mv.target.x, mv.center.y - mv.target.y, 0.0);
vp.view_height = mv.height;
vp.custom_scale = scale;
scene.add_entity(codec::EntityType::Viewport(vp));
scene.add_entity(codec::EntityType::Viewport(Box::new(vp)));
// A paper-space named view of the same name frames it.
let mut named = codec::tables::View::new(title.as_str());
named.handle = scene.document.allocate_handle();
+49 -40
View File
@@ -3671,53 +3671,62 @@ impl OpenCADStudio {
.push_error(crate::tf!("COMPARE: {error}").as_ref()),
}
}
// AUDIT runs the codec's audit; `AUDIT Yes` also applies its
// repair, undoable as one step.
"AUDIT" => {
use std::collections::BTreeSet;
let mut undefined_layers: BTreeSet<String> = BTreeSet::new();
let mut undefined_blocks: BTreeSet<String> = BTreeSet::new();
let mut total = 0usize;
{
use crate::command::KeywordCommand;
let c = KeywordCommand::new(
"AUDIT",
"AUDIT Fix any errors detected? [Yes / No] <No>:",
vec![("Yes", "YES", None), ("No", "NO", None)],
)
.with_default("NO");
self.command_line.push_info(&c.prompt());
self.tabs[i].active_cmd = Some(Box::new(c));
}
cmd if cmd.starts_with("AUDIT ") => {
let fix = cmd[6..].trim().to_uppercase().starts_with('Y');
let report = self.tabs[i].scene.document.audit();
let total = {
let doc = &self.tabs[i].scene.document;
for e in doc.entities() {
total += 1;
let layer = &e.common().layer;
if !layer.is_empty() && doc.layers.get(layer).is_none() {
undefined_layers.insert(layer.clone());
}
if let codec::EntityType::Insert(ins) = e {
if doc.block_records.get(&ins.block_name).is_none() {
undefined_blocks.insert(ins.block_name.clone());
}
}
}
}
doc.entities().count() + doc.objects.len()
};
self.command_line
.push_output(crate::tf!("AUDIT: scanned {total} object(s).").as_ref());
if undefined_layers.is_empty() && undefined_blocks.is_empty() {
if report.is_clean() {
self.command_line
.push_output(crate::t!("AUDIT: no issues found.").as_ref());
} else {
if !undefined_layers.is_empty() {
self.command_line.push_error(
crate::tf!(
"AUDIT: reference(s) to undefined layer(s): {}",
undefined_layers.into_iter().collect::<Vec<_>>().join(", ")
)
.as_ref(),
);
}
if !undefined_blocks.is_empty() {
self.command_line.push_error(
crate::tf!(
"AUDIT: reference(s) to undefined block(s): {}",
undefined_blocks.into_iter().collect::<Vec<_>>().join(", ")
)
.as_ref(),
);
}
self.command_line.push_info(
crate::t!("AUDIT: report only — no automatic repair performed.").as_ref(),
return Some(Task::none());
}
self.command_line.push_error(
crate::tf!(
"AUDIT: {} error(s), {} warning(s) found.",
report.error_count(),
report.warning_count()
)
.as_ref(),
);
// ponytail: first 50 issues only; the counts above cover the rest.
for issue in report.issues.iter().take(50) {
self.command_line
.push_info(&format!(" {:?}: {}", issue.code, issue.message));
}
if fix {
self.push_undo_snapshot(i, "AUDIT");
let repair = self.tabs[i].scene.document.repair();
self.command_line.push_output(
crate::tf!(
"AUDIT: {} repair(s) applied, {} issue(s) left unresolved.",
repair.actions.len(),
repair.unresolved.len()
)
.as_ref(),
);
if !repair.actions.is_empty() {
self.tabs[i].dirty = true;
self.tabs[i].scene.rebuild_derived_caches();
self.refresh_layer_panel();
}
}
}
+2 -2
View File
@@ -126,10 +126,10 @@ mod tests {
let i = app.active_tab;
let first = app.tabs[i]
.scene
.add_entity(codec::EntityType::Viewport(codec::entities::Viewport::new()));
.add_entity(codec::EntityType::Viewport(Box::new(codec::entities::Viewport::new())));
let second = app.tabs[i]
.scene
.add_entity(codec::EntityType::Viewport(codec::entities::Viewport::new()));
.add_entity(codec::EntityType::Viewport(Box::new(codec::entities::Viewport::new())));
app.tabs[i].scene.active_viewport = Some(first);
let _ = app.run_command_line("UCSFOLLOW 1");
assert!(app.tabs[i].scene.ucs_follow());
+5 -2
View File
@@ -1000,7 +1000,10 @@ impl OpenCADStudio {
match self.tabs[i]
.scene
.document
.add_entity_to_layout(codec::EntityType::Viewport(vp), &layout_name)
.add_entity_to_layout(
codec::EntityType::Viewport(Box::new(vp)),
&layout_name,
)
{
Ok(handle) => {
self.tabs[i].scene.auto_fit_viewport(handle);
@@ -2207,7 +2210,7 @@ mod tests {
locked_hatch.common.layer = "LOCKED_LAYER".into();
let h_locked_hatch = app.tabs[i]
.scene
.add_entity_clone(EntityType::Hatch(locked_hatch));
.add_entity_clone(EntityType::Hatch(Box::new(locked_hatch)));
let h_line = app.tabs[i]
.scene