diff --git a/src/App.tsx b/src/App.tsx index 282cd19..f70077c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2534,15 +2534,18 @@ export default function App() { // Persistiert in localStorage, damit die Wahl einen Neustart ohne URL-Param // übersteht (z.B. die Electron-App startet immer auf der Basis-URL). const RENDERER_STORAGE_KEY = "cad.rendererMode"; + const webGpuAvailable = typeof navigator !== "undefined" && "gpu" in navigator; const rendererMode: RendererMode = (() => { const fromUrl = new URLSearchParams(window.location.search).get("engine"); if (fromUrl === "wasm") return "wasm"; if (fromUrl === "webgl2") return "webgl2"; - return window.localStorage.getItem(RENDERER_STORAGE_KEY) === "wasm" - ? "wasm" - : "webgl2"; + const fromStorage = window.localStorage.getItem(RENDERER_STORAGE_KEY); + if (fromStorage === "webgl2") return "webgl2"; + if (fromStorage === "wasm") return "wasm"; + // Keine explizite Wahl (weder URL noch localStorage) — Nordstern (WASM) + // ist Standard, sofern WebGPU verfügbar ist; sonst WebGL2 als Fallback. + return webGpuAvailable ? "wasm" : "webgl2"; })(); - const webGpuAvailable = typeof navigator !== "undefined" && "gpu" in navigator; const setRendererMode = (mode: RendererMode) => { window.localStorage.setItem(RENDERER_STORAGE_KEY, mode); const url = new URL(window.location.href); @@ -3343,9 +3346,6 @@ export default function App() { referenceLinesEnabled={planActive} activeFloor={activeLevel.name} activeLayer={activeLayerName} - rendererMode={rendererMode} - webGpuAvailable={webGpuAvailable} - onRendererModeChange={setRendererMode} lineMode={lineMode} onLineModeChange={setLineMode} lineModeEnabled={planActive} @@ -3411,6 +3411,9 @@ export default function App() { onSnapColorChange={setSnapColor} project={project} setProject={setProject} + rendererMode={rendererMode} + webGpuAvailable={webGpuAvailable} + onRendererModeChange={setRendererMode} onClose={() => setSettingsOpen(false)} /> )} diff --git a/src/styles.css b/src/styles.css index ccc3dcb..18010d7 100644 --- a/src/styles.css +++ b/src/styles.css @@ -816,12 +816,14 @@ body { background: var(--border); } -/* Renderer-Umschalter (WebGL2 / Engine) in der Statusleiste — kleine - Segmentpille, an die 22px-Leiste angepasst (siehe .tb-seg für das größere - Vorbild in der Oberleiste). */ +/* Renderer-Umschalter (WebGL2 / Nordstern) — kleine Segmentpille; ursprünglich + in der Statusleiste (22px-Leiste), jetzt im Einstellungs-Fenster. In einer + flex-column (.imp-section) würde sie sonst auf volle Breite gestreckt + werden (Standard-`align-items: stretch`) — bleibt daher inhaltsbreit. */ .sb-renderer-toggle { display: inline-flex; align-items: stretch; + align-self: flex-start; height: 16px; border: 1px solid var(--border); border-radius: 999px; diff --git a/src/ui/SettingsDialog.tsx b/src/ui/SettingsDialog.tsx index d9ff785..fdc92cf 100644 --- a/src/ui/SettingsDialog.tsx +++ b/src/ui/SettingsDialog.tsx @@ -14,6 +14,7 @@ import { t } from "../i18n"; import { ACCENT_SWATCHES } from "../theme/accents"; import type { Project } from "../model/types"; import { ColorHexField } from "./ColorHexField"; +import type { RendererMode } from "./StatusBar"; export interface SettingsDialogProps { marqueeColor: string; @@ -22,6 +23,15 @@ export interface SettingsDialogProps { onSnapColorChange: (hex: string) => void; project: Project; setProject: (next: Project | ((p: Project) => Project)) => void; + /** Aktuell gewählter Plan-Renderer (aus dem `?engine`-URL-Param abgeleitet). */ + rendererMode: RendererMode; + /** Ist `navigator.gpu` vorhanden? Steuert, ob „Nordstern" wählbar ist. */ + webGpuAvailable: boolean; + /** + * Renderer wechseln (setzt/entfernt den `engine`-URL-Param und lädt neu — kein + * Live-Remount der Renderer-Hooks). + */ + onRendererModeChange: (mode: RendererMode) => void; onClose: () => void; } @@ -32,6 +42,9 @@ export function SettingsDialog({ onSnapColorChange, project, setProject, + rendererMode, + webGpuAvailable, + onRendererModeChange, onClose, }: SettingsDialogProps) { useEffect(() => { @@ -85,6 +98,33 @@ export function SettingsDialog({