diff --git a/scripts/generate-relief-atlases.js b/scripts/generate-relief-atlases.js index d507fa9c..88bd322d 100644 --- a/scripts/generate-relief-atlases.js +++ b/scripts/generate-relief-atlases.js @@ -1,139 +1,28 @@ -#!/usr/bin/env node "use strict"; /** - * Generate pre-rasterised PNG sprite atlases for the three relief icon sets - * (simple, gray, colored) from the SVG definitions in src/index.html. - * + * Generate pre-rasterised PNG sprite atlases for the relief icon sets. * Output: public/images/relief/{simple,gray,colored}.png * * Each atlas is a grid of SPRITE_SIZE × SPRITE_SIZE tiles arranged - * left-to-right, top-to-bottom. Tile order matches the SET_SYMBOLS arrays - * in src/renderers/draw-relief-icons.ts — keep the two in sync. + * left-to-right, top-to-bottom. Tile order matches the RELIEF_SYMBOLS. * - * Rendering strategy: each symbol is placed as a standalone element - * positioned in a CSS grid inside a regular HTML page, then Playwright's - * native page.screenshot() captures the result. This avoids the headless- - * Chromium restriction that prevents SVG blob/data URLs from rendering when - * drawn to a element. - * - * Usage: - * node scripts/generate-relief-atlases.js + * Run: `node scripts/generate-relief-atlases.js` */ const {chromium} = require("playwright"); const path = require("path"); const fs = require("fs"); - -// --------------------------------------------------------------------------- -// Configuration — keep in sync with SET_SYMBOLS in draw-relief-icons.ts -// --------------------------------------------------------------------------- +const {RELIEF_SYMBOLS} = require("../src/config/relief-config.ts"); const SPRITE_SIZE = 512; // px per symbol tile -const SET_SYMBOLS = { - simple: [ - "relief-mount-1", - "relief-hill-1", - "relief-conifer-1", - "relief-deciduous-1", - "relief-acacia-1", - "relief-palm-1", - "relief-grass-1", - "relief-swamp-1", - "relief-dune-1" - ], - gray: [ - "relief-mount-2-bw", - "relief-mount-3-bw", - "relief-mount-4-bw", - "relief-mount-5-bw", - "relief-mount-6-bw", - "relief-mount-7-bw", - "relief-mountSnow-1-bw", - "relief-mountSnow-2-bw", - "relief-mountSnow-3-bw", - "relief-mountSnow-4-bw", - "relief-mountSnow-5-bw", - "relief-mountSnow-6-bw", - "relief-hill-2-bw", - "relief-hill-3-bw", - "relief-hill-4-bw", - "relief-hill-5-bw", - "relief-conifer-2-bw", - "relief-coniferSnow-1-bw", - "relief-swamp-2-bw", - "relief-swamp-3-bw", - "relief-cactus-1-bw", - "relief-cactus-2-bw", - "relief-cactus-3-bw", - "relief-deadTree-1-bw", - "relief-deadTree-2-bw", - "relief-vulcan-1-bw", - "relief-vulcan-2-bw", - "relief-vulcan-3-bw", - "relief-dune-2-bw", - "relief-grass-2-bw", - "relief-acacia-2-bw", - "relief-palm-2-bw", - "relief-deciduous-2-bw", - "relief-deciduous-3-bw" - ], - colored: [ - "relief-mount-2", - "relief-mount-3", - "relief-mount-4", - "relief-mount-5", - "relief-mount-6", - "relief-mount-7", - "relief-mountSnow-1", - "relief-mountSnow-2", - "relief-mountSnow-3", - "relief-mountSnow-4", - "relief-mountSnow-5", - "relief-mountSnow-6", - "relief-hill-2", - "relief-hill-3", - "relief-hill-4", - "relief-hill-5", - "relief-conifer-2", - "relief-coniferSnow-1", - "relief-swamp-2", - "relief-swamp-3", - "relief-cactus-1", - "relief-cactus-2", - "relief-cactus-3", - "relief-deadTree-1", - "relief-deadTree-2", - "relief-vulcan-1", - "relief-vulcan-2", - "relief-vulcan-3", - "relief-dune-2", - "relief-grass-2", - "relief-acacia-2", - "relief-palm-2", - "relief-deciduous-2", - "relief-deciduous-3" - ] -}; - -// --------------------------------------------------------------------------- -// Paths -// --------------------------------------------------------------------------- - const ROOT = path.resolve(__dirname, ".."); const INDEX_HTML = path.join(ROOT, "src", "index.html"); const OUTPUT_DIR = path.join(ROOT, "public", "images", "relief"); -// --------------------------------------------------------------------------- -// Extract every element from index.html -// Returns a map of symbolId → {viewBox, innerSvg} -// --------------------------------------------------------------------------- - function extractSymbols(html) { const symbols = {}; - // Match each ... block. - // elements never nest, so a lazy [\s\S]*? is safe here. const re = /]+)>([\s\S]*?)<\/symbol>/g; let m; while ((m = re.exec(html)) !== null) { @@ -164,24 +53,18 @@ console.log(`Extracted ${found} relief symbols from index.html`); fs.mkdirSync(OUTPUT_DIR, {recursive: true}); -// --------------------------------------------------------------------------- -// Main — render each atlas via Playwright's native screenshot -// --------------------------------------------------------------------------- - (async () => { const browser = await chromium.launch(); const page = await browser.newPage(); - for (const [set, ids] of Object.entries(SET_SYMBOLS)) { + for (const [set, ids] of Object.entries(RELIEF_SYMBOLS)) { const n = ids.length; const cols = Math.ceil(Math.sqrt(n)); const rows = Math.ceil(n / cols); const W = cols * SPRITE_SIZE; const H = rows * SPRITE_SIZE; - // Build one SVG per symbol, absolutely positioned in a grid. - // Using standalone elements (not ) means the symbols are - // self-contained and render correctly regardless of CSP restrictions. + // Build one SVG per symbol, absolutely positioned in a grid const svgTiles = ids .map((symbolId, idx) => { const sym = allSymbols[symbolId]; diff --git a/src/renderers/draw-relief-icons.ts b/src/renderers/draw-relief-icons.ts index 33768d0a..3f82b79b 100644 --- a/src/renderers/draw-relief-icons.ts +++ b/src/renderers/draw-relief-icons.ts @@ -233,8 +233,6 @@ function renderFrame(): void { } function drawWebGl(icons: ReliefIcon[], parentEl: HTMLElement): void { - parentEl.innerHTML = ""; - parentEl.dataset.mode = "webGL"; const set = parentEl.getAttribute("set") || "simple"; if (ensureRenderer()) { @@ -248,12 +246,12 @@ function drawWebGl(icons: ReliefIcon[], parentEl: HTMLElement): void { } function drawSvg(icons: ReliefIcon[], parentEl: HTMLElement): void { - const html = icons.map( - (r) => - ``, - ); - parentEl.innerHTML = html.join(""); - parentEl.dataset.mode = "svg"; + parentEl.innerHTML = icons + .map( + (r) => + ``, + ) + .join(""); } window.drawRelief = ( @@ -262,6 +260,9 @@ window.drawRelief = ( ) => { if (!parentEl) throw new Error("Relief: parent element not found"); + parentEl.innerHTML = ""; + parentEl.dataset.mode = "webGL"; + const icons = pack.relief?.length ? pack.relief : generateRelief(); if (!icons.length) return;