feat: LED strips — editor notes, docs, demo, smokes, golden scenes, profile (#780)

Stage 5 of #780.

- Import summary: «Strips left unbound after import: {n}» from the backend
  `unbound_led_strips` count; «Optimize plans» reports strips passing
  through walls per space and edits none (AC16).
- Linear field for long strips (ТЗ §13.2): pieces of at most the radius
  along the polyline, emitters thinned to r/4, each piece clipped to the
  visibility fans of its own emitters as separate clipPath children (no
  boolean pass per piece), one floor clip for the whole layer, no fan at
  all where nothing blocks within the radius; a grid index of body faces
  and boxed inside tests; unchanged fields skip re-diffing. 50×50 on the
  large house: first stable frame ~1.4 s, warm space ~1.1 s locally.
- led-strips-v1 profile: demo/benchmark_led_strips.mjs with the derived
  large-house fixture (10×5, 50×50, none), absolute limits of the ТЗ table
  in demo/performance/budgets-led-strips.json, exact counters (zero
  recomputes on HA ticks/camera/colour, ≤50 cache entries, no growth over
  20 cycles); added to the full performance workflow.
- Bundle: LAZY_LED_GZIP_CEILING 10 KiB, LAZY_LED_EDITOR_GZIP_CEILING 11 KiB
  (measured + 10 %, rounded up); overlaps with the initial and editor
  graphs refused; the lazy editor graph stays inside its ceiling.
- Smokes smoke_led_strip_draw/bind/glow, linked in smoke-links; 13 mutants
  in the registry (7 browser guards in the inventory); config field registry
  entry `spaces[].led_strips`.
- Golden: five new scenes on the `golden-led` space of the visual fixture
  (`ledStrips` option, the designer's four strips on #868D94), matrix v71.
- Docs: LIGHT, DEVICE-PRESENTATION, USER-GUIDE (en/ru), UX-MODES,
  ARCHITECTURE, ISOMETRIC, CONFIG-COMPATIBILITY, TOUCH-SUPPORT, demo/stand
  README, performance README; docs/design/led-strips with the unchanged
  designer archive, two paired frames and ACCEPTANCE.md; both changelogs.

Issue: #780
User-Visible: yes
This commit is contained in:
Codex
2026-10-02 13:35:11 +03:00
parent 1511996c5e
commit 9825819cd4
64 changed files with 2075 additions and 134 deletions
+30
View File
@@ -1041,6 +1041,35 @@ binding to **Available again**. A disabled or missing binding keeps its saved
category and receives a separate Home Assistant status instead of silently
moving to another tab.
### LED strip (#780)
An LED strip is drawn on the plan as a polyline and can stand in for any
device instead of its round icon. Everything happens in the **Devices
editor** — there is no need to switch to the Plan editor.
| Action | Result |
|---|---|
| **LED strip** (next to «Add») | Starts drawing. A clean click adds a point; the grid and wall faces attract it, a zero-thickness wall its axis; `Shift` gives 45° steps. A new segment stops at the first face of a thick wall, partition, column or window («The strip stopped at a wall»); doors, gates and passages let it through |
| `Ctrl/Cmd+Z` while drawing | Removes the chain's last point, not another history step |
| `Esc`, a double click on the last point, pressing **LED strip** again, leaving the editor | Finish the strip; a chain of fewer than two distinct points is not saved |
| A click on the first point (at least three vertices) | Closes the strip |
| After finishing | The device picker opens: lights first, devices bound to another strip are disabled with an explanation, **New device…** creates one and binds it in the same write, **Later** keeps an unbound strip (grey dashes, visible in the Devices editor only) |
| A click on a strip | Selects it and shows its vertices; they can be dragged, and walls stop them even on a fast drag. The tray offers **Device settings**, **Bind / Change device**, **Unbind**, **Show as icon**, **Delete strip**. `Esc` or a clean click on free space drops the selection |
| In the device dialog | **Show as LED strip** draws a shape for the same marker (or brings a saved one back at once); **Show as icon** returns the ordinary icon, the shape is kept hidden and comes back without redrawing. The usual unsaved-changes question comes first |
Binding creates no new Home Assistant device: the same marker, light
settings, tap actions and badge. The strip glows when the device does: with
Glow on, a white core and a soft band of colour 50 cm wide by default (or the
device's own radius); without Glow the core takes the light's colour. Light
does not pass through walls or closed doors. In View the whole strip is one
tap target, like an icon. Every finished shape change and every switch of the
representation is one **Undo/Redo** step.
«Unbind» keeps an unbound shape, «Delete strip» deletes the shape but not the
device. Deleting the device leaves the strip unbound. Up to 50 points per
strip and 50 strips per space (hidden shapes included). «Optimize plans»
reports strips passing through walls and changes nothing in them.
### Marker basics
The dialog has five cards: **Basics**, a compact tap-action card without a
@@ -2154,6 +2183,7 @@ Marker attachments accept PDF/PNG/JPG/WebP/TXT up to 50 MB, with a
| Room details use hover in View | A touch-only user may need an editor or another visible metric |
| Sun has no exterior 3D model | It cannot know shadows from trees, awnings or neighbouring structures |
| Icon rules use regular expressions | First matching rule wins and invalid expressions are rejected |
| LED strips are not cut by walls | A thickened wall does not edit a strip: parts inside the wall do not glow, «Optimize plans» shows how many strips pass through walls |
Storage guards allow up to 50 spaces, 400 rooms per space, 2,000 markers, 500
openings, 1,000 Background items and bounded wall/physical-object catalogues