feat(xref): honor BlockRecord is_loaded — skip Unloaded xrefs

When the host DWG marks an xref as Unloaded (via XREF→Unload in
AutoCAD), the user explicitly chose NOT to load that reference. We
were ignoring that and pulling the external file in anyway, which
on large drawings could push GPU memory past the device budget.

Bump the acadrust dep to the branch that exposes
`BlockRecord::is_loaded`, then short-circuit `resolve_xrefs` for
any entry with `is_loaded == Some(false)`. New `XrefStatus::Unloaded`
surfaces this in the command-line log so the user can see which
references were skipped (and can re-load them via the XREF dialog).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Hakan 2026-05-14 11:20:11 +03:00
commit e88a946176
5 changed files with 32 additions and 6 deletions

2
Cargo.lock generated
View file

@ -41,7 +41,7 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
[[package]]
name = "acadrust"
version = "0.3.4"
source = "git+https://github.com/HakanSeven12/acadrust?rev=622729f#622729f961dae4d29fbc890d3622a3a86294ec8d"
source = "git+https://github.com/HakanSeven12/acadrust?branch=feat%2Fexpose-blockrecord-is-loaded#44ee57604af6f29a3f3ace05c2e49879fb8ae18a"
dependencies = [
"ahash",
"anyhow",

View file

@ -23,4 +23,4 @@ rayon = "1"
windows-sys = { version = "0.59", features = ["Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
[patch.crates-io]
acadrust = { git = "https://github.com/HakanSeven12/acadrust", rev = "622729f" }
acadrust = { git = "https://github.com/HakanSeven12/acadrust", branch = "feat/expose-blockrecord-is-loaded" }

View file

@ -584,6 +584,12 @@ impl H7CAD {
info.name, info.path
));
}
crate::io::xref::XrefStatus::Unloaded => {
self.command_line.push_info(&format!(
"XREF Unloaded (skipped): \"{}\"",
info.name
));
}
}
}
self.tabs[i].scene.populate_hatches_from_document();

View file

@ -155,6 +155,12 @@ impl H7CAD {
info.name, info.path
));
}
crate::io::xref::XrefStatus::Unloaded => {
self.command_line.push_info(&format!(
"XREF Unloaded (skipped): \"{}\"",
info.name
));
}
}
}
}

View file

@ -13,6 +13,9 @@ pub enum XrefStatus {
Loaded,
/// File path is set but the file could not be found or read.
NotFound,
/// XRef is marked Unloaded in the host DWG — we honor that and
/// skip resolving the external file. The user can re-load via UI.
Unloaded,
}
/// Describes a single external reference found in a document.
@ -31,17 +34,28 @@ pub struct XrefInfo {
///
/// Returns a list of [`XrefInfo`] describing each xref block found.
pub fn resolve_xrefs(doc: &mut CadDocument, base_dir: &Path) -> Vec<XrefInfo> {
// Collect xref blocks: (name, raw_path, block_record_handle)
let xref_entries: Vec<(String, String, Handle)> = doc
// Collect xref blocks: (name, raw_path, block_record_handle, is_loaded)
// is_loaded == Some(false) means the host DWG marked this xref Unloaded
// via XREF→Unload; respect that and skip reading the external file.
let xref_entries: Vec<(String, String, Handle, Option<bool>)> = doc
.block_records
.iter()
.filter(|br| (br.flags.is_xref || br.flags.is_xref_overlay) && !br.xref_path.is_empty())
.map(|br| (br.name.clone(), br.xref_path.clone(), br.handle))
.map(|br| (br.name.clone(), br.xref_path.clone(), br.handle, br.is_loaded))
.collect();
let mut result = Vec::new();
for (block_name, raw_path, br_handle) in xref_entries {
for (block_name, raw_path, br_handle, is_loaded) in xref_entries {
if is_loaded == Some(false) {
result.push(XrefInfo {
name: block_name,
path: raw_path,
status: XrefStatus::Unloaded,
});
continue;
}
let resolved = resolve_path(&raw_path, base_dir);
let status = match &resolved {