970281e10a
Properties-Panel: - Konsistentes 50px/1fr/14px Grid fuer alle Treppen-Rows - Lage + Unten als Dropdown (lowercase Labels) - Versatz: Dropdown (Geschoss-OKFF) oder eigenes Z mit Input + x-Button - Ziel: gleich (Geschoss-Liste oder eigene Hoehe), Geschosse-Filter excludes das Start-Geschoss - Start-Dropdown filtert auf okff < Ziel-Z (kein hoeheres Geschoss als Start waehlbar, beachtet auch eigene-Hoehe-Ziel) - Stufen: Dropdown 2-40 (statt freie Eingabe), mit Lock nur S-konforme Werte - Dropdowns nutzen System-Font (statt mono) - Ausgrenzung 'Aussenlinie'-Toggle (Aussenlinie immer an) - Pfeil-Style-Dropdown unter Lauflinie-Checkbox: klassisch / gefuellt (Solid-Hatch) / breit / voll (Spitzen bis Treppen-Aussenkanten) Backend Treppe: - Start-Z-Override via treppe_uk_over (m Offset relativ zu Geschoss-OKFF) - 2D-Symbol bleibt auf OKFF (egal ob Versatz) — Symbol klebt am Boden - Lauflinie-Schaft auf visuellen Treppen-Mittelpunkt versetzt (bei Lage=links/rechts), nicht mehr auf der Referenz-Achse - Trittmass-Lock: treppe_lock_s + target_S/A. Beim Aktivieren werden S+A als Ziel gespeichert. Bei H-Change wird N=round(H/target_S) recomputed + Axis-Laenge auf N*target_A angepasst (gerade Treppen) - Bruchsymbol-Toggle aus: ganze Treppe ungesplittet zeichnen (eff_cut_h=0 → kein Lower/Upper-Split) - Treppen-Endpunkt-Marker (treppe_grips.py) — gruene Punkte an Start/ Ende der Lauflinie, beachtet treppe_art (Wendel: poly[1]/poly[2]) Verdoppelungs-Fix: - _find_target_volume skipt treppe_2d_symbol explicit (sind 2D-Curves, kein Volume). Vorher konnte Replace(curve, brep) fehlschlagen → das echte Treppen-Brep blieb stehen + neues kam dazu → Duplikat - _find_objects_by_wall_id mit HiddenObjects+LockedObjects-Iterator, findet auch Objs auf hidden 3D-Layer - Anti-Dup-Cleanup in _regenerate_element: bei mehreren treppe_volume mit gleicher element_id → alle ausser dem ersten loeschen State-Pipeline: - geschosse-Liste enthaelt jetzt okff+hoehe (fuer Frontend-Constraints) - Treppe-State neu: ukOver, arrowStyle, lockS, targetS, targetA - Hidden-Source-Fallback in _send_state findet auch Treppen wenn der 3D-Layer aus ist (sodass Properties-Panel angezeigt wird) Dimensionen-Panel: - on_select + on_idle skippen waehrend Partnership-Cascade oder User-Transform — kein Flicker mehr beim Drag Andere: - Wand-Polyline-Vertex-Grips (alle Vertices, nicht nur Enden) - PopupMenu unterstuetzt _divider + checked-Items - TREPPEN/RAEUME Layer-Migration auf Capital-Case - selection-partnership tolerant: hidden Source wird trotzdem in die Selection genommen (sonst kann Drag nicht durch Pure-Transform)
105 lines
4.0 KiB
Python
105 lines
4.0 KiB
Python
#! 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)
|