Files

230 lines
13 KiB
Markdown
Raw Permalink Normal View History

# 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) · 23 Tage
1. `seatingService.ts`: `rowId`/`blockId` via UUID-Counter statt `Date.now()`; Block-Reihen erhalten eigene `rowId`
2. `geometry.ts findIntersection`: LineCircle, CircleCircle, LineArc 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) · 35 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) · 34 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 · 23 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 · 12 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 | 1617 |
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