Feat: VPLAYER ALL — freeze/thaw layer across all viewports in layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-04-02 23:13:09 +03:00
commit d66673a4fa
2 changed files with 56 additions and 23 deletions

View file

@ -286,7 +286,8 @@ impl H7CAD {
}
}
CmdResult::VpLayerUpdate { vp_handle, freeze, thaw } => {
// Resolve layer names → handles, then update frozen_layers on the viewport.
// Resolve layer names → handles, then update frozen_layers on the viewport(s).
// vp_handle == Handle::NULL means "apply to all viewports in current layout".
let freeze_handles: Vec<Handle> = freeze.iter()
.filter_map(|name| {
self.tabs[i].scene.document.layers.iter()
@ -305,19 +306,36 @@ impl H7CAD {
let mut frozen_count = 0usize;
let mut thawed_count = 0usize;
if let Some(acadrust::EntityType::Viewport(vp)) =
self.tabs[i].scene.document.get_entity_mut(vp_handle)
{
for h in &freeze_handles {
if !vp.frozen_layers.contains(h) {
vp.frozen_layers.push(*h);
frozen_count += 1;
// Collect target viewport handles
let target_handles: Vec<Handle> = if vp_handle == acadrust::Handle::NULL {
// All viewports in current layout block
let block_handle = self.tabs[i].scene.current_layout_block_handle_pub();
self.tabs[i].scene.document.entities()
.filter(|e| {
e.common().owner_handle == block_handle
&& matches!(e, acadrust::EntityType::Viewport(_))
})
.map(|e| e.common().handle)
.collect()
} else {
vec![vp_handle]
};
for &target_handle in &target_handles {
if let Some(acadrust::EntityType::Viewport(vp)) =
self.tabs[i].scene.document.get_entity_mut(target_handle)
{
for h in &freeze_handles {
if !vp.frozen_layers.contains(h) {
vp.frozen_layers.push(*h);
frozen_count += 1;
}
}
for h in &thaw_handles {
let before = vp.frozen_layers.len();
vp.frozen_layers.retain(|fh| fh != h);
if vp.frozen_layers.len() < before { thawed_count += 1; }
}
}
for h in &thaw_handles {
let before = vp.frozen_layers.len();
vp.frozen_layers.retain(|fh| fh != h);
if vp.frozen_layers.len() < before { thawed_count += 1; }
}
}

View file

@ -2,9 +2,11 @@
//
// Usage (command line):
// VPLAYER
// > F <layer_name> → freeze layer in active viewport
// > T <layer_name> → thaw layer in active viewport
// > Enter → exit
// > F <layer_name> → freeze layer in active viewport
// > T <layer_name> → thaw layer in active viewport
// > F ALL <layer_name> → freeze layer in ALL viewports
// > T ALL <layer_name> → thaw layer in ALL viewports
// > Enter → exit
//
// Layer names are case-insensitive. Multiple space-separated names are accepted.
@ -43,12 +45,22 @@ impl CadCommand for VplayerCommand {
return Some(CmdResult::Cancel);
}
let mut parts = text.splitn(2, char::is_whitespace);
let op = parts.next().unwrap_or("").to_uppercase();
let rest = parts.next().unwrap_or("").trim();
let tokens: Vec<&str> = text.split_whitespace().collect();
if tokens.is_empty() {
return None;
}
let layer_names: Vec<String> = rest
.split_whitespace()
let op = tokens[0].to_uppercase();
// Check for ALL keyword: "F ALL layer1 layer2" or "T ALL layer1"
let (all_viewports, layer_start) = if tokens.get(1).map(|s| s.to_uppercase().as_str() == "ALL").unwrap_or(false) {
(true, 2)
} else {
(false, 1)
};
let layer_names: Vec<String> = tokens[layer_start..]
.iter()
.map(|s| s.to_string())
.collect();
@ -56,14 +68,17 @@ impl CadCommand for VplayerCommand {
return None; // no layer name given — ignore and re-prompt
}
// Handle::NULL signals "apply to all viewports" in cmd_result.rs
let vp_handle = if all_viewports { acadrust::Handle::NULL } else { self.vp_handle };
match op.as_str() {
"F" | "FREEZE" => Some(CmdResult::VpLayerUpdate {
vp_handle: self.vp_handle,
vp_handle,
freeze: layer_names,
thaw: vec![],
}),
"T" | "THAW" => Some(CmdResult::VpLayerUpdate {
vp_handle: self.vp_handle,
vp_handle,
freeze: vec![],
thaw: layer_names,
}),