3d2d4d6321
Neuer GPU-Renderer fuer den Grundriss (src/plan/glPlan/): Earcut-Tessellierung (konkav-faehig), gehrte Linienzuege (Miter), echte Papier-mm-Strichbreiten im Massstab (repliziert den SVG-printStrokeVb-Pfad), Hybrid mit scharfem SVG-Text- Overlay. GPU ist der Standardpfad; der SVG-Renderer bleibt automatischer Fallback, falls WebGL2/Shader nicht verfuegbar sind. Imperativer Pan (rAF + CSS-transform) fuer fluessige Interaktion ohne React-Re-Render je Frame. Enthaelt zudem den bisher nicht committeten Arbeitsstand des Browser-BIM (Oeffnungen, Treppen, Raeume, Decken, DXF-Export, Materialbibliothek, Kontext- Import, Tauri-Compute-Boundary-PoC).
124 lines
4.8 KiB
JavaScript
124 lines
4.8 KiB
JavaScript
// Probe (Welle A — 3D-Materialien): weist einem Wand-Bauteil ein Bibliotheks-
|
||
// Material (Backstein) zu, schaltet 3D auf „Texturiert" und beweist die
|
||
// texturierte Wand mit Normal-Map-Tiefe. Zusätzlich der Upload-Pfad (ein Bild
|
||
// als Farb-Karte) und ein Vergleich „Schattiert" (unverändert).
|
||
//
|
||
// Aufruf: PROBE_URL=http://localhost:5174/ node scripts/probe-materials.mjs
|
||
import puppeteer from "puppeteer";
|
||
import { fileURLToPath } from "node:url";
|
||
import { dirname, resolve } from "node:path";
|
||
|
||
const URL = process.env.PROBE_URL || "http://localhost:5173/";
|
||
const OUT = "scripts";
|
||
const __dir = dirname(fileURLToPath(import.meta.url));
|
||
|
||
const browser = await puppeteer.launch({
|
||
headless: "new",
|
||
args: ["--no-sandbox", "--use-gl=swiftshader", "--enable-unsafe-swiftshader"],
|
||
});
|
||
const page = await browser.newPage();
|
||
await page.setViewport({ width: 1360, height: 900, deviceScaleFactor: 2 });
|
||
|
||
const logs = [];
|
||
page.on("console", (m) => logs.push(`[${m.type()}] ${m.text()}`));
|
||
page.on("pageerror", (e) => logs.push(`[PAGEERROR] ${e.message}`));
|
||
|
||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||
const shot = (n) => page.screenshot({ path: `${OUT}/${n}` });
|
||
|
||
async function clickByText(selector, text) {
|
||
const handle = await page.evaluateHandle(
|
||
(sel, t) =>
|
||
[...document.querySelectorAll(sel)].find((el) => el.textContent.includes(t)),
|
||
selector,
|
||
text,
|
||
);
|
||
const el = handle.asElement();
|
||
if (!el) throw new Error(`nicht gefunden: ${selector} ~ "${text}"`);
|
||
await el.click();
|
||
}
|
||
|
||
await page.goto(URL, { waitUntil: "domcontentloaded", timeout: 20000 });
|
||
await page.waitForSelector(".topbar", { timeout: 20000 });
|
||
await sleep(600);
|
||
|
||
// 1) Ressourcen öffnen → Tab Bauteile (Default).
|
||
await clickByText("button.res-trigger", "Ressourcen");
|
||
await sleep(400);
|
||
await page.waitForSelector(".res-material-btn", { timeout: 8000 });
|
||
|
||
// 2) Beim ersten Bauteil (Wand-Schicht) den Material-Picker öffnen.
|
||
const matBtns = await page.$$(".res-material-btn");
|
||
console.log("Material-Buttons:", matBtns.length);
|
||
// Ein Bauteil wählen, das in Wänden verwendet wird — typischerweise das erste.
|
||
await matBtns[0].click();
|
||
await page.waitForSelector(".mat-dialog", { timeout: 8000 });
|
||
await shot("probe-materials-1-picker.png");
|
||
|
||
// 3) Bibliotheks-Material „Backstein" (Bricks104) zuweisen.
|
||
await clickByText(".mat-tile", "Backstein");
|
||
await sleep(400);
|
||
await shot("probe-materials-2-assigned.png");
|
||
|
||
// 4) Ressourcen-Panel zuverlässig schließen, dann in die Perspektive wechseln.
|
||
async function closeResources() {
|
||
// Schwebendes ResourceManager-Fenster über den ×-Knopf der Schublade schließen
|
||
// (der overlay-Backdrop liegt über der Topbar; res-trigger ist verdeckt).
|
||
const closeBtn = await page.$(".res-drawer .res-close");
|
||
if (closeBtn) {
|
||
await closeBtn.click();
|
||
await page.waitForSelector(".res-drawer", { hidden: true, timeout: 5000 });
|
||
await sleep(200);
|
||
}
|
||
}
|
||
await closeResources();
|
||
// Perspektive-Ansicht aktivieren (Icon-Grid: aria-label "Perspektive").
|
||
const persp = await page.$('button[aria-label="Perspektive"]');
|
||
if (persp) await persp.click();
|
||
await sleep(1200);
|
||
|
||
// Darstellung-Dropdown auf „Texturiert".
|
||
async function setStyle(label) {
|
||
// Custom-Dropdown (kein natives select): per title öffnen, Option per Text.
|
||
const trigger = await page.$('button.tb-dd-trigger[title*="Darstellungsart der"]');
|
||
if (!trigger) throw new Error("Darstellung-Dropdown nicht gefunden");
|
||
await trigger.click();
|
||
await page.waitForSelector("button.tb-dd-item", { timeout: 4000 });
|
||
await sleep(150);
|
||
await clickByText("button.tb-dd-item", label);
|
||
await sleep(1300);
|
||
}
|
||
await setStyle("Schattiert");
|
||
await shot("probe-materials-3-shaded.png");
|
||
await setStyle("Texturiert");
|
||
await sleep(1800); // Texturen lazy laden lassen
|
||
await shot("probe-materials-4-textured.png");
|
||
|
||
// 5) Upload-Pfad: ein Bild als Farb-Karte hochladen + zuweisen.
|
||
// Wieder Ressourcen öffnen, Picker öffnen, Datei wählen, zuweisen.
|
||
await clickByText("button.res-trigger", "Ressourcen");
|
||
await sleep(400);
|
||
const matBtns2 = await page.$$(".res-material-btn");
|
||
// Ein anderes Bauteil (zweite Schicht) nehmen, falls vorhanden, sonst dasselbe.
|
||
await (matBtns2[1] ?? matBtns2[0]).click();
|
||
await page.waitForSelector(".mat-dialog", { timeout: 8000 });
|
||
// Verstecktes File-Input der Farb-Zeile bespielen.
|
||
const fileInput = await page.$('.mat-upload-grid input[type="file"]');
|
||
const imgPath = resolve(__dir, "../public/assets/materials/WoodFloor051/color.jpg");
|
||
await fileInput.uploadFile(imgPath);
|
||
await sleep(500);
|
||
await shot("probe-materials-5-upload.png");
|
||
await clickByText(".mat-actions .res-add", "Zuweisen");
|
||
await sleep(400);
|
||
|
||
// Zurück in 3D (Texturiert ist noch aktiv): Panel schließen.
|
||
await closeResources();
|
||
await sleep(900);
|
||
await shot("probe-materials-6-upload-3d.png");
|
||
|
||
console.log("--- console ---");
|
||
for (const l of logs.slice(-30)) console.log(l);
|
||
|
||
await browser.close();
|
||
console.log("done");
|