task(C2int): integrate pixi renderer as overlay with lazy import
This commit is contained in:
@@ -18,6 +18,7 @@ import { CADDocument } from '../kernel/document/CADDocument';
|
||||
import { YjsDocument } from '../crdt/YjsDocument';
|
||||
import { setActiveDocument, getActiveDocument } from '../kernel/document/documentService';
|
||||
import { V2_TOOLS_ENABLED } from '../kernel/featureFlags';
|
||||
import { PixiRenderer } from '../render/pixi/PixiRenderer';
|
||||
import { pluginRegistry } from '../plugins';
|
||||
|
||||
const CanvasArea: React.FC<CanvasAreaProps> = ({
|
||||
@@ -34,6 +35,10 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
|
||||
const renderEngineRef = useRef<RenderEngine | null>(null);
|
||||
const interactionRef = useRef<InteractionEngine | null>(null);
|
||||
const dispatcherRef = useRef<InteractionDispatcher | null>(null);
|
||||
/** Task C2: PixiJS-Canvas-Ref für V2-Elemente-Overlay. */
|
||||
const pixiCanvasRef = useRef<HTMLCanvasElement>(null);
|
||||
/** Task C2: Aktiver PixiJS-Renderer (für Cleanup). */
|
||||
const pixiRendererRef = useRef<PixiRenderer | null>(null);
|
||||
/** Bereits an onElementCreated gemeldete V2-Element-IDs (verhindert Doppelmeldung bei jedem onChanged-Frame). */
|
||||
const announcedV2Ids = useRef<Set<string>>(new Set());
|
||||
const spatialIndexRef = useRef<SpatialIndex | null>(null);
|
||||
@@ -65,6 +70,60 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
|
||||
const v2Doc = new CADDocument(ydoc);
|
||||
// App-Level-Zugriffspunkt für HistoryPanel/Tastenkürzel (Task A4.11):
|
||||
setActiveDocument(v2Doc);
|
||||
|
||||
// ── Task C2: PixiJS-Renderer parallel schalten ──
|
||||
// DEFENSIV: Ein Ausfall von Pixi (z.B. WebGL im Headless-Browser)
|
||||
// darf NIEMALS den kompletten Editor-Mount brechen. Im Fehlerfall
|
||||
// läuft weiter ohne Overlay.
|
||||
let pixi: PixiRenderer | null = null;
|
||||
const pixiCanvas = pixiCanvasRef.current;
|
||||
if (pixiCanvas) {
|
||||
try {
|
||||
pixi = new PixiRenderer();
|
||||
pixiRendererRef.current = pixi;
|
||||
pixi.init(pixiCanvas);
|
||||
pixi.waitForReady().catch((err) => {
|
||||
logger.warn('Pixi init failed — V2-Overlay deaktiviert:', err);
|
||||
pixi = null;
|
||||
pixiRendererRef.current = null;
|
||||
});
|
||||
} catch (err) {
|
||||
logger.warn('Pixi init exception — V2-Overlay deaktiviert:', err);
|
||||
pixi = null;
|
||||
pixiRendererRef.current = null;
|
||||
}
|
||||
}
|
||||
/** Letztes bekanntes Elementobjekt je ID (Referenzdiff statt JSON). */
|
||||
const lastKnownEl = new Map<string, CADElement>();
|
||||
const syncPixi = (): void => {
|
||||
if (!pixi) return;
|
||||
void pixi.waitForReady().then(() => {
|
||||
const all = v2Doc.getAllElements();
|
||||
const visibleIds = new Set<string>();
|
||||
for (const el of all) {
|
||||
visibleIds.add(el.id);
|
||||
// Nur neu zeichnen wenn sich die OBJEKTREFERENZ geändert hat:
|
||||
if (lastKnownEl.get(el.id) !== el) {
|
||||
lastKnownEl.set(el.id, el);
|
||||
pixi!.drawElement(el, {
|
||||
id: 'layer-0', name: 'Standard', visible: true, locked: false,
|
||||
color: '#ffffff', lineType: 'solid', transparency: 0,
|
||||
sortOrder: 0, parentId: null,
|
||||
} as never, {
|
||||
color: '#ffffff', lineType: 'solid', transparency: 0, visible: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
// Gelöschte IDs aus dem Renderer entfernen:
|
||||
for (const knownId of lastKnownEl.keys()) {
|
||||
if (!visibleIds.has(knownId)) {
|
||||
lastKnownEl.delete(knownId);
|
||||
pixi!.removeElement(knownId);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Committete V2-Elemente fließen über den etablierten Kanal in UI/State:
|
||||
v2Doc.onChanged(() => {
|
||||
for (const el of v2Doc.getAllElements()) {
|
||||
@@ -73,6 +132,7 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
|
||||
onElementCreated(el);
|
||||
}
|
||||
}
|
||||
syncPixi(); // Task C2: V2-Elemente in den PixiJS-Overlay-Renderer spiegeln
|
||||
});
|
||||
|
||||
dispatcherRef.current = new InteractionDispatcher(canvas, {
|
||||
@@ -115,6 +175,8 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
|
||||
interaction.detach();
|
||||
dispatcherRef.current?.destroy();
|
||||
dispatcherRef.current = null;
|
||||
pixiRendererRef.current?.destroy(); // Task C2: WebGL-Kontext freigeben
|
||||
pixiRendererRef.current = null;
|
||||
setActiveDocument(null);
|
||||
zoomPanRef.current = null;
|
||||
renderEngineRef.current = null;
|
||||
@@ -413,6 +475,22 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
|
||||
<span style={{ color: 'var(--color-text-faint)' }}>{unit}</span>
|
||||
</div>
|
||||
|
||||
{/* Task C2-Integration: PixiJS-Overlay für V2-Elemente — liegt ÜBER dem
|
||||
Legacy-Canvas (z-index höher), rendert nur Elemente aus dem V2-Dokument.
|
||||
Pointer-Events gehen durch (pointerEvents:none), damit Drag/Drop weiter
|
||||
auf dem Legacy-Canvas funktioniert. */}
|
||||
{V2_TOOLS_ENABLED && (
|
||||
<canvas
|
||||
ref={pixiCanvasRef}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
pointerEvents: 'none',
|
||||
zIndex: 5,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="canvas-svg"
|
||||
|
||||
Reference in New Issue
Block a user