Buildings (modern/fantasy, multi-floor, footprint shapes), caves, outdoor biomes, and town/village + city-block settlements. Auto-places Foundry walls, doors, windows, lighting; furniture as locked tiles; live preview. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
66 lines
3.1 KiB
JavaScript
66 lines
3.1 KiB
JavaScript
/**
|
|
* Build an HTML harness that renders one generated SVG two ways:
|
|
* left = inline in the DOM (what the preview does — lenient HTML parser)
|
|
* right = rasterised to a <canvas> via Image (what scene.mjs does)
|
|
* Used with Playwright to reproduce the "missing content in scene" bug.
|
|
*/
|
|
import { writeFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { dirname, join } from "node:path";
|
|
|
|
import { Rng } from "../module/lib/rng.mjs";
|
|
import { generateBuilding } from "../module/lib/building.mjs";
|
|
import { buildWalls } from "../module/lib/walls.mjs";
|
|
import { renderSVG } from "../module/lib/render-vector.mjs";
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
|
|
const layout = generateBuilding({ cols: 26, rows: 18, targetRooms: 11, subtype: "modern", seed: "mire-680", shape: "rectangle" });
|
|
const walls = buildWalls(layout, { rng: new Rng("mire-680::walls::0") });
|
|
const svg = renderSVG({ layout, walls, gridSize: 100, subtype: "modern", seed: "mire-680::0" });
|
|
const W = layout.cols * 100, H = layout.rows * 100;
|
|
|
|
const html = `<!doctype html><html><head><meta charset="utf-8"><style>
|
|
body{margin:0;background:#444;font-family:sans-serif;color:#fff}
|
|
.row{display:flex;gap:8px;padding:8px}
|
|
.cell{flex:1}.cell h3{margin:4px}
|
|
svg,canvas{width:100%;height:auto;border:1px solid #000;background:#888}
|
|
</style></head><body>
|
|
<div class="row">
|
|
<div class="cell"><h3>A: inline SVG (preview)</h3><div id="inline">${svg}</div></div>
|
|
<div class="cell"><h3 id="status">B: SVG→canvas</h3><canvas id="cv" width="${W}" height="${H}"></canvas></div>
|
|
<div class="cell"><h3 id="status2">C: →PNG blob→reload (final scene bytes)</h3><canvas id="cv2" width="${W}" height="${H}"></canvas></div>
|
|
</div>
|
|
<script>
|
|
const svgText = ${JSON.stringify(svg)};
|
|
const W=${W}, H=${H};
|
|
const blob = new Blob([svgText], { type: "image/svg+xml;charset=utf-8" });
|
|
const url = URL.createObjectURL(blob);
|
|
const img = new Image(); img.width=W; img.height=H;
|
|
img.onload = async () => {
|
|
try { if (img.decode) await img.decode(); } catch(e){}
|
|
const cv = document.getElementById("cv");
|
|
cv.getContext("2d").drawImage(img, 0, 0, W, H);
|
|
document.getElementById("status").textContent = "B: SVG→canvas — OK";
|
|
// C: exactly what scene.mjs uploads — toBlob PNG, then reload it
|
|
cv.toBlob((png) => {
|
|
if (!png) { document.getElementById("status2").textContent = "C: toBlob NULL"; window.__done = true; return; }
|
|
const purl = URL.createObjectURL(png);
|
|
const img2 = new Image();
|
|
img2.onload = () => {
|
|
document.getElementById("cv2").getContext("2d").drawImage(img2, 0, 0, W, H);
|
|
document.getElementById("status2").textContent = "C: PNG " + Math.round(png.size/1024) + "KB — OK";
|
|
window.__done = true;
|
|
};
|
|
img2.onerror = () => { document.getElementById("status2").textContent = "C: PNG RELOAD ERROR"; window.__done = true; };
|
|
img2.src = purl;
|
|
}, "image/png");
|
|
};
|
|
img.onerror = (e) => { document.getElementById("status").textContent = "B: IMAGE ERROR"; window.__done = true; };
|
|
img.src = url;
|
|
</script>
|
|
</body></html>`;
|
|
|
|
writeFileSync(join(here, "raster-test.html"), html);
|
|
console.log("wrote", join(here, "raster-test.html"), "size", svg.length);
|