# Umbauplan web-cad v2.0 — Plugin-first, WebGL, Voll-CAD > ⚠️ **STATUS: ARCHIVIERTE PLANREFERENZ** — Die operative Umsetzung läuft über **[ROADMAP.md](./ROADMAP.md)** > (Tasks mit exakten Arbeitsschritten, Status, Fortschritts-Log). > Dieses Dokument bleibt als Begründung/Kontext stehen: Warum welche Entscheidungen getroffen wurden, > Marktvergleich, Risikoanalyse. Bei Abweichungen gilt immer ROADMAP.md. Stand: 2026-08-26 · Basis: Commit `126277a` (main) ## Zielbild Web-CAD im Umfang einer Standard-2D-CAD-Software mit Event-Fokus: - **Alle Werkzeuge sind Plugins** — auch Kern-Werkzeuge (built-in Plugins haben keinen Sonderstatus mehr) - **WebGL-Renderer** (PixiJS) für große Pläne (50.000+ Elemente bei 60fps) - **Branchenneutrale Basis**: Grundrisse, Gelände, Flächen — nicht nur Veranstaltungen - **Library als First-Class-System**, erweiterbar durch Plugin-Kataloge - **Zwei Bedienmodi**: „Einfach“ für Einsteiger, „Pro“ für CAD-Anwender --- ## Architektur-Grundsätze 1. **Core = Kernel only**: Datenmodell (CADElement/Layer), SpatialIndex, ZoomPan, History, Yjs-Sync, CommandRegistry, PluginRegistry. Kein einziges konkretes Werkzeug im Kernel. 2. **Werkzeug = Plugin**: Jedes Werkzeug implementiert `ToolExtensionV2` mit eigenem Event-Zustand (onPointerDown/Move/Up/Key/Cancel), eigener Live-Vorschau über RenderAdapter-Overlay und Optionsleiste. 3. **InteractionEngine wird Dispatcher**: Sie besitzt nur noch Event-Routing, aktives Tool delegieren, Undo-Transaktionen kapseln. Der aktuelle 1157-Zeilen-switch fällt weg. 4. **RenderAdapter als Schnittstelle**: Alles Rendern läuft gegen eine schmale API (`clear/draw*/overlay/hitTest`), Implementierung PixiJS. Canvas2D entfällt (keine produktiven Nutzer → kein Legacy-Pfad). 5. **Backend spiegelt Plugin-Lifecycle**: installierte Plugins, Versionen, Aktivierung pro Mandant/User in SQLite; Plugin-Bundles als ZIP mit Frontend-Code + optionalen Backend-Routen (sandboxed, manifest-signiert). 6. **Datenmodell offen für Branchen**: `element.type` bleibt string; unbekannte Typen werden vom registrierenden Plugin gerendert (bereits vorhanden, wird zur Pflicht). --- ## Phase A — Plugin-first Refactoring (Kernel) · ca. 2 Wochen ### A1 Plugin-API v2 (`frontend/src/plugins/types.ts`) - `ToolExtensionV2`: id, label, icon, ribbonTab, shortcut, cursor, optionsSchema (PropertyFields für Optionsleiste), `handlers: { onPointerDown/Move/Up/KeyDown/Cancel }`, `preview(adapter, state)`, `commit() -> Operation[]` (für Undo als eine Transaktion) - `PanelExtension`: eigene Sidebar-Panels (z.B. Bestuhlungsplaner, Gästeliste) - `LibraryProviderExtension`: liefert Kataloge (siehe Phase F) - `SnapProviderExtension`: zusätzliche Fangpunkte (z.B. Tangente eines Plugin-Elements) - `ImportExportExtension` behalten, um `formatId`, `mime`, `export(doc)`, `import(data)` erweitern - Manifest: `category` erweitert um `'library'`; neue Felder `minAppVersion`, `permissions[]` (canvas, network, storage) ### A2 InteractionEngine zum Dispatcher umbauen - Neuer Vertrag: `setTool(toolId)` holt Tool aus PluginRegistry statt internem Switch - Undo/Redo: jedes Tool-commit wird eine HistoryManager-Transaktion (heute inkonsistent) - CommandRegistry bleibt; Commands aus Plugins bereits vorhanden - RibbonBar rendert dynamisch aus Registry (`getToolExtensions()` gruppiert nach ribbonTab) — Tabs bleiben konfigurierbar ### A3 Kern-Tools als built-in Plugins migrieren | Plugin-Paket | Inhalt | |---|---| | `core-drawing` | line, polyline, rect, circle, arc, polygon, point, xline, ray, ellipse, spline | | `core-modify` | select, move, copy, rotate, scale, mirror, trim, extend, fillet, chamfer, offset, stretch, break, join, explode, align, array-rect, array-polar, array-path | | `core-annotate` | text, mtext, dimension-linear/-angular/-radial, leader, revcloud, hatch | | `core-measure` | measure, distance-info, area-info | | `event-tools` | chair, seating-row, seating-block, table, stage, templates (bestehend, erweitert) | Akzeptanz: `interaction/index.ts` < 300 LOC (nur Routing); alle 380 bestehenden Tests grün; Ribbon zeigt identische Werkzeuge wie zuvor. ### A4 Backend: Plugin-Registrierung - SQLite-Tabelle `plugins(id, version, enabled_default, installed_at)` + `plugin_settings(plugin_id, scope, scope_id, json)` - REST `/api/plugins` (list), `/api/plugins/:id/settings` (GET/PUT), Admin-Upload `/api/plugins/install` (ZIP) - Websocket-Event `pluginStateChanged` → Clients aktivieren/deaktivieren live --- ## Phase B — Bugfixes (sofort, unabhängig) · 2–3 Tage 1. `seatingService.ts`: `rowId`/`blockId` via UUID-Counter statt `Date.now()`; Block-Reihen erhalten eigene `rowId` 2. `geometry.ts findIntersection`: Line–Circle, Circle–Circle, Line–Arc ergänzen (trim/extend/fillet funktionieren dann auf Kreisen/Bögen) 3. Offset-Tool: Richtungssinn aus zweitem Klick (Vorzeichen der Seitigkeit per Kreuzprodukt) 4. `RenderEngine.drawBackground`: Bild cachen (einmal laden), kein `img.onload → render()` pro Frame 5. `countSeats`: byRow auch für Blöcke korrekt Jeder Fix mit Unit-Test. Diese Phase läuft parallel zu A und ändert Dateien, die B später ohnehin anfasst (Konflikt klein halten durch Reihenfolge: erst B, dann A-Migration je Tool). --- ## Phase C — WebGL-Renderer (PixiJS) · 3–5 Wochen ### C1 RenderAdapter-Schnittstelle (`frontend/src/render/types.ts`) ``` interface RenderAdapter { init(canvas), resize(w,h,dpr), setViewport(vp), destroy() beginFrame(), endFrame() drawGrid(cfg), drawBackground(img,cfg), drawRuler(cfg) drawElement(el, layerStyle, scale) drawPreview(el), drawSelection(el, handles), drawSnapPoints(pts) drawOverlay(fn) // Freihand-Overlays von Tools (Gummibänder, Arc-Row-Vorschau) } ``` ### C2 PixiJS-Implementierung - Layer-Konzept: Graphics pro CAD-Layer, statische Elemente in Container mit Cache-as-Texture, dynamisches (Selection/Snap/Preview) in Overlay-Layer - Text: PIXI.Text/BitmapText; Dimensionen als Graphics + Label - Chair/Table/Stage: Texture-Atlas (einmal generiert, tausendfach instanziert) — der große Performance-Hebel für Bestuhlung - Grid/Ruler als getrennte Ticker-Layer, DPR-korrekt - Hintergrundbild als Sprite (löst gleichzeitig Bug #4 endgültig) ### C3 Kompatibilität Plugin-Element-Renderer - `ElementTypeExtension.render(ctx)` erhält Adapter-Wrapper: zeichnet in Offscreen-Canvas → `Texture.from(canvas)` → Sprite. Bestehende Event-Elemente (curtain, spotlight, barrier) laufen unverändert weiter; später können Plugins nativen Pixi-Renderer liefern (`renderPixi?`). ### C4 Tests & Benchmarks - 29 RenderEngine-Tests auf Adapter-Mock umschreiben (ca. 1 Tag Aufwand) - PerformanceBenchmark neu: 10k / 25k / 50k Chairs, Zielschwelle 60fps (Playwright + trace) - Feature-Flag `renderer=webgl` während Migration, danach Flag entfernen Akzeptanz: visuelle Parität zu Canvas2D (Screenshot-Vergleichstests), 50k Chairs @60fps auf Referenz-Hardware, alle Tests grün. --- ## Phase D — CAD-Werkzeuge komplettieren (alles Plugins) · 3–4 Wochen ### D1 core-drawing Ergänzungen - Ellipse + Ellipsenbogen (Achsen-, Rotations-Eingabe) - Spline: Bézier (CV-Kontrolle) + Glättungs-Polyline-Interpolation; Speicherung als Kontrollpunkte - Punkt, Konstruktionslinien (XLine/Ray, eigene Layer-Klasse „construction“) - MTEXT: mehrzeilig, Inline-Formatierung (fett/kursiv/Größe), Autowrap-Box ### D2 core-modify Ergänzungen - Stretch (Fenster über Polygonecken, Endpunkte verschieben) - Break (Element am Punkt teilen), Join (kollineare Segmente/Polylines fusionieren) - Chamfer (wie Fillet, gerade Kante), Explode (Block→Einzelelemente, Polyline→Segmente) - Align (2-Punkt-Ausrichtung inkl. Skalierung optional) - Lengthen (DElta/Total/Dynamisch) - Polyline-Editor: Segment hinzufügen/löschen, Kurven glätten, Breite - Grip-Editing: Ankerpunkte (Endpunkte/Mitte/Centre) direkt ziehen — großer Bedienkomfort-Gewinn ### D3 Arrays - Rechteckig (Zeilen×Spalten×Abstände), Polar (Zentrum, Anzahl, Winkel, rotieren ja/nein), Pfad (entlang Polyline/Arc) — für Bestuhlung kritisch ### D4 Snaps erweitern (SnapEngine + SnapProviderExtension) - Tangente, Senkrecht, Parallel, Quadrant, Center, Knoten, From-Offset (Basispunkt+Versatz) ### D5 Block-Attribute - Datenmodell: Blockdefinition mit `attrDefs[]`, Instanz mit `attrValues[]` - Editor-UI (Attribut-Formular beim Einfügen), Anzeige im RenderAdapter - DXF-Interop: ATTDEF/ATTR lesen/schreiben (Phase F nutzt es) --- ## Phase E — Event-Domain ausbauen · 2 Wochen 1. Interaktives Bestuhlungs-Werkzeug (im `event-tools` Plugin): Klick-Drag definiert Reihe/Block, Live-Vorschau via Overlay, Parameter (Anzahl, Abstand, Kurvenradius) in Optionsleiste 2. **Arc-Rows**: Reihen entlang Kreisbogen um Bühnenpunkt (Radius, Winkelspread, Versatz) 3. Sitzplatzzählung robust: byRow/byBlock/byZone, Summen in StatusBar, Klick auf Zahl highlightet Reihe 4. Vorlagenkatalog: Kino, Bankett-Rundtische, Stehtische, Podeste, Parlamentarisch, U-Form 5. Sitzplatzliste export (CSV/XLSX: Reihe, Platz, Zone, Gast optional) 6. Optional (Backend): `guests`-Tabelle + Zuordnung seatId↔guest, CSV-Import — Vorbereitung Social-Tables-ähnlicher Funktion 7. Event-Elemente veredeln: Bühne (mit Höhen-Angabe), Vorhang, Scheinwerfer (Farbe/Winkel), Barrieren (Kettenstücke), Fluchtweg-Signaturen --- ## Phase F — Library-System & Import/Export · 2–3 Wochen ### F1 Library-Kern - Backend-Schema erweitern: `library_folders` (Baum, Mandant-scope), `library_blocks` (+ tags, thumbnail, attrDefs, source: builtin/user/plugin) - Suche (Name/Tags), Favoriten pro User, Drag-Drop ins Canvas, „Als Block speichern“ aus Auswahl - Thumbnail-Generierung client-seitig beim Speichern (kleines PNG dataURL) ### F2 Library-Plugins - `LibraryProviderExtension`: `id`, `label`, `listFolders()`, `listBlocks(folder)`, `getBlock(id)` - Built-in Provider: `builtin-catalog` (mitgelieferte Kataloge: event, architecture, landscape), `user-library`, `global-library` - Plugin-Katalog-Pakete liefern Provider + Blöcke (Beispiel: „messe-plugin“ mit Standwand-Katalog) ### F3 Import - DXF: Parser erweitern um ELLIPSE, SPLINE, MTEXT, POINT, HATCH (Basis), ATTDEF/ATTR; INSERT→Blockdefinition + Instanz; Layer-Mapping - SVG→Block (Vektor in Elemente konvertieren oder als referenzierter Render-Typ) - Bibliotheks-Pakete `.wcadlib` (ZIP: manifest.json + blocks.json + thumbnails) importieren - PNG/JPG als Hintergrund (vorhanden) + PDF-Unterlage beibehalten ### F4 Export - `.wcadlib` Paket-Export (eigene Bibliothek teilen) - DXF-Export mit BLOCKS/INSERTS (Austausch mit AutoCAD/LibreCAD) - Bestehende Formate behalten: SVG, PDF, JSON --- ## Phase G — Layouts & Plot (Standard-CAD-Niveau) · 2 Wochen 1. Paperspace/Layouts: mehrere Layouts pro Zeichnung, Viewports mit Maßstab 1:1…1:500, Rahmen/Titelblock als Block mit Attributen (Projekt, Datum, Maßstab, Bearbeiter) 2. PDF-Export pro Layout in echtem Ausgabemaßstab (pdf-lib vorhanden) 3. Plot-Stil: Linienstärken nach Farbe/Layer, monochrom-Option 4. Drucken über Browser-Print (CSS @page) zusätzlich --- ## Phase H — Branchenneutralität & Einfachheit · 1–2 Wochen 1. **Modus „Einfach/Pro“**: User-Setting; Simple-Mode blendet Ribbon nach `tool.tags:['basic']` (Auswahl, Stühle, Vorlagen, Text, Maß), versteckt CommandLine/Layer-Tiefe; Pro zeigt alles. Gleiche Engine, gleiche Daten. 2. **Projekt-Templates**: Halle, Open Air, Saal, Messehalle, Bürogrundriss, Garten/Gelände — Template aktiviert passende Bibliotheks-Ordner + Plugin-Set + Rastermaßstab (m/cm/ft) 3. **Rollen**: Library-Admin (global bearbeiten) vs. Nutzer (lesen, eigene Ordner) — an bestehendes 4-Rollen-Auth andocken 4. i18n-Vorbereitung: Strings zentral (de/en), UI-Texte aus Bundle 5. Gelände-Tauglichkeit: Polygon-Flächen mit Flächenberechnung (m²), Hang-/Höhen-Annotation als Text/Leader reicht v1; GIS-Anbindung bewusst out-of-scope --- ## Phase I — Qualität, CI, Release · 1 Woche - CI (Forgejo Actions): lint + tsc + vitest (FE 400+/BE 255+) + Playwright-Smoke + Performance-Gate (50k@60fps) - Test-Deckung Tools: jede ToolExtension braucht Workflow-Test (ziehen, snappen, committen, undo) - Docker/Coolify unverändert; Migrations-Scripte für SQLite-Schema (plugins, library, guests, layouts) - Docs: Plugin-Entwickler-Guide (API v2), Library-Paket-Spec, Changelog 2.0 --- ## Meilensteine & Timeline | Milestone | Inhalt | ca. Woche | |---|---|---| | M1 | Phase B Bugfixes + A Plugin-first Kernel, Ribbon dynamisch | 2 | | M2 | C WebGL live hinter Flag, Parität + Benchmarks grün | 6 | | M3 | D volle Werkzeugpalette (Ellipse/Spline/Array/Grip/Attribute) | 10 | | M4 | E Event-Domain + F Library/Import-Export fertig | 13 | | M5 | G Layouts/PDF + H Modi/Templates + I Release 2.0 | 16–17 | Einzelarbeit ~4 Monate. Parallelisierung (z.B. B+C ein Track, D+F zweiter Track) verkürzt auf ~3 Monate. ## Risiken 1. **PixiJS-Textqualität bei Dimensionen** → früh Screenshot-Paritätstest, ggf. DOM-Overlay für Labels 2. **Plugin-Sandboxing** (fremder Code im Browser) → v2 nur Admin-installierte, signierte Bundles; CSP; später Worker-Isolation 3. **DXF-Sonderfälle** (SPLINE-Grad, HATCH-Grenzen) → Grenzen dokumentieren, Fehlertoleranz-Importer mit Report 4. **Yjs + Layouts** → Layouts als Yjs-Map pro Projekt, Konfliktfreiheit gegeben ## Offene Entscheidungen - PixiJS vs. Three.js-2D-Mode → Empfehlung PixiJS (Szene-Graph, Texture-Atlasten, kleiner) - Fremd-Plugins sofort erlaubt? → Empfehlung nein (nur first-party bis M5) - Gästemodul (E6) in 2.0 oder 2.1? → Empfehlung 2.1