Hatch↔Curve-Sync: User-Transform-Skip war zu aggressiv
Symptom: Beim Verschieben einer Polylinie ging die gekoppelte Hatch nicht mehr mit; umgekehrt zog die Hatch die Curve auch nicht mehr mit. Die bidirektionale Hatch-Curve-Kopplung war kaputt. Ursache: ich hatte vor einiger Zeit in gestaltungs on_replace, on_delete und on_add jeweils einen `_dossier_user_transform_active`- Skip eingebaut um waehrend elemente-Moves die Listener stumm zu halten (Performance). Damit wurden aber auch die Hatch-Coupling- Updates fuer normale Polylinien geblockt — die laufen ja gerade genau dann, wenn der User einen `_Move` macht. Fix: Skip-Logik selektiver machen: - on_replace: Skip ENTFERNT. Stattdessen ein frueher Bail-out wenn das Objekt weder _FILL_KEY noch _FILL_OWNER_KEY hat → Wand-Sub- Volumen werden immer noch nicht angepackt, aber Hatch-gekoppelte Polylinien laufen durch (auch waehrend _Move). - on_delete: Skip ENTFERNT. Der vorhandene Bail-out auf "kein Hatch- UserString" filtert dossier-Sub-Volumen weiterhin raus. Hatch- gekoppelte Curves machen Cascade-Delete + Pending-Save fuer die Recovery in on_add. - on_add: zwei Phasen — Drag-Recovery (Phase 1, IMMER) und Auto-Fill (Phase 2, nur ausserhalb User-Transform). So funktioniert die Delete+Add-Recovery von Rhinos Move waehrend Auto-Fill nicht versehentlich neue Hatches fuer Wand-Volumen anlegt. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+23
-14
@@ -1387,16 +1387,24 @@ def _install_selection_listener(bridge):
|
||||
- Hatch hat _FILL_OWNER_KEY (= curve_id) → Curve um den gleichen
|
||||
Vektor mit-translaten (User hat Hatch alleine verschoben).
|
||||
"""
|
||||
# Waehrend User-Transform-Command: elemente uebernimmt die Geometrie-
|
||||
# Synchronisation. Hatch-Re-Create laeuft hier sowieso ins Leere weil
|
||||
# Rhino bei Move Delete+Add statt Replace feuert.
|
||||
if sc.sticky.get("_dossier_user_transform_active"): return
|
||||
if sc.sticky.get("_dossier_undo_active"): return
|
||||
if sc.sticky.get("_elemente_regen_busy"): return
|
||||
new_obj = args.NewRhinoObject
|
||||
if new_obj is None or new_obj.Id in _processing:
|
||||
return
|
||||
a = new_obj.Attributes
|
||||
# Frueher Bail-out wenn das Objekt KEIN Hatch-Coupling hat — irrelevant.
|
||||
# Erst NACH dieser Pruefung das user-transform-Skip, sonst wuerde die
|
||||
# Hatch-Sync beim Verschieben einer normalen Polylinie nicht laufen
|
||||
# (war der Fall nach dem Split: Hatch ging bei _Move nicht mehr mit).
|
||||
hatch_id_str_quick = a.GetUserString(_FILL_KEY)
|
||||
owner_id_str_quick = a.GetUserString(_FILL_OWNER_KEY)
|
||||
if not hatch_id_str_quick and not owner_id_str_quick:
|
||||
return
|
||||
# Dossier-eigene Sources (wand_axis etc.) haben weder _FILL_KEY noch
|
||||
# _FILL_OWNER_KEY — die werden hier oben rausgekickt. User-Transform-
|
||||
# Skip war eigentlich nur fuer Dossier-Elemente gedacht; reine Hatch-
|
||||
# gekoppelte Polylinien brauchen die Sync auch waehrend _Move.
|
||||
# Reverse-Direction: Hatch verschoben/rotiert/skaliert → Curve mitnehmen.
|
||||
# Wir nehmen die Outer-Boundary direkt aus der (bereits transformed)
|
||||
# Hatch — funktioniert fuer Move, Rotate, Scale, beliebige Transforms.
|
||||
@@ -1470,10 +1478,6 @@ def _install_selection_listener(bridge):
|
||||
"""Wenn eine Curve geloescht wird, ihre gekoppelte Hatch mitloeschen.
|
||||
Wenn umgekehrt eine Hatch direkt geloescht wird, den Verweis auf der
|
||||
Curve aufraeumen damit beim naechsten Toggle keine Geister-Referenz steht."""
|
||||
# Waehrend User-Transform-Command: Rhino feuert Delete+Add fuer
|
||||
# transformierte Objekte. Curve→Hatch-Cascade hier wuerde die Hatch
|
||||
# killen obwohl sie gleich wieder benoetigt wird.
|
||||
if sc.sticky.get("_dossier_user_transform_active"): return
|
||||
if sc.sticky.get("_dossier_undo_active"): return
|
||||
if sc.sticky.get("_elemente_regen_busy"): return
|
||||
obj = args.TheObject
|
||||
@@ -1486,7 +1490,10 @@ def _install_selection_listener(bridge):
|
||||
return
|
||||
|
||||
# Schneller Bail-out: ohne Hatch-UserString interessiert uns das
|
||||
# Event nicht. Vermeidet Print-Spam fuer Wand-Sub-Volumen etc.
|
||||
# Event nicht. Vermeidet Print-Spam fuer Wand-Sub-Volumen etc. UND
|
||||
# filtert den user-transform-Pfad: nur Hatch-gekoppelte Objekte
|
||||
# brauchen die Sync (= Cascade-Delete + pending-Save fuer Recovery).
|
||||
# Wand-Volumen werden nicht beruehrt.
|
||||
try:
|
||||
hatch_id_str = attrs.GetUserString(_FILL_KEY)
|
||||
except Exception:
|
||||
@@ -1551,10 +1558,6 @@ def _install_selection_listener(bridge):
|
||||
- Wenn das Objekt eben gerade als Teil eines Drag/Move geloescht wurde,
|
||||
stellen wir die Hatch mit den gemerkten Metadaten wieder her.
|
||||
- Sonst pruefen wir ob die Ebene ein Auto-Fill konfiguriert hat."""
|
||||
# Waehrend User-Transform-Command: elemente uebernimmt Geometrie-Sync.
|
||||
# Auto-Fill hier wuerde unnoetige Hatches erzeugen weil das Objekt
|
||||
# bereits eine geerbte Fill-UserString hat (vom Delete+Add im Move).
|
||||
if sc.sticky.get("_dossier_user_transform_active"): return
|
||||
if sc.sticky.get("_dossier_undo_active"): return
|
||||
if sc.sticky.get("_elemente_regen_busy"): return
|
||||
obj = args.TheObject
|
||||
@@ -1565,6 +1568,9 @@ def _install_selection_listener(bridge):
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
|
||||
# 1) Drag-Recovery: Hatch-Metadaten wurden gerade in on_delete gespeichert?
|
||||
# MUSS auch waehrend User-Transform laufen (= das ist gerade DER Fall:
|
||||
# Rhino's Move feuert Delete+Add, on_delete hat pending gespeichert,
|
||||
# jetzt muss on_add die Hatch wiederherstellen).
|
||||
pending = _take_pending_hatch(obj.Id)
|
||||
if pending is not None:
|
||||
try:
|
||||
@@ -1580,7 +1586,10 @@ def _install_selection_listener(bridge):
|
||||
except Exception: pass
|
||||
return
|
||||
|
||||
# 2) Auto-Fill aus Ebenen-Definition
|
||||
# 2) Auto-Fill aus Ebenen-Definition — nur ausserhalb User-Transform.
|
||||
# Waehrend Move/Rotate werden Sub-Volumen erzeugt die kein Auto-Fill
|
||||
# brauchen, und elemente uebernimmt die Coupling.
|
||||
if sc.sticky.get("_dossier_user_transform_active"): return
|
||||
try:
|
||||
ok = _apply_ebene_fill(doc, obj)
|
||||
except Exception as ex:
|
||||
|
||||
Reference in New Issue
Block a user