2D: Kanten-Griffe (Seite parallel verschieben) bekommen dieselbe

Bearbeitung wie Punkt-Griffe

Nutzer-Wunsch: "das Ganze soll auch an den Seiten bei diesen Dreiecken
gehen bei denen man eine Fläche parallel verschieben kann" -- also
dieselbe Klick-loslassen-tippen-bestätigen-Geste, dieselbe Cursor-HUD-
Anzeige und dieselbe getippte Werteingabe wie bei den Punkt-Griffen aus
den letzten Commits, jetzt auch für die Kanten-Anfasser.

useGripEditing.ts: onEdgeMove rechnet jetzt mit einem ABSOLUTEN
Zielpunkt relativ zum ORIGINALEN Kanten-Mittelpunkt (Momentaufnahme vom
Grab), nicht mehr rein inkrementell pro Frame -- eine neue
edgeAppliedDeltaRef verankert, wie viel Delta bereits angewandt wurde,
und wendet jeweils nur die Differenz zum neuen Ziel an (moveEdgeOf/
moveRoomEdge/moveCeilingEdge sind additiv). Neuer edgeEdit-Feld-
Controller (Pendant zu gripEdit): geführte Kanten (rect/geschlossene
Polylinie/Wand) haben nur EIN Feld ("Länge" = vorzeichenbehafteter
Abstand entlang der festen Normale, kein Winkel), freie Kanten (offene
Polylinie/Linie) wie ein Punkt-Griff Länge+Winkel relativ zum
Ursprung. Cursor-HUD zeigt bei geführten Kanten "Δ: …m" als Freitext
(das L/W-Schema passt nicht für ein Einzelfeld), bei freien Kanten
L/W wie beim Punkt-Griff. onEdgeCancel verwirft exakt auf den
Ursprung zurück (Ziel = Anker selbst).

PlanView.tsx: Kanten-Griff-Grab läuft jetzt ohne Pointer-Capture
(dasselbe "bewaffnet nach Loslassen"-Verhalten wie beim Punkt-Griff),
Abschluss per erneutem Klick/Enter, Verwerfen per Escape. Neue
confirmEdgeEdit()-Methode am Imperativ-Handle (Pendant zu
confirmGripEdit) fürs Enter-mit-leerem-Text aus der Befehlszeile.

App.tsx: CommandLine-Verdrahtung (active/promptKey/fields/onSubmit/
onCycleField/onCancel) um den edgeEdit-Zweig erweitert, neuer i18n-
Prompt "cmd.edit.edge" (de/en). useToolNumberShortcuts blockt
Zifferntasten jetzt auch während eines bewaffneten Kanten-Griffs
(gleicher Bug wie zuvor bei Punkt-Griffen, präventiv mitgefixt).

useCommandTabShortcut (useKeyboardShortcuts.ts) generalisiert: Tab
zykelt/öffnet jetzt sowohl den Punkt- als auch den neuen Kanten-Feld-
Controller (dieselbe Instanz, zusätzliche optionale Parameter).
This commit is contained in:
2026-08-21 23:56:48 +02:00
parent cdfef949bf
commit 31a5b64836
6 changed files with 368 additions and 114 deletions
+15
View File
@@ -69,6 +69,12 @@ export function useCommandTabShortcut(
locks: { length?: number; angle?: number };
} | null>,
cycleGripEditFieldRef: RefObject<() => void>,
// Dasselbe für einen Kanten-Griff (Seite parallel verschieben) — separater
// Drag-Kanal, aber identisches Tab-Verhalten (öffnen/zyklen + Befehlsfeld
// fokussieren).
edgeDragInfoRef?: RefObject<{ edge: unknown; raw: Vec2 } | null>,
edgeEditRef?: RefObject<unknown>,
cycleEdgeEditFieldRef?: RefObject<() => void>,
): void {
useEffect(() => {
const onKey = (e: KeyboardEvent) => {
@@ -105,6 +111,13 @@ export function useCommandTabShortcut(
if (!wasOpen) commandLineRef.current?.focus();
return;
}
// Dasselbe für einen laufenden Kanten-Drag (Seite parallel verschieben).
if (edgeDragInfoRef?.current) {
const wasOpen = edgeEditRef?.current != null;
cycleEdgeEditFieldRef?.current?.();
if (!wasOpen) commandLineRef.current?.focus();
return;
}
commandLineRef.current?.focus();
};
window.addEventListener("keydown", onKey);
@@ -125,6 +138,7 @@ export function useToolNumberShortcuts(
isFloor: boolean,
engineRef: RefObject<CommandEngine | null>,
gripDragInfoRef?: RefObject<{ index: number; raw: Vec2 } | null>,
edgeDragInfoRef?: RefObject<unknown>,
): void {
const toolShortcutRef = useRef({ onSelectTool, floor: isFloor });
toolShortcutRef.current = { onSelectTool, floor: isFloor };
@@ -150,6 +164,7 @@ export function useToolNumberShortcuts(
// getippter Wert schaltete auf das per Ziffer gemappte Zeichenwerkzeug
// um, sobald das leere, fokussierte Befehlsfeld erkannt wurde).
if (gripDragInfoRef?.current) return;
if (edgeDragInfoRef?.current) return;
const el = e.target as HTMLElement | null;
const isInput =
!!el && (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable);