Merge: Schnittfunktion ausgebaut (Schnittlinie, Editieren im Schnitt, Tiefe)
- Befehl 'sectionline'/'viewline' (Aliase schnittlinie/ansichtslinie): zwei Klicks setzen die Schnitt-/Ansichtslinie, neue Ebene bei Bedarf - Schnittführungs-Symbol im Grundriss (Strichpunkt, Endmarken, Richtungs- pfeile, Label) + Pick-Band, Auswahl + Attribut-Sektion (Name, Richtung umkehren, Endpunkte, Tiefe, Löschen) - Editieren IM Schnitt: Cut-Polygone tragen die Quell-Element-Id (durch Schicht-Zerlegung/Terminierung/Dominanz propagiert) → Klick wählt das Bauteil, Panels editieren, Schnitt rechnet neu - Schnitt-Tiefe (DrawingLevel.depth): Ansichtskanten ferner Bauteile werden ausgeblendet (Owner-Distanz-Näherung, dokumentiert) # Conflicts: # src/model/types.ts
This commit is contained in:
+74
-1
@@ -582,6 +582,9 @@ export default function App() {
|
||||
const selectedRoofIds = useStore((s) => s.selectedRoofIds);
|
||||
const setSelectedRoofIds = useStore((s) => s.setSelectedRoofIds);
|
||||
const selectedRoofId = selectedRoofIds.length === 1 ? selectedRoofIds[0] : null;
|
||||
// Schnitt-/Ansichtslinien-Auswahl (Einzel-DrawingLevel-Id oder null).
|
||||
const selectedSectionLineId = useStore((s) => s.selectedSectionLineId);
|
||||
const setSelectedSectionLineId = useStore((s) => s.setSelectedSectionLineId);
|
||||
const updateRoof = useStore((s) => s.updateRoof);
|
||||
const moveRoofGrip = useStore((s) => s.moveRoofGrip);
|
||||
const moveRoofBy = useStore((s) => s.moveRoofBy);
|
||||
@@ -635,6 +638,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
setMenu(null);
|
||||
setEditor(null);
|
||||
}, [activeLevelId]);
|
||||
@@ -1853,6 +1857,13 @@ export default function App() {
|
||||
}
|
||||
if (e.key !== "Delete" && e.key !== "Backspace") return;
|
||||
if (activeTransform) return; // während einer Transformation nicht löschen
|
||||
// Schnittlinie: Entf löscht NUR ihre Linie (linePoints), die Ebene bleibt.
|
||||
if (selectedSectionLineId) {
|
||||
patchLevel(selectedSectionLineId, { linePoints: undefined });
|
||||
setSelectedSectionLineId(null);
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (
|
||||
selectedDrawingIds.length ||
|
||||
selectedWallIds.length ||
|
||||
@@ -1898,6 +1909,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
@@ -1914,6 +1926,7 @@ export default function App() {
|
||||
selectedExtrudedSolidIds,
|
||||
selectedColumnIds,
|
||||
selectedRoofIds,
|
||||
selectedSectionLineId,
|
||||
project.walls,
|
||||
project.drawings2d,
|
||||
project.ceilings,
|
||||
@@ -2707,6 +2720,21 @@ export default function App() {
|
||||
],
|
||||
);
|
||||
|
||||
// Gewählte Schnitt-/Ansichtslinie (DrawingLevel) — separat von `selection`, da
|
||||
// eine Schnittlinie KEIN Projekt-Bauteil ist. Speist die Schnittlinien-Sektion
|
||||
// des Object-Info-Panels.
|
||||
const sectionLine = useMemo(
|
||||
() =>
|
||||
selectedSectionLineId
|
||||
? project.drawingLevels.find(
|
||||
(z) =>
|
||||
z.id === selectedSectionLineId &&
|
||||
(z.kind === "section" || z.kind === "elevation"),
|
||||
) ?? null
|
||||
: null,
|
||||
[project.drawingLevels, selectedSectionLineId],
|
||||
);
|
||||
|
||||
// ── DXF/DWG-Import (Dialog) ───────────────────────────────────────────────
|
||||
// Eine Datei (Button ODER Drop) öffnet den modalen Import-Dialog. DXF wird als
|
||||
// Text geparst, DWG als ArrayBuffer über LibreDWG-WASM (lazy, asynchron); beide
|
||||
@@ -3319,6 +3347,14 @@ export default function App() {
|
||||
onSetRoofPatch: (patch) => {
|
||||
if (selection?.kind === "roof") updateRoof(selection.id, patch);
|
||||
},
|
||||
// ── Schnitt-/Ansichtslinie (nur bei selektierter Linie) ────────────────
|
||||
sectionLine,
|
||||
onSetSectionLinePatch: (patch) => {
|
||||
if (selectedSectionLineId) patchLevel(selectedSectionLineId, patch);
|
||||
},
|
||||
onDeleteSectionLine: () => {
|
||||
if (selectedSectionLineId) patchLevel(selectedSectionLineId, { linePoints: undefined });
|
||||
},
|
||||
// ── Treppen-Attribute (nur bei selektierter Treppe) ────────────────────
|
||||
onSetStairShape: (shape) => {
|
||||
if (selection?.kind === "stair") updateStair(selection.id, { shape });
|
||||
@@ -3475,6 +3511,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
switch (kind) {
|
||||
case "Wand":
|
||||
setSelectedWallIds([id]);
|
||||
@@ -3848,6 +3885,8 @@ export default function App() {
|
||||
detail,
|
||||
scaleDenominator,
|
||||
selection,
|
||||
sectionLine,
|
||||
selectedSectionLineId,
|
||||
selectedViewSnapshotId,
|
||||
]);
|
||||
|
||||
@@ -4334,6 +4373,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
setStampEditorRoomId(roomId);
|
||||
};
|
||||
// Doppelklick auf ein Text-2D-Element: selektieren + Inhalts-Editor öffnen.
|
||||
@@ -4349,6 +4389,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
setEditTextId(drawingId);
|
||||
};
|
||||
// Bearbeiteten Text-Inhalt übernehmen (immutabel; nur bei Text-Geometrie).
|
||||
@@ -4373,6 +4414,13 @@ export default function App() {
|
||||
// Rest behalten (Wände und 2D-Zeichnungen unabhängig, gemischte Auswahl
|
||||
// erlaubt). Leerraum-Klick mit Shift lässt die Auswahl unverändert.
|
||||
if (sel.shift) {
|
||||
// Schnittlinie ist Einzelauswahl — Shift+Klick togglet sie an/aus.
|
||||
if (sel.sectionLineId) {
|
||||
setSelectedSectionLineId(
|
||||
selectedSectionLineId === sel.sectionLineId ? null : sel.sectionLineId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (sel.wallId) {
|
||||
const id = sel.wallId;
|
||||
setSelectedWallIds(
|
||||
@@ -4454,8 +4502,12 @@ export default function App() {
|
||||
if (keep !== "extrudedSolid") setSelectedExtrudedSolidIds([]);
|
||||
if (keep !== "column") setSelectedColumnIds([]);
|
||||
if (keep !== "roof") setSelectedRoofIds([]);
|
||||
if (keep !== "sectionLine") setSelectedSectionLineId(null);
|
||||
};
|
||||
if (sel.openingId) {
|
||||
if (sel.sectionLineId) {
|
||||
setSelectedSectionLineId(sel.sectionLineId);
|
||||
clearOthers("sectionLine");
|
||||
} else if (sel.openingId) {
|
||||
setSelectedOpeningIds([sel.openingId]);
|
||||
clearOthers("opening");
|
||||
} else if (sel.wallId) {
|
||||
@@ -4500,6 +4552,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
};
|
||||
// Rechts-Klick im Grundriss: Wand-Kontextmenü. Trifft der Klick eine Wand, die
|
||||
// NICHT bereits in der Auswahl ist, wird die Auswahl auf sie gesetzt (damit die
|
||||
@@ -4526,6 +4579,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
}
|
||||
};
|
||||
// Links-Klick im 3D: per Raycast getroffene Treppe wählen (Einzelauswahl).
|
||||
@@ -4540,6 +4594,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
}
|
||||
};
|
||||
// Links-Klick im 3D: per Raycast getroffene Decke wählen (Einzelauswahl).
|
||||
@@ -4554,6 +4609,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
}
|
||||
};
|
||||
// Links-Klick im 3D: per Raycast getroffene Öffnung wählen (Einzelauswahl).
|
||||
@@ -4568,6 +4624,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
}
|
||||
};
|
||||
// Links-KLICK im Nordstern-3D-Viewport (WASM, TS-Raycast): getroffenes Bauteil
|
||||
@@ -4587,6 +4644,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
return;
|
||||
}
|
||||
// Öffnung (Fenster/Tür) und Treppe sind jetzt auch im WASM-Viewport pickbar
|
||||
@@ -4602,6 +4660,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
return;
|
||||
}
|
||||
if (hit.kind === "stair") {
|
||||
@@ -4614,6 +4673,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
return;
|
||||
}
|
||||
if (hit.kind === "roof") {
|
||||
@@ -4646,6 +4706,7 @@ export default function App() {
|
||||
setSelectedExtrudedSolidIds([]);
|
||||
setSelectedColumnIds([]);
|
||||
setSelectedRoofIds([]);
|
||||
setSelectedSectionLineId(null);
|
||||
};
|
||||
// Rechts-Klick im 3D: Wand-Kontextmenü an der Cursorposition.
|
||||
const onViewportContextMenu = (info: ViewportContextInfo) => {
|
||||
@@ -4941,6 +5002,7 @@ export default function App() {
|
||||
selectedColumnIds={selectedColumnIds}
|
||||
selectedRoomIds={selectedRoomIds}
|
||||
selectedRoofIds={selectedRoofIds}
|
||||
selectedSectionLineId={selectedSectionLineId}
|
||||
roomStamp={roomStamp}
|
||||
onStampMove={moveRoomStamp}
|
||||
onStampEdit={onOpenStampEditor}
|
||||
@@ -6074,6 +6136,7 @@ function Content({
|
||||
selectedColumnIds,
|
||||
selectedRoomIds,
|
||||
selectedRoofIds,
|
||||
selectedSectionLineId,
|
||||
roomStamp,
|
||||
onStampMove,
|
||||
onStampEdit,
|
||||
@@ -6152,6 +6215,7 @@ function Content({
|
||||
selectedColumnIds: string[];
|
||||
selectedRoomIds: string[];
|
||||
selectedRoofIds: string[];
|
||||
selectedSectionLineId: string | null;
|
||||
roomStamp: { roomId: string; anchor: Vec2 } | null;
|
||||
onStampMove: (roomId: string, delta: Vec2) => void;
|
||||
onStampEdit: (roomId: string) => void;
|
||||
@@ -6269,6 +6333,7 @@ function Content({
|
||||
selectedColumnIds={selectedColumnIds}
|
||||
selectedRoomIds={selectedRoomIds}
|
||||
selectedRoofIds={selectedRoofIds}
|
||||
selectedSectionLineId={selectedSectionLineId}
|
||||
roomStamp={roomStamp}
|
||||
onStampMove={onStampMove}
|
||||
onStampEdit={onStampEdit}
|
||||
@@ -6324,6 +6389,7 @@ function Content({
|
||||
selectedColumnIds={selectedColumnIds}
|
||||
selectedRoomIds={selectedRoomIds}
|
||||
selectedRoofIds={selectedRoofIds}
|
||||
selectedSectionLineId={selectedSectionLineId}
|
||||
roomStamp={roomStamp}
|
||||
onStampMove={onStampMove}
|
||||
onStampEdit={onStampEdit}
|
||||
@@ -6419,6 +6485,7 @@ function Content({
|
||||
selectedColumnIds={selectedColumnIds}
|
||||
selectedRoomIds={selectedRoomIds}
|
||||
selectedRoofIds={selectedRoofIds}
|
||||
selectedSectionLineId={selectedSectionLineId}
|
||||
roomStamp={roomStamp}
|
||||
onStampMove={onStampMove}
|
||||
onStampEdit={onStampEdit}
|
||||
@@ -6464,6 +6531,7 @@ function LevelPlanView({
|
||||
selectedColumnIds,
|
||||
selectedRoomIds,
|
||||
selectedRoofIds,
|
||||
selectedSectionLineId,
|
||||
roomStamp,
|
||||
onStampMove,
|
||||
onStampEdit,
|
||||
@@ -6502,6 +6570,7 @@ function LevelPlanView({
|
||||
selectedColumnIds: string[];
|
||||
selectedRoomIds: string[];
|
||||
selectedRoofIds: string[];
|
||||
selectedSectionLineId: string | null;
|
||||
roomStamp: { roomId: string; anchor: Vec2 } | null;
|
||||
onStampMove: (roomId: string, delta: Vec2) => void;
|
||||
onStampEdit: (roomId: string) => void;
|
||||
@@ -6579,6 +6648,7 @@ function LevelPlanView({
|
||||
selectedColumnIds={selectedColumnIds}
|
||||
selectedRoomIds={selectedRoomIds}
|
||||
selectedRoofIds={selectedRoofIds}
|
||||
selectedSectionLineIds={selectedSectionLineId ? [selectedSectionLineId] : []}
|
||||
roomStamp={roomStamp}
|
||||
onStampMove={onStampMove}
|
||||
onStampEdit={onStampEdit}
|
||||
@@ -6632,6 +6702,7 @@ function SectionPlanView({
|
||||
selectedColumnIds,
|
||||
selectedRoomIds,
|
||||
selectedRoofIds,
|
||||
selectedSectionLineId,
|
||||
roomStamp,
|
||||
onStampMove,
|
||||
onStampEdit,
|
||||
@@ -6666,6 +6737,7 @@ function SectionPlanView({
|
||||
selectedColumnIds: string[];
|
||||
selectedRoomIds: string[];
|
||||
selectedRoofIds: string[];
|
||||
selectedSectionLineId: string | null;
|
||||
roomStamp: { roomId: string; anchor: Vec2 } | null;
|
||||
onStampMove: (roomId: string, delta: Vec2) => void;
|
||||
onStampEdit: (roomId: string) => void;
|
||||
@@ -6767,6 +6839,7 @@ function SectionPlanView({
|
||||
selectedColumnIds={selectedColumnIds}
|
||||
selectedRoomIds={selectedRoomIds}
|
||||
selectedRoofIds={selectedRoofIds}
|
||||
selectedSectionLineIds={selectedSectionLineId ? [selectedSectionLineId] : []}
|
||||
roomStamp={roomStamp}
|
||||
onStampMove={onStampMove}
|
||||
onStampEdit={onStampEdit}
|
||||
|
||||
Reference in New Issue
Block a user