Files
web-cad/umbauplan-v2.md
T

230 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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