View-Toggle 2x4: TOP/ISO/PERSP/Cam + N/O/S/W mit Norden-Rotation

User-Vorschlag: Architektur-konformes View-Layout — 3D-Views oben, 4
Gebaeudeansichten unten. Plus Norden-Rotation als Doc-Setting damit bei
rotierten Projekten (swissBUILDINGS, Sonnenberechnungen) die richtigen
Wandansichten gepickt werden.

Backend (rhino/kamera.py):
- get_north_angle/set_north_angle — doc.Strings["dossier_north_angle"]
  (Grad im Uhrzeigersinn von +Y, default 0°)
- _scene_target_and_diag(doc) — gemeinsamer Helper fuer Szenen-Center +
  Diagonal-Distanz
- set_cardinal_view(vp, 'N'|'O'|'S'|'W'): rotiert Kamera-Position via
  Norden-Vektor. Parallel-Projektion, Camera-Z = Target-Z (echte
  Elevation), Up-Vektor +Z.
- set_top_view(vp): Plan-Ansicht mit Norden = Up-Vektor (Plan rotiert
  visuell wenn Norden != +Y)
- _set_iso(vp, octant): Octant-Richtung jetzt aus north+east-Vektoren
  konstruiert → ISO rotiert mit Norden mit
- Bridge-Handler SET_NORTH_ANGLE + state.northAngle, notify Oberleiste

Backend (oberleiste.py):
- SET_VIEW erweitert: Top → kamera.set_top_view, N/O/S/W →
  kamera.set_cardinal_view, Iso → kamera._set_iso. Front/Right/etc bleibt
  als Legacy direkt-Rhino-Call.
- State liefert northAngle

Frontend (OberleisteApp):
- VIEWS_ROW1: TOP/ISO/PERSP + Kamera-Settings-Button (Icons only)
- VIEWS_ROW2: N/O/S/W als DM-Mono-Buchstaben
- 2x4-Grid, VIEW_W=140 (konsistent mit Massstab-Pills), CELL_W=35
- matchView nur fuer Top/Iso/Perspective; Cardinals haben keinen
  Active-State (Viewport-Name ist nicht zuverlaessig erkennbar)

Frontend (KameraApp):
- Plan-Norden Section mit Number-Input (Grad, 0.5°-Step) + Reset-Button
- Hinweis-Text dass Wirkung auf TOP/ISO/N/O/S/W geht

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 00:04:44 +02:00
parent 2252ffd2f9
commit 205c626a5a
5 changed files with 306 additions and 99 deletions
+31 -5
View File
@@ -875,20 +875,40 @@ class OberleisteBridge(panel_base.BaseBridge):
# --- View-Switcher ----------------------------------------------
elif t == "SET_VIEW":
v = p.get("view")
if v in ("Top", "Front", "Right", "Perspective", "Left", "Back", "Bottom"):
try:
import kamera
vp = kamera._active_viewport()
except Exception:
vp = None
if v == "Top":
# Plan rotiert mit Norden — Up-Vektor zeigt Norden
try:
import kamera
kamera.set_top_view(vp)
except Exception as ex:
print("[OBERLEISTE] top:", ex)
self._send_state(force=True)
elif v == "Perspective":
_run("_-{} _Enter".format(v))
self._send_state(force=True)
elif v == "Iso":
# Standard-Architektur-Isometrie aus NE, true-iso 35°/45°.
# Implementiert in kamera.py — Logik dort, damit Kamera-
# Panel und Topbar dieselbe Berechnung teilen.
try:
import kamera
vp = kamera._active_viewport()
kamera._set_iso(vp, "NE")
except Exception as ex:
print("[OBERLEISTE] iso:", ex)
self._send_state(force=True)
elif v in ("N", "O", "S", "W"):
try:
import kamera
kamera.set_cardinal_view(vp, v)
except Exception as ex:
print("[OBERLEISTE] cardinal:", ex)
self._send_state(force=True)
elif v in ("Front", "Right", "Left", "Back", "Bottom"):
# Legacy direkte Rhino-Views (falls noch wo benutzt)
_run("_-{} _Enter".format(v))
self._send_state(force=True)
# --- Kamera-Panel oeffnen ---------------------------------------
elif t == "OPEN_KAMERA_PANEL":
@@ -1177,6 +1197,12 @@ class OberleisteBridge(panel_base.BaseBridge):
self._fonts_sent = True
except Exception:
info["textSettings"] = {}
# Norden-Rotation fuer N/O/S/W-Buttons
try:
import kamera
info["northAngle"] = kamera.get_north_angle(doc)
except Exception:
info["northAngle"] = 0
# Command-Line State
prompt = _get_command_prompt()
info["cmdPrompt"] = prompt