13 KiB
Umbauplan web-cad v2.0 — Plugin-first, WebGL, Voll-CAD
⚠️ STATUS: ARCHIVIERTE PLANREFERENZ — Die operative Umsetzung läuft über 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
- Core = Kernel only: Datenmodell (CADElement/Layer), SpatialIndex, ZoomPan, History, Yjs-Sync, CommandRegistry, PluginRegistry. Kein einziges konkretes Werkzeug im Kernel.
- Werkzeug = Plugin: Jedes Werkzeug implementiert
ToolExtensionV2mit eigenem Event-Zustand (onPointerDown/Move/Up/Key/Cancel), eigener Live-Vorschau über RenderAdapter-Overlay und Optionsleiste. - InteractionEngine wird Dispatcher: Sie besitzt nur noch Event-Routing, aktives Tool delegieren, Undo-Transaktionen kapseln. Der aktuelle 1157-Zeilen-switch fällt weg.
- 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). - 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).
- Datenmodell offen für Branchen:
element.typebleibt 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)ImportExportExtensionbehalten, umformatId,mime,export(doc),import(data)erweitern- Manifest:
categoryerweitert um'library'; neue FelderminAppVersion,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
seatingService.ts:rowId/blockIdvia UUID-Counter stattDate.now(); Block-Reihen erhalten eigenerowIdgeometry.ts findIntersection: Line–Circle, Circle–Circle, Line–Arc ergänzen (trim/extend/fillet funktionieren dann auf Kreisen/Bögen)- Offset-Tool: Richtungssinn aus zweitem Klick (Vorzeichen der Seitigkeit per Kreuzprodukt)
RenderEngine.drawBackground: Bild cachen (einmal laden), keinimg.onload → render()pro FramecountSeats: 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=webglwä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 mitattrValues[] - 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
- Interaktives Bestuhlungs-Werkzeug (im
event-toolsPlugin): Klick-Drag definiert Reihe/Block, Live-Vorschau via Overlay, Parameter (Anzahl, Abstand, Kurvenradius) in Optionsleiste - Arc-Rows: Reihen entlang Kreisbogen um Bühnenpunkt (Radius, Winkelspread, Versatz)
- Sitzplatzzählung robust: byRow/byBlock/byZone, Summen in StatusBar, Klick auf Zahl highlightet Reihe
- Vorlagenkatalog: Kino, Bankett-Rundtische, Stehtische, Podeste, Parlamentarisch, U-Form
- Sitzplatzliste export (CSV/XLSX: Reihe, Platz, Zone, Gast optional)
- Optional (Backend):
guests-Tabelle + Zuordnung seatId↔guest, CSV-Import — Vorbereitung Social-Tables-ähnlicher Funktion - 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
.wcadlibPaket-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
- 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)
- PDF-Export pro Layout in echtem Ausgabemaßstab (pdf-lib vorhanden)
- Plot-Stil: Linienstärken nach Farbe/Layer, monochrom-Option
- Drucken über Browser-Print (CSS @page) zusätzlich
Phase H — Branchenneutralität & Einfachheit · 1–2 Wochen
- 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. - Projekt-Templates: Halle, Open Air, Saal, Messehalle, Bürogrundriss, Garten/Gelände — Template aktiviert passende Bibliotheks-Ordner + Plugin-Set + Rastermaßstab (m/cm/ft)
- Rollen: Library-Admin (global bearbeiten) vs. Nutzer (lesen, eigene Ordner) — an bestehendes 4-Rollen-Auth andocken
- i18n-Vorbereitung: Strings zentral (de/en), UI-Texte aus Bundle
- 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
- PixiJS-Textqualität bei Dimensionen → früh Screenshot-Paritätstest, ggf. DOM-Overlay für Labels
- Plugin-Sandboxing (fremder Code im Browser) → v2 nur Admin-installierte, signierte Bundles; CSP; später Worker-Isolation
- DXF-Sonderfälle (SPLINE-Grad, HATCH-Grenzen) → Grenzen dokumentieren, Fehlertoleranz-Importer mit Report
- 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