diff --git a/src/led-strip-runtime.ts b/src/led-strip-runtime.ts index 0075cbf1..4de28c22 100755 --- a/src/led-strip-runtime.ts +++ b/src/led-strip-runtime.ts @@ -22,6 +22,8 @@ import { } from './glow-scene'; import { NORM_W, iconUnit } from './space-geometry'; import { roomGlowOf, roomPoly } from './logic'; +import { ISO_ICON_SCALE, ISO_TILE, isoEdgeColor, isoTileShadow } from './iso-tiles'; +import { deviceThemeClass } from './device-face'; import type { VirtualLightSnapshot } from './virtual-light-state'; import { geometryAllRings, pointInOpaquePlanBody } from './physical-geometry'; import { @@ -131,8 +133,19 @@ export interface LedHandlers { label: (d: DevItem) => string; } +/** 2.5D View (ТЗ §7): the stripe raised like a tile, its edge and floor shadow. */ +export interface LedIsoStyle { + /** Raise of the stripe, plan units: ISO_TILE.lift × D (0.075 D). */ + lift: number; + /** Visible edge below the raised stripe: ISO_TILE.depth × D (0.1 D). */ + depth: number; + edge: string; + shadow: { dx: number; dy: number; sigma: number; opacity: number }; +} + export interface LedStripeInput { views: readonly LedStripView[]; + iso?: LedIsoStyle | null; /** Base device diameter D in plan units (icon_size of this card × iconUnit). */ d: number; faces: FaceContext | null; @@ -183,7 +196,12 @@ export function renderLedStripes(input: LedStripeInput): TemplateResult { const h = input.handlers; // Smaller ids last: an exact overlap of hit paths resolves to the stable id. const ordered = [...input.views].sort((a, b) => (a.strip.id < b.strip.id ? 1 : a.strip.id > b.strip.id ? -1 : 0)); - return svg` + const iso = input.iso; + return svg` + ${iso ? svg` + ` : nothing}