DXF-Import: TEXT/MTEXT -> editierbarer Plan-Text (Drawing2D text-Primitiv, SVG-Render)
This commit is contained in:
+32
-1
@@ -1640,7 +1640,15 @@ export const PlanView = forwardRef<PlanViewHandle, PlanViewProps>(
|
||||
// Raum-Stempel selbst (glyphon) — das SVG darf ihn NICHT zusätzlich
|
||||
// zeichnen (sonst doppelter Text), also entfällt dort auch das Textoverlay.
|
||||
// Sonst (reines SVG): alles außer den gebündelten 2D-Zeichenlinien.
|
||||
(useGpuRenderer ? wantWasm || p.kind !== "text" : p.kind === "line" && p.drawingId) ? null : (
|
||||
// `drawingText` (importierter Einzeltext) rendert IMMER im SVG — der GL-
|
||||
// wie der WASM-Renderer zeichnet ihn nicht. Der Raum-Stempel (`text`)
|
||||
// bleibt: unter WASM rastert ihn render2d selbst (sonst doppelt).
|
||||
(useGpuRenderer
|
||||
? wantWasm
|
||||
? p.kind !== "drawingText"
|
||||
: p.kind !== "text" && p.kind !== "drawingText"
|
||||
: p.kind === "line" && p.drawingId)
|
||||
? null : (
|
||||
<PrimitiveShape
|
||||
key={i}
|
||||
p={p}
|
||||
@@ -3065,5 +3073,28 @@ function renderPrimitive(
|
||||
</text>
|
||||
);
|
||||
}
|
||||
case "drawingText": {
|
||||
// Modellverankerter Einzeltext (DXF-Import): Höhe in Metern → viewBox-
|
||||
// Einheiten (skaliert mit dem Zoom), Baseline am Ankerpunkt (links).
|
||||
const c = toScreen(p.at);
|
||||
const fontSize = p.heightM * PX_PER_M;
|
||||
// Modell-Winkel CCW; Screen-Y ist gespiegelt und SVG-rotate CW-positiv → -deg.
|
||||
const deg = -(p.angle * 180) / Math.PI;
|
||||
return (
|
||||
<text
|
||||
x={c.x}
|
||||
y={c.y}
|
||||
fontSize={fontSize}
|
||||
fontFamily="var(--font-ui, sans-serif)"
|
||||
fill={p.color}
|
||||
opacity={p.greyed ? 0.45 : undefined}
|
||||
textAnchor="start"
|
||||
transform={deg ? `rotate(${deg} ${c.x} ${c.y})` : undefined}
|
||||
style={{ pointerEvents: "none", userSelect: "none" }}
|
||||
>
|
||||
{p.text}
|
||||
</text>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +294,23 @@ export type Primitive =
|
||||
/** ID des Raums (Room), zu dem dieser Stempel gehört (Auswahl). */
|
||||
roomId?: string;
|
||||
greyed?: boolean;
|
||||
}
|
||||
| {
|
||||
// Schlichter, modellverankerter Einzeltext (aus Drawing2D `{shape:"text"}`,
|
||||
// z. B. DXF-Import). Anders als `kind:"text"` (Raum-Stempel, RichText) trägt
|
||||
// er nur einen String mit Höhe in Metern + Drehung — rein SVG-gerendert.
|
||||
kind: "drawingText";
|
||||
/** Ankerpunkt im Modell (Meter). */
|
||||
at: Vec2;
|
||||
text: string;
|
||||
/** Schrifthöhe in Modell-Metern. */
|
||||
heightM: number;
|
||||
/** Drehung in RADIANT (CCW im Modell). */
|
||||
angle: number;
|
||||
color: string;
|
||||
/** ID des 2D-Zeichenelements (für Links-Klick-Auswahl). */
|
||||
drawingId?: string;
|
||||
greyed?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1013,7 +1030,19 @@ function addDrawing2D(
|
||||
for (let i = 0; i < N; i++) seg(pts[i], pts[(i + 1) % N]);
|
||||
break;
|
||||
}
|
||||
// arc/text: Primitive-Erweiterungen folgen später.
|
||||
case "text":
|
||||
out.push({
|
||||
kind: "drawingText",
|
||||
at: g.at,
|
||||
text: g.text,
|
||||
heightM: g.height,
|
||||
angle: g.angle,
|
||||
color,
|
||||
greyed,
|
||||
drawingId: d.id,
|
||||
});
|
||||
break;
|
||||
// arc: Primitive-Erweiterung folgt später.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -486,7 +486,7 @@ export function planToRenderScene(plan: Plan, paperScaleN: number = STAMP_DEFAUL
|
||||
widthMm: p.weightMm,
|
||||
dash: p.dash ?? null,
|
||||
});
|
||||
} else {
|
||||
} else if (p.kind === "text") {
|
||||
// "text": zeilenweise flachen — die ECHTEN Glyphen rastert der Rust-
|
||||
// Renderer über einen GPU-Glyphen-Atlas (glyphon, dieselbe Font-Familie
|
||||
// wie im Browser). Layout identisch zum SVG-Pfad in PlanView (case
|
||||
|
||||
Reference in New Issue
Block a user