forked from 1b-agent/opencadstudio-upstream
Locked-layer objects were fully editable. Now they stay visible and snappable but are otherwise protected: - Not selectable: the five interactive pick paths (box, lasso, single click, cycling, box-release) plus SELECTALL and QSELECT skip locked entities. - Not modifiable (defense-in-depth even if a handle slips through): transform_entities, erase_entities, apply_grip and the Properties commit all skip locked entities. - Faded: entities on a locked layer render dimmed toward the background (render_style + wire tessellation); toggling lock re-tessellates. - Snap still works: locked entities are intentionally kept in the wire set (visibility_ok untouched), so object snap keeps finding them. - Feedback: a small padlock is drawn by the crosshair when hovering a locked object, and clicking one prints "Object is on locked layer …". New Scene::is_layer_locked / locked_layer_name helpers centralise the check (mirroring layer_hidden). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
101 lines
3.8 KiB
Rust
101 lines
3.8 KiB
Rust
// Auto-split from scene/mod.rs. Pure text-move; behaviour unchanged.
|
|
use super::*;
|
|
|
|
impl Scene {
|
|
// ── Group helpers ──────────────────────────────────────────────────────
|
|
|
|
pub fn groups(&self) -> impl Iterator<Item = &acadrust::objects::Group> {
|
|
self.document.objects.values().filter_map(|obj| match obj {
|
|
ObjectType::Group(g) => Some(g),
|
|
_ => None,
|
|
})
|
|
}
|
|
|
|
/// Returns the names of all groups that contain `handle`.
|
|
pub fn group_names_for_entity(&self, handle: Handle) -> Vec<String> {
|
|
self.groups()
|
|
.filter(|g| g.contains(handle))
|
|
.map(|g| g.name.clone())
|
|
.collect()
|
|
}
|
|
|
|
/// Creates a named group from the given handles and registers it in the group dictionary.
|
|
pub fn create_group(&mut self, name: String, handles: Vec<Handle>) -> Handle {
|
|
let group_dict_handle = self.document.header.acad_group_dict_handle;
|
|
let mut group = acadrust::objects::Group::new(&name);
|
|
group.handle = self.document.allocate_handle();
|
|
group.owner = group_dict_handle;
|
|
group.add_entities(handles);
|
|
let gh = group.handle;
|
|
self.document.objects.insert(gh, ObjectType::Group(group));
|
|
if let Some(ObjectType::Dictionary(dict)) =
|
|
self.document.objects.get_mut(&group_dict_handle)
|
|
{
|
|
dict.add_entry(&name, gh);
|
|
}
|
|
gh
|
|
}
|
|
|
|
/// Dissolves all groups that contain any of the given handles.
|
|
/// Returns the number of groups removed.
|
|
pub fn delete_groups_containing(&mut self, handles: &[Handle]) -> usize {
|
|
let group_dict_handle = self.document.header.acad_group_dict_handle;
|
|
let to_delete: Vec<Handle> = self
|
|
.document
|
|
.objects
|
|
.values()
|
|
.filter_map(|obj| match obj {
|
|
ObjectType::Group(g) if handles.iter().any(|h| g.contains(*h)) => Some(g.handle),
|
|
_ => None,
|
|
})
|
|
.collect();
|
|
let count = to_delete.len();
|
|
for gh in &to_delete {
|
|
if let Some(ObjectType::Dictionary(dict)) =
|
|
self.document.objects.get_mut(&group_dict_handle)
|
|
{
|
|
dict.entries.retain(|(_, h)| h != gh);
|
|
}
|
|
self.document.objects.remove(gh);
|
|
}
|
|
count
|
|
}
|
|
|
|
/// If `handle` belongs to any selectable groups, also select all other members of those groups.
|
|
pub fn expand_selection_for_groups(&mut self, handles: &[Handle]) {
|
|
let to_add: Vec<Handle> = self
|
|
.document
|
|
.objects
|
|
.values()
|
|
.filter_map(|obj| match obj {
|
|
ObjectType::Group(g) if g.selectable && handles.iter().any(|h| g.contains(*h)) => {
|
|
Some(g.entities.clone())
|
|
}
|
|
_ => None,
|
|
})
|
|
.flatten()
|
|
.collect();
|
|
for h in to_add {
|
|
self.selected.insert(h);
|
|
}
|
|
self.bump_selection();
|
|
}
|
|
|
|
// ── Layer helpers ──────────────────────────────────────────────────────
|
|
|
|
pub fn toggle_layer_visibility(&mut self, name: &str) {
|
|
if let Some(layer) = self.document.layers.get_mut(name) {
|
|
layer.flags.off = !layer.flags.off;
|
|
}
|
|
self.bump_geometry();
|
|
}
|
|
|
|
pub fn toggle_layer_lock(&mut self, name: &str) {
|
|
if let Some(layer) = self.document.layers.get_mut(name) {
|
|
layer.flags.locked = !layer.flags.locked;
|
|
}
|
|
// Re-tessellate so the locked-layer dim (fade) appears/clears at once.
|
|
self.bump_geometry();
|
|
}
|
|
}
|