mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 06:59:46 +00:00
fix(led): preserve strip corners and feather the complete light field
Keep real end and corner emitters, robust decimal joins and wall-circle sweep events. Render one positive-winding compound visibility clip so Chromium cannot cancel or cut away overlapping light regions. Add independent pixel oracles for glow falloff and wall-following tubes. Replace the lossy fan-count limit with explicit cached-path bounds while retaining the original timing and warm-cycle heap-growth limits. Issue: #788 User-Visible: yes
This commit is contained in:
@@ -2,6 +2,11 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Fixed remaining LED-strip rendering defects: clean joins on fractional and
|
||||
slightly tilted contours, continuous light without cut-out wedges, and an
|
||||
equally soft falloff at both ends and the outside of sharp turns
|
||||
([#788](https://github.com/Matysh/houseplan-card/issues/788)).
|
||||
|
||||
## v1.79.0-beta.6 — 2026-10-03
|
||||
|
||||
- Fixed rectangular LED strips on wall faces: corners remain exact miters and
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
|
||||
## Не выпущено
|
||||
|
||||
- Исправлены оставшиеся дефекты LED-лент: выступы на стыках с дробными
|
||||
координатами и небольшим наклоном, вырезы внутри свечения и резкие края
|
||||
вместо плавного затухания на концах и снаружи острых углов
|
||||
([#788](https://github.com/Matysh/houseplan-card/issues/788)).
|
||||
|
||||
## v1.79.0-beta.6 — 2026-10-03
|
||||
|
||||
- Исправлены прямоугольные LED-ленты на гранях стен: углы теперь остаются
|
||||
|
||||
+39
-15
@@ -420,18 +420,24 @@ only the geometry differs:
|
||||
|
||||
- **Radius.** 30 cm by default, independent of `settings.glow_radius_cm`; the
|
||||
marker's personal `glow_radius_cm` wins.
|
||||
- **Field.** A continuous band along every segment with round free ends: grey
|
||||
luminance bands of the shared `GLOW_FALLOFF`, one piece per stretch, blended
|
||||
with `lighten` inside one isolated group, so corners and the closing of a
|
||||
loop neither seam nor double the brightness. Intensity and the 500 ms fade
|
||||
- **Field.** One continuous stroked path with round free ends: 48 grey
|
||||
luminance bands of the shared `GLOW_FALLOFF` in one mask, so corners and the
|
||||
closing of a loop neither seam nor double the brightness. Intensity and the 500 ms fade
|
||||
are the shared `glowAlpha` / `GLOW_FADE_MS`.
|
||||
- **Visibility.** The strip is cut into consecutive pieces no longer than the
|
||||
radius; each piece is clipped to the visibility fans of its own emitters
|
||||
(the shared `visibilityPolygon` over the same barrier scene as pools; the
|
||||
fans are separate paths of one clipPath, no boolean pass per piece), and the
|
||||
whole field layer is clipped once to the floor. An unobstructed emitter uses
|
||||
- **Visibility.** Classify and sample the full polyline at radius/4 or finer,
|
||||
retaining every actual vertex and both ends; never thin a short final run
|
||||
or an acute corner. The continuous field is clipped to the union of the
|
||||
emitters' visibility fans (the shared `visibilityPolygon` over the same
|
||||
barrier scene as pools), then once to the floor. Groups of five fans are
|
||||
retained as compact positive-winding paths and rendered as one SVG clip
|
||||
child with explicit `clip-rule=nonzero` (several compound clip children
|
||||
caused Chromium raster holes despite correct geometric membership);
|
||||
discs and blocked fans have the same winding, so overlap adds visibility
|
||||
instead of cutting holes. An unobstructed emitter uses
|
||||
an exact SVG disc; a blocked fan keeps hard obstacle edges and exact circular
|
||||
arcs between them, so free ends cannot expose angular-sweep facets. Windows,
|
||||
arcs between them. Before the sweep, barriers are clipped to the emitter's
|
||||
radius: exact wall–circle intersections become angular events, not a chord
|
||||
cutting away visible floor between two coarse rays. Windows,
|
||||
columns,
|
||||
thick walls and Solid zero walls block; doors/gates pass by their actual
|
||||
opening; Dashed zero walls are transparent. Emitters on a thick face sit
|
||||
@@ -442,9 +448,12 @@ only the geometry differs:
|
||||
inherits their free-side normal. The visible stripe and its emitters
|
||||
therefore stay on one straight line through the opening. At a genuine turn,
|
||||
safely intersecting shifted sides use that bounded intersection as their
|
||||
single miter; unsafe acute angles retain the short connector. A stored
|
||||
four-corner loop consequently stays a four-corner rectangle without steps
|
||||
at openings or diagonal corner inserts (#787).
|
||||
single miter; a free side contributes its unshifted axis to the same join.
|
||||
Numeric endpoint tails are not gaps; redundant collinear subdivisions are
|
||||
removed only from the derived visible path before offsetting, never from
|
||||
the saved points. Unsafe acute angles retain the short connector. A stored
|
||||
four-corner loop stays four-cornered without steps or protruding hooks;
|
||||
a genuinely tilted side stays tilted (#787, #788).
|
||||
- **Core.** With effective Glow (space `glow_enabled` + room `glow`) the core
|
||||
stays white and the colour is the field; without Glow the core takes the
|
||||
source colour and there is no field. Off: white core, no field.
|
||||
@@ -461,5 +470,20 @@ only the geometry differs:
|
||||
- **Laziness.** The stripe/hit/2.5D code (`led-strip-runtime`) and the field
|
||||
(`led-strip-field`) are separate lazy chunks; the initial graph holds only
|
||||
the presence check and the loader (`led-strip-gate`). Caches are bounded per
|
||||
space (50 shapes, 50 visibilities, 2500 retained fans) and released on space
|
||||
change and on disconnect; a chunk that lands after disconnect applies nothing.
|
||||
space (50 shapes and 50 visibility entries) and released on space change
|
||||
and on disconnect; a chunk that lands after disconnect applies nothing.
|
||||
The `led-strips-v1` maximum-load witness bounds the compact representation
|
||||
to 2500 cached path batches and 4 Mi cached characters (at most 8 MiB UTF-16,
|
||||
excluding the joined Lit/DOM clip string), with unchanged timing and 64 MiB
|
||||
warm-cycle heap-growth budgets (not a total browser-memory bound).
|
||||
The actual fan count remains a separate honest
|
||||
diagnostic. The former 2500-fan acceptance bound depended on dropping
|
||||
required vertices/endpoints and was incompatible with the 50×50-point
|
||||
contract; compaction now reduces object/DOM overhead, not geometric detail.
|
||||
|
||||
`smoke_led_strip_field` compares rasterised production-field pixels with an
|
||||
independent distance/falloff oracle across three radii, both path directions
|
||||
and three raster densities: free ends, acute/reflected turns, decimal loops,
|
||||
self-crossings and an opaque wall. Unit tests pin joins, circle events and
|
||||
doorway emitter normals. The original household export is checked locally,
|
||||
not stored as a public fixture.
|
||||
|
||||
@@ -29,6 +29,7 @@ Everything computable from the tree and git; regenerate, never edit by hand
|
||||
|---|---|
|
||||
| Current local cycle | **Beta v1.79.0-beta.6 candidate** — two integrated S8 issues since beta.5. LED-strip Glow has smooth free end caps, while rectangular strips keep clean corners and remain straight across doors, gates and passages (#786, #787). `main` remains on stable v1.78.0. |
|
||||
| Branches | `main` carries stable releases only; pre-release tags point at `dev`. Work lands on `dev`, which is equal to or ahead of `main`, never behind. |
|
||||
| LED regression acceptance | #788 covers mixed face/free and fractional-coordinate joins, winding-safe field unions, retained endpoints/acute vertices and circle–wall transition events. The actual owner export is exercised locally; public fixtures are synthetic. Pixel oracles, not just SVG counts, protect the visible falloff. |
|
||||
| Warm remount | Delayed editor restoration preserves the original View camera, reserves pending chrome space, and yields synchronously to mode/space navigation (#762). Header/stage dimensions are published as one settled pair. Canonical: `docs/WARM-REMOUNT.md`. |
|
||||
| 2.5D View | Public since #649: the installation-wide General settings switch `settings.volumetric_view` (Display). Flat stays the default and byte-for-byte unchanged; editors and `houseplan-space-card` stay Flat. Canonical: `docs/ISOMETRIC.md`. |
|
||||
| Input support | Owner's rule since 2026-08-08: View and kiosk are fully supported and release-blocking on touch; the three editors are desktop-first, touch editing is best effort. Canonical: `docs/TOUCH-SUPPORT.md`. |
|
||||
|
||||
@@ -14,11 +14,11 @@ to prove that the Node witness actually kills it.
|
||||
| --- | ---: | --- |
|
||||
| Performance threshold | 4 | The witness measures real browser wall-time or frame work; a pure assertion cannot prove the budget. |
|
||||
| Browser harness integrity | 4 | The mutation breaks page-error, round-trip or page-registration observation in the browser harness itself. |
|
||||
| Paint, cascade and layer composition | 32 | The invariant depends on computed CSS, SVG paint, clipping, stacking or pixels produced by Chromium. |
|
||||
| Paint, cascade and layer composition | 36 | The invariant depends on computed CSS, SVG paint, clipping, stacking or pixels produced by Chromium. |
|
||||
| Pointer geometry and trusted interaction | 47 | The invariant depends on hit testing, pointer capture, touch/keyboard dispatch or live DOM geometry. |
|
||||
| Responsive DOM layout | 38 | The invariant depends on measured element boxes, responsive breakpoints, native/HA dialog shells or focusable target size. |
|
||||
| Custom-element and HA browser lifecycle | 101 | The invariant crosses Lit/custom-element lifecycle, browser storage/events, lazy loading or a complete HA-card state transition. |
|
||||
| **Total** | **226 / 200** | Above the guideline `mutation-gate --check` warns rather than fails (#699); each guard above it is held by its own reason in this inventory and its `because`. |
|
||||
| **Total** | **230 / 200** | Above the guideline `mutation-gate --check` warns rather than fails (#699); each guard above it is held by its own reason in this inventory and its `because`. |
|
||||
|
||||
## Measured effect
|
||||
|
||||
@@ -93,6 +93,10 @@ The invariant depends on computed CSS, SVG paint, clipping, stacking or pixels p
|
||||
- `iso-theme-dark-wall-rule-returns`
|
||||
- `led-badge-dropped`
|
||||
- `led-core-coloured-under-glow`
|
||||
- `led-field-endpoint-dropped`
|
||||
- `led-field-disc-cancels-fan`
|
||||
- `led-field-compound-clip-children`
|
||||
- `led-field-circle-events-missing`
|
||||
- `led-icon-not-suppressed`
|
||||
- `led-source-stays-round-at-anchor`
|
||||
- `led-static-live-ignored`
|
||||
|
||||
Reference in New Issue
Block a user