#! python3 # -*- coding: utf-8 -*- # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (C) 2026 Karim Gabriele Varano """ treppe_grips.py Display-Conduit fuer gruene Endpunkt-Marker an Treppen-Achsen. Visuelle Indikation wie bei Waenden, aber keine eigene Drag-Logik — der normale Partnership-Cascade (elemente._on_select_objects) + Pure-Transform-Pfad verschieben die Treppe bereits sauber. Endpunkt-Logik pro Treppen-Art: - gerade : PointAtStart, PointAtEnd der Linie - L : poly[0] (Start), poly[2] (Ende) — poly[1] ist der Eck-Punkt - Wendel : poly[1] (Start), poly[2] (Ende) — poly[0] ist Rotations- zentrum, nicht der Treppen-Anfang """ import Rhino import Rhino.Display as rd import Rhino.Geometry as rg import scriptcontext as sc import System.Drawing as SD _MARKER_RADIUS_PX = 7 _MARKER_FILL = SD.Color.FromArgb(220, 95, 168, 150) # petrol-gruen, gleich wie wand_grips _MARKER_BORDER = SD.Color.FromArgb(255, 47, 93, 84) def _treppe_endpoints(axis_obj): """Liefert Liste von Point3d fuer Treppen-Start + -Ende. Beachtet treppe_art (Wendel hat anderes Polyline-Schema).""" if axis_obj is None or axis_obj.IsDeleted: return [] a = axis_obj.Attributes if a.GetUserString("dossier_element_type") != "treppe_axis": return [] geom = axis_obj.Geometry if not isinstance(geom, rg.Curve): return [] art = a.GetUserString("dossier_treppe_art") or "gerade" try: if art == "wendel": ok, poly = geom.TryGetPolyline() if not ok or poly is None or poly.Count != 3: return [] return [poly[1], poly[2]] # gerade + L → Start- und End-Punkt der Curve sind die Treppen-Enden return [geom.PointAtStart, geom.PointAtEnd] except Exception: return [] class _TreppeEndpointConduit(rd.DisplayConduit): """Zeichnet gruene Endpunkt-Marker an allen selektierten Treppen-Achsen.""" def DrawForeground(self, e): try: doc = Rhino.RhinoDoc.ActiveDoc if doc is None: return sel = list(doc.Objects.GetSelectedObjects(False, False)) seen = set() for obj in sel: a = obj.Attributes eid = a.GetUserString("dossier_element_id") or "" if not eid or eid in seen: continue # Source-Axis via element_id finden (kann anderer Obj sein # wenn User nur Volume oder 2D-Symbol selektiert hat) axis = None for o in doc.Objects: if o is None or o.IsDeleted: continue try: a2 = o.Attributes if a2.GetUserString("dossier_element_id") == eid and \ a2.GetUserString("dossier_element_type") == "treppe_axis": axis = o; break except Exception: continue if axis is None: continue seen.add(eid) for pt in _treppe_endpoints(axis): try: e.Display.DrawPoint(pt, rd.PointStyle.RoundControlPoint, _MARKER_RADIUS_PX, _MARKER_FILL) except Exception: try: e.Display.DrawDot(pt, "●", _MARKER_FILL, _MARKER_BORDER) except Exception: pass except Exception as ex: print("[TREPPE_GRIPS] DrawForeground:", ex) _STICKY_CONDUIT = "_dossier_treppe_grips_conduit" def install_handlers(): """Idempotente Registrierung. Bei Modul-Reload alten Conduit zuerst disablen, dann neuen anhaengen.""" try: old = sc.sticky.get(_STICKY_CONDUIT) if old is not None: try: old.Enabled = False except Exception: pass conduit = _TreppeEndpointConduit() conduit.Enabled = True sc.sticky[_STICKY_CONDUIT] = conduit print("[TREPPE_GRIPS] Endpoint-Conduit aktiv") except Exception as ex: print("[TREPPE_GRIPS] install:", ex)