/** * Furniture piece registry + room-type mapping. * * Each piece declares a footprint (in grid cells) and a draw() that renders the * art to FILL a box of (wpx × hpx), centred, on a transparent background. The * same registry feeds (a) the live preview vector, (b) the sprite PNGs used for * locked Tile placement in the scene. System-agnostic, no external art. */ export const PAL = { modern: { wood: "#9a8f80", woodLine: "#5d5448", metal: "#9aa3ad", metalLine: "#5b636c", fabric: "#7d8ba0", line: "#3a3f45", soft: "#c4ccd4", seat: "#8b95a3" }, fantasy: { wood: "#9c7b50", woodLine: "#4f3a20", metal: "#8a8d92", metalLine: "#4a4d52", fabric: "#8a6b52", line: "#3a2614", soft: "#c8b48f", seat: "#7a5532" } }; const r2 = (n) => +n.toFixed(1); /** Map a room label to furniture kinds (in placement priority order). */ export function piecesFor(label) { const l = label.toLowerCase(); if (/bed|chamber/.test(l)) return ["bed", "chest"]; if (/exec|study/.test(l)) return ["desk", "shelf", "chair"]; if (/office/.test(l)) return ["desk", "chair", "shelf"]; if (/meeting|common|dining|ballroom/.test(l)) return ["bigtable"]; if (/kitchen/.test(l)) return ["counter", "table"]; if (/server/.test(l)) return ["racks", "racks"]; if (/restroom|privy|bath/.test(l)) return ["toilet", "sink"]; if (/storage|store/.test(l)) return ["crates", "shelf", "crates"]; if (/strong|vault|cellar/.test(l)) return ["chest", "chest"]; if (/reception|lobby|entry|foyer|hall/.test(l)) return ["counter"]; if (/guard|barracks/.test(l)) return ["bunk", "table"]; if (/break/.test(l)) return ["table", "counter"]; return ["table"]; } /** * Piece registry. footprint = [wCells, hCells] in the piece's native (un-rotated) * orientation. `wall` true → prefers sitting against a wall. `collide` false → * decorative, never blocks (and may overlap). */ export const PIECES = { bed: { footprint: [1, 2], wall: true, draw: drawBed }, bunk: { footprint: [1, 2], wall: true, draw: drawBed }, chest: { footprint: [1, 1], wall: true, draw: drawChest }, desk: { footprint: [2, 1], wall: true, draw: drawDesk }, chair: { footprint: [1, 1], wall: false, draw: drawChair }, table: { footprint: [1, 1], wall: false, draw: drawTable }, bigtable: { footprint: [3, 2], wall: false, draw: drawBigTable }, counter: { footprint: [2, 1], wall: true, draw: drawCounter }, racks: { footprint: [1, 1], wall: true, draw: drawRacks }, toilet: { footprint: [1, 1], wall: true, draw: drawToilet }, sink: { footprint: [1, 1], wall: true, draw: drawSink }, crates: { footprint: [1, 1], wall: true, draw: drawCrates }, shelf: { footprint: [1, 1], wall: true, draw: drawShelf } }; /** Full standalone transparent SVG for one piece — used to make sprite PNGs. */ export function pieceSpriteSVG(kind, subtype, wpx, hpx) { const def = PIECES[kind]; const pal = PAL[subtype] ?? PAL.modern; const inner = def ? def.draw(wpx, hpx, pal) : ""; return `${inner}`; } /** Inner SVG for a piece (no wrapper) — used by the preview renderer. */ export function pieceInnerSVG(kind, subtype, wpx, hpx) { const def = PIECES[kind]; const pal = PAL[subtype] ?? PAL.modern; return def ? def.draw(wpx, hpx, pal) : ""; } // --- piece art (drawn to fill a wpx×hpx box, small inset, transparent bg) ----- function box(w, h, inset) { const m = Math.min(w, h) * inset; return { x: r2(m), y: r2(m), w: r2(w - 2 * m), h: r2(h - 2 * m), m: r2(m) }; } function drawBed(w, h, pal) { const b = box(w, h, 0.08); const pillow = r2(b.h * 0.26); return `` + `` + ``; } function drawChest(w, h, pal) { const b = box(w, h, 0.18); return `` + ``; } function drawDesk(w, h, pal) { const b = box(w, h, 0.1); return `` + ``; } function drawChair(w, h, pal) { const b = box(w, h, 0.26); return ``; } function drawTable(w, h, pal) { const b = box(w, h, 0.16); return ``; } function drawBigTable(w, h, pal) { const b = box(w, h, 0.2); let s = ``; // chairs around const cr = r2(Math.min(w, h) * 0.07); for (let i = 0; i < 3; i += 1) { const cx = r2(b.x + b.w * (0.2 + i * 0.3)); s += ``; s += ``; } s += ``; return s + ``; } function drawCounter(w, h, pal) { const b = box(w, h, 0.12); const top = r2(b.h * 0.5); return ``; } function drawRacks(w, h, pal) { let s = ``; const b = box(w, h, 0.12); for (let i = 0; i < 3; i += 1) { const x = r2(b.x + (b.w / 3) * i + b.w * 0.04); s += ``; } return s + ``; } function drawToilet(w, h, pal) { const cx = r2(w * 0.5); return `` + ``; } function drawSink(w, h, pal) { const b = box(w, h, 0.24); return ``; } function drawCrates(w, h, pal) { let s = ``; const sz = r2(Math.min(w, h) * 0.42); for (const [ox, oy] of [[0.06, 0.1], [0.5, 0.16], [0.28, 0.52]]) { s += ``; } return s + ``; } function drawShelf(w, h, pal) { const x = r2(w * 0.08), y = r2(h * 0.1), bw = r2(w * 0.84), bh = r2(h * 0.34); return `` + ``; }