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

+19 -1
View File
@@ -483,10 +483,28 @@ impl Scene {
} else {
self.paper_bg_color
};
(adapt_to_bg(color, bg), pl, pat, lw, aci)
// Objects on a locked layer are dimmed toward the background so they
// read as "not editable" (they stay visible and snappable).
let adapted = adapt_to_bg(color, bg);
let final_color = if layer_locked(&self.document, e) {
crate::scene::cache::block_cache::fade_toward_bg(adapted, bg)
} else {
adapted
};
(final_color, pl, pat, lw, aci)
}
}
/// Whether an entity sits on a locked layer (via the document's layer table).
/// Document-only so it is safe from the parallel tessellation path.
pub(in crate::scene) fn layer_locked(document: &CadDocument, e: &EntityType) -> bool {
document
.layers
.get(&e.common().layer)
.map(|l| l.is_locked())
.unwrap_or(false)
}
// ── Document-only render-style helpers (no &self, safe to call from parallel contexts) ──
/// Resolves the effective linetype name for an entity, falling back to the