Raumstempel: Auto-Konvertierung beim Modus-Wechsel + Font-API-Fix

Bug: Beim Toggle fix↔masstab blieb txt_h derselbe Zahlenwert mit anderer
Einheit. 0.20m wurde zu 0.20mm@1:100 = 0.02m Text (2cm). Stempel
unsichtbar klein.

Fix: Bridge konvertiert txt_h automatisch wenn der Modus wechselt UND
kein expliziter txtH-Wert im Patch ist:
  fix → masstab: paper_mm = m * 1000 / scale
  masstab → fix: m       = paper_mm * scale / 1000
Frontend sendet beim Modus-Toggle nur { txtModus } ohne txtH → Backend-
Konvertierung greift.

Plus: _list_system_fonts probiert jetzt InstalledFonts() + AvailableFontFaces
(InstalledFontsAsString existiert auf Mac Rhino 8 nicht); Ergebnis wird
session-weit gecacht damit der Error nicht jeden state-emit spamt.
This commit is contained in:
2026-05-26 20:58:28 +02:00
parent 238d7d062b
commit e56ee2cb8f
+54 -20
View File
@@ -440,37 +440,50 @@ def _list_hatch_patterns(doc):
return out return out
_RAUM_FONTS_CACHE = None # einmal pro Session, danach gecacht (System-Fonts aendern sich nicht)
def _list_system_fonts(): def _list_system_fonts():
"""Sammelt installierte Font-Quartet-Namen via Rhino.DocObjects.Font. """Sammelt installierte Font-Quartet-Namen via Rhino.DocObjects.Font.
Liefert sortierte Liste mit den haeufig benutzten DOSSIER-Fonts oben.""" Probiert mehrere API-Varianten (Rhino-Versionen unterscheiden sich)
out = [] und fuegt die DOSSIER-Default-Fonts oben an. Gecacht."""
global _RAUM_FONTS_CACHE
if _RAUM_FONTS_CACHE is not None:
return _RAUM_FONTS_CACHE
preferred = ["DM Mono", "Krungthep", "Archivo Black", "Playfair Display", preferred = ["DM Mono", "Krungthep", "Archivo Black", "Playfair Display",
"Helvetica", "Helvetica Neue", "Arial", "SF Pro Display", "Helvetica", "Helvetica Neue", "Arial", "SF Pro Display",
"Times New Roman", "Courier New"] "Times New Roman", "Courier New"]
raw = []
try: try:
from Rhino.DocObjects import Font as _Font from Rhino.DocObjects import Font as _Font
installed = _Font.InstalledFontsAsString() # Variante A: InstalledFonts() liefert IEnumerable[Font]
# InstalledFontsAsString liefert ; oder \n separated — beide handeln try:
raw = [] for f in _Font.InstalledFonts():
if installed: try:
for sep in (";", "\n", "\r"): n = f.QuartetName
if sep in installed: if n: raw.append(n)
raw = [s.strip() for s in installed.split(sep) if s.strip()] except Exception: pass
break except Exception: pass
if not raw: raw = [installed.strip()] # Variante B: AvailableFontFaces (Rhino 7+)
if not raw:
try:
for f in _Font.AvailableFontFaces:
try:
n = getattr(f, "QuartetName", None) or getattr(f, "FamilyPlusFaceName", None)
if n: raw.append(str(n))
except Exception: pass
except Exception: pass
except Exception: pass
# Dedupe + sortieren, Preferred zuerst
out = []
seen = set() seen = set()
# Erst Preferred wenn installiert
for f in preferred: for f in preferred:
if f in raw and f not in seen:
out.append(f); seen.add(f)
# Dann der Rest alphabetisch
for f in sorted(raw):
if f and f not in seen: if f and f not in seen:
out.append(f); seen.add(f) out.append(f); seen.add(f)
except Exception as ex: for f in sorted(set(raw)):
print("[ELEMENTE] list_system_fonts:", ex) if f and f not in seen:
# Fallback: nur die DOSSIER-Defaults out.append(f); seen.add(f)
out = preferred[:] _RAUM_FONTS_CACHE = out
return out return out
_TREPPE_SOLL_DEFAULT = { _TREPPE_SOLL_DEFAULT = {
@@ -10077,6 +10090,27 @@ class ElementeBridge(panel_base.BaseBridge):
if not isinstance(r_layout, list): r_layout = [] if not isinstance(r_layout, list): r_layout = []
r_modus = p.get("txtModus", old_meta.get("raum_txt_modus", "fix")) r_modus = p.get("txtModus", old_meta.get("raum_txt_modus", "fix"))
if r_modus not in ("fix", "masstab"): r_modus = "fix" if r_modus not in ("fix", "masstab"): r_modus = "fix"
# Modus-Wechsel: txt_h automatisch in die neue Einheit
# umrechnen, damit die Stempelgroesse visuell stabil bleibt.
# User hat 0.20m in fix → toggelt auf masstab → ohne Umrechnung
# wuerde das als 0.20mm@1:100 interpretiert = 0.02m Text. Mit
# Umrechnung: 0.20m @ 1:100 = 2mm Paper.
old_modus = old_meta.get("raum_txt_modus", "fix")
if r_modus != old_modus and "txtH" not in p:
try:
import massstab as _ms
scale = (_ms.get_applied_scale_ratio()
or _ms.get_current_scale_ratio() or 100.0)
except Exception: scale = 100.0
if r_modus == "masstab" and old_modus == "fix":
# m → paper-mm: paper_mm = m * 1000 / scale
r_th = float(r_th) * 1000.0 / float(scale)
elif r_modus == "fix" and old_modus == "masstab":
# paper-mm → m: m = paper_mm * scale / 1000
r_th = float(r_th) * float(scale) / 1000.0
print("[ELEMENTE] Raum-Modus {}{} @ 1:{:.0f}: "
"txt_h umgerechnet auf {:.4f}".format(
old_modus, r_modus, scale, r_th))
gstart = p.get("geschoss", old_meta["geschoss"]) gstart = p.get("geschoss", old_meta["geschoss"])
attrs = axis_obj.Attributes attrs = axis_obj.Attributes
if gstart != old_meta["geschoss"]: if gstart != old_meta["geschoss"]: