Wand-Grips + Schnitt-Grips + Referenz-Sublayer pro Bauteil + Print-Auto-Hide
Custom-Grip-Overlays via DisplayConduit + MouseCallback: - wand_grips.py: dicke klickbare Marker an wand_axis-Endpunkten, auch wenn die Referenz-Layer ausgeblendet ist. GetPoint mit fixem Anker. - schnitt_grips.py: 3 Marker pro Schnitt (P1, P2, Mid). Mid translatiert ganze Linie, P1/P2 verschieben Endpunkt. Hide Clipping-Planes waehrend GetPoint damit kein Verbots-Cursor durch Locked-Edges erscheint. skip_view=True bei Re-Activate damit Drag nicht in Section springt. Referenz-Architektur umgebaut: - wand_axis + oeffnung_point liegen jetzt unter <Geschoss>::20_Waende:: 20r_Referenz statt eigener top-level 19_Referenzlinien-Ebene. - Migration v4 zieht existierende Sources auf den neuen Pfad. - Toggle in Oberleiste keyword-driven: findet alle 'Referenz'-Sub-Ebenen rekursiv, toggelt alle Praefixe gemeinsam. Bauteil-uebergreifend. Oberleiste-Layout: - Druck-Ansicht-Button hoch neben Massstab-Dropdown (Reihe 1). - Referenzlinien-Toggle in Reihe 2 neben Zoom-Pill, symmetrisch zum Druck-Button. Zoom-Pill auf 3 Buttons reduziert. - Print-View AN → Referenz-Layer automatisch ausblenden, Snapshot restored beim Ausschalten. Fix: clear_schnitt_clipping respektiert Mode=Locked nicht — vor Delete auf Normal-Mode wechseln + Modify damit's persistiert. Schnitt-Loeschen raeumt Clipping-Planes jetzt sauber auf. Fix: Schnitt-Doppelklick-Handler aktiviert nur bei expliziter Schnitt- Auswahl, ignoriert andere Selektionen. Fix: _send_state Selection-Detection mit Source-ODER-Volume-Fallback — Fenster-Properties erscheinen jetzt auch wenn oeffnung_point auf hidden Referenz-Layer liegt. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+91
-14
@@ -645,16 +645,77 @@ def _layer_path_volume(doc, geschoss_name):
|
||||
return _layer_path_axis(doc, geschoss_name)
|
||||
|
||||
|
||||
def _ensure_referenz_child_in_doc(doc, parent_code, parent_keywords,
|
||||
parent_default_name):
|
||||
"""Stellt sicher dass unter einer Bauteil-Parent-Ebene (z.B. WAENDE,
|
||||
Code 20) ein 'Referenz'-Sub-Sub-Layer existiert. Code ist
|
||||
parent_code + 'r' (z.B. '20r'). Liefert (parent_sub_name, child_sub_name)
|
||||
fuer Pfad-Konstruktion.
|
||||
|
||||
Idempotent: legt nur an wenn nicht vorhanden, triggert dann
|
||||
build_layers + broadcast_state."""
|
||||
parent_sub = _find_ebene_sublayer_name(
|
||||
doc, parent_keywords, parent_code, parent_default_name,
|
||||
default_color="#0a0a0a", default_lw=0.50)
|
||||
# parent_sub = "20_Wände" oder vom User customisiert — Code aus Prefix
|
||||
parent_real_code = parent_sub.split("_", 1)[0] if "_" in parent_sub else parent_code
|
||||
ref_code = parent_real_code + "r"
|
||||
ref_child_sub = "{}_Referenz".format(ref_code)
|
||||
|
||||
raw = doc.Strings.GetValue("dossier_ebenen")
|
||||
try: ebenen = json.loads(raw) if raw else []
|
||||
except Exception: ebenen = []
|
||||
if not isinstance(ebenen, list): return parent_sub, ref_child_sub
|
||||
|
||||
# Parent-Eintrag im Tree finden (rekursiv falls nested)
|
||||
def _find_parent(lst):
|
||||
for e in lst:
|
||||
if not isinstance(e, dict): continue
|
||||
if e.get("code") == parent_real_code: return e
|
||||
kids = e.get("children")
|
||||
if isinstance(kids, list):
|
||||
r = _find_parent(kids)
|
||||
if r is not None: return r
|
||||
return None
|
||||
parent_e = _find_parent(ebenen)
|
||||
if parent_e is None: return parent_sub, ref_child_sub
|
||||
|
||||
if not isinstance(parent_e.get("children"), list):
|
||||
parent_e["children"] = []
|
||||
have = any(isinstance(c, dict) and c.get("code") == ref_code
|
||||
for c in parent_e["children"])
|
||||
if not have:
|
||||
parent_e["children"].append({
|
||||
"code": ref_code, "name": "Referenz",
|
||||
"color": "#a0a0a0", "lw": 0.13,
|
||||
"visible": True, "locked": False,
|
||||
})
|
||||
try:
|
||||
doc.Strings.SetString("dossier_ebenen",
|
||||
json.dumps(ebenen, ensure_ascii=False))
|
||||
import layer_builder
|
||||
z_raw = doc.Strings.GetValue("dossier_zeichnungsebenen")
|
||||
zlist = json.loads(z_raw) if z_raw else []
|
||||
if zlist: layer_builder.build_layers(doc, zlist, ebenen)
|
||||
import rhinopanel
|
||||
rhinopanel._broadcast_state(doc)
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] _ensure_referenz_child:", ex)
|
||||
return parent_sub, ref_child_sub
|
||||
|
||||
|
||||
def _layer_path_referenz(doc, geschoss_name):
|
||||
"""Sublayer 'Referenzlinien' (Code 19) — eigene Ebene fuer wand_axis +
|
||||
oeffnung_point Source-Objekte. Getrennt vom Wand-Volumen-Layer (20)
|
||||
damit der User die Konstruktions-Referenzen ein-/ausblenden kann ohne
|
||||
die Volumen-Sichtbarkeit zu verlieren. Wird automatisch im Ebenen-
|
||||
Panel sichtbar (auto-add via _find_ebene_sublayer_name)."""
|
||||
sub = _find_ebene_sublayer_name(doc, ["referenz", "referenzlinie"],
|
||||
"19", "Referenzlinien",
|
||||
default_color="#a0a0a0", default_lw=0.13)
|
||||
return "{}::{}".format(geschoss_name, sub)
|
||||
"""Sub-Sub-Layer '<parent_code>r_Referenz' unter der WAENDE-Ebene fuer
|
||||
wand_axis + oeffnung_point Source-Objekte. Bauteil-konsistent: die
|
||||
Referenz-Linie gehoert konzeptuell zur Wand, also nested unter WAENDE
|
||||
statt als eigene top-level Ebene wie frueher (alt: 19_Referenzlinien).
|
||||
|
||||
Toggle in der Oberleiste findet alle 'Referenz'-Sub-Sub-Layer ueber
|
||||
alle Bauteile keyword-basiert — falls Decken/Dach/Tragwerk spaeter
|
||||
auch Referenz-Sublayer kriegen, wirkt der Toggle automatisch."""
|
||||
parent_sub, child_sub = _ensure_referenz_child_in_doc(
|
||||
doc, "20", ["wand", "wände", "waende"], "Wände")
|
||||
return "{}::{}::{}".format(geschoss_name, parent_sub, child_sub)
|
||||
|
||||
|
||||
def _layer_path_schnittlinie(doc, geschoss_name):
|
||||
@@ -10367,11 +10428,11 @@ def _migrate_referenz_layer_once(doc):
|
||||
Geschoss aufgerufen, was via _find_ebene_sublayer_name den Auto-Add
|
||||
+ broadcast_state ausloest."""
|
||||
if doc is None: return
|
||||
# Sticky-Version bumped: vorherige Versionen liefen ohne proaktive
|
||||
# Ebenen-Registrierung — wenn die alten Keys gesetzt sind, wuerde die
|
||||
# neue Logik nie greifen. v3 = aktuelle Implementierung.
|
||||
try: key = "_dossier_referenz_migration_v3_" + str(doc.RuntimeSerialNumber)
|
||||
except Exception: key = "_dossier_referenz_migration_v3_default"
|
||||
# v4: Referenzlinien wandern von top-level '19_Referenzlinien' auf
|
||||
# Sub-Sub-Layer '<parent_code>r_Referenz' unter den jeweiligen
|
||||
# Bauteil-Parent (aktuell nur WAENDE). Sticky-Bump zwingt Re-Run.
|
||||
try: key = "_dossier_referenz_migration_v4_" + str(doc.RuntimeSerialNumber)
|
||||
except Exception: key = "_dossier_referenz_migration_v4_default"
|
||||
if sc.sticky.get(key): return
|
||||
sc.sticky[key] = True
|
||||
n_moved = 0
|
||||
@@ -11553,6 +11614,22 @@ def _install_listeners(bridge):
|
||||
schnitte.install_double_click_handler()
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] schnitt dblclick install:", ex)
|
||||
# Wand-Endpoint-Grip-Overlay (Display-Conduit + Mouse-Handler) —
|
||||
# dicke klickbare Marker an den Achs-Endpunkten, auch wenn die
|
||||
# Referenzlinien-Layer ausgeblendet ist.
|
||||
try:
|
||||
import wand_grips
|
||||
wand_grips.install_handlers()
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] wand_grips install:", ex)
|
||||
# Schnittsymbol-Endpoint-Grips — analoges Overlay an den P1/P2 der
|
||||
# Schnittlinie. Ziehen updated linePts + regeneriert das Symbol +
|
||||
# re-aktiviert den Schnitt wenn aktiv.
|
||||
try:
|
||||
import schnitt_grips
|
||||
schnitt_grips.install_handlers()
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] schnitt_grips install:", ex)
|
||||
|
||||
|
||||
def _bridge_factory():
|
||||
|
||||
Reference in New Issue
Block a user