feat(layers): enforce layer lock (select/modify/fade + cursor badge)

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>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-01 13:10:39 +03:00
1 parent c71950fa7c
commit 56e1c03ac2
11 files changed
+149 -2

No files matched your search

+14
View File
@@ -130,6 +130,16 @@ impl Scene {
let Some(e) = self.document.get_entity(h) else {
continue;
};
// Never quick-select objects on a locked layer.
if self
.document
.layers
.get(&e.common().layer)
.map(|l| l.is_locked())
.unwrap_or(false)
{
continue;
}
if let Some(t) = type_name {
if entity_type_name(e) != t {
continue;
@@ -316,6 +326,10 @@ impl Scene {
pub fn erase_entities(&mut self, handles: &[Handle]) {
for &h in handles {
// Objects on a locked layer can't be erased.
if self.is_layer_locked(h) {
continue;
}
self.document.remove_entity(h);
self.selected.remove(&h);
self.hatches.remove(&h);