From 72e24fd5122ac7b0981d27c24c2e7780627fe41e Mon Sep 17 00:00:00 2001 From: karim Date: Wed, 20 May 2026 02:46:21 +0200 Subject: [PATCH] =?UTF-8?q?Bulk-Op=20Bail-out=20per=20Objekt-Typ=20statt?= =?UTF-8?q?=20global=20=E2=80=94=20DOSSIER-Cascade=20bleibt=20aktiv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regression vom letzten Commit: _on_object_deleted und gestaltung.on_delete bailten KOMPLETT bei Bulk-Ops. Damit liefen Cascade-Cleanups nicht mehr: - Wand-Achse geloescht → Wand-Volumen blieb orphaned - Oeffnungs-Punkt geloescht → Loch in Wand verschwand nicht - Curve mit Hatch geloescht → Hatch blieb als Geist liegen Fix: Schnellfilter per UserString-Lookup VOR dem Bail. - elemente._on_object_deleted: GetUserString(_KEY_TYPE) — nur DOSSIER- Sources triggern Cascade. OSM/Swisstopo-Curves haben keinen Type → cheap exit, kein per-Event-Overhead. Bulk-Bail entfernt. - gestaltung.on_delete: bestehender _FILL_KEY/_FILL_OWNER_KEY-Check (line 1540-1548) filtert non-Hatch-Objekte schon billig. Bulk-Bail entfernt. Panel-Sync optimiert: _send_state aus on_object_deleted unterdrueckt waehrend Bulk, einmaliger Push aus _on_command_end. Co-Authored-By: Claude Opus 4.7 --- rhino/elemente.py | 26 +++++++++++++++++++++----- rhino/gestaltung.py | 11 +++++------ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/rhino/elemente.py b/rhino/elemente.py index 4b8de18..31e2434 100644 --- a/rhino/elemente.py +++ b/rhino/elemente.py @@ -8975,9 +8975,6 @@ def _on_object_deleted(sender, e): """ # Waehrend Swisstopo-Import: keine DOSSIER-Metas vorhanden, nur Overhead if sc.sticky.get("dossier_swisstopo_busy"): return - # Bulk-Delete (z.B. SelAll + Delete bei 6000 OSM-Curves): pro-Event- - # Arbeit waere reiner Overhead. CommandEnd refresht einmalig. - if sc.sticky.get(_BULK_ACTIVE_KEY): return # Waehrend Move/Rotate/Mirror/Scale: CommandEnd-Pfad uebernimmt das # Re-Sync. Sonst queued der Delete-Event ueberfluessige Regen-Calls die # den Pure-Translate-Skip wieder zunichtemachen. @@ -8987,6 +8984,18 @@ def _on_object_deleted(sender, e): if sc.sticky.get(_UNDO_ACTIVE_KEY): return try: obj = e.TheObject + # Schneller Filter: ohne DOSSIER-Type-UserString gibt es nichts zu + # cascaden. Greift fuer OSM-Curves, Swisstopo-Geometrie, importierte + # Linien etc. → kein per-Event-Overhead bei Bulk-Delete mit 6000 + # Fremd-Objekten. Wand-Achsen/Oeffnungs-Punkte/etc behalten ihre + # Cascade auch waehrend Bulk-Ops, sonst zerfaellt die Verknuepfung + # (Volumen orphaned, Oeffnungen in Wand bleiben liegen). + try: + _type_quick = obj.Attributes.GetUserString(_KEY_TYPE) + except Exception: + _type_quick = None + if not _type_quick: + return meta = _read_meta(obj) if meta and meta.get("type") in SOURCE_TYPES: doc = Rhino.RhinoDoc.ActiveDoc @@ -9048,8 +9057,11 @@ def _on_object_deleted(sender, e): _queue_regen(wid) except Exception as ex: print("[ELEMENTE] del dep regen:", ex) - b = sc.sticky.get("elemente_bridge") - if b is not None: b._send_state() + # Panel-Sync: bei Bulk-Op nur einmal am CommandEnd, sonst + # sofort. Sonst pusht ein Delete von 50 Waenden 50× state. + if not sc.sticky.get(_BULK_ACTIVE_KEY): + b = sc.sticky.get("elemente_bridge") + if b is not None: b._send_state() except Exception as ex: print("[ELEMENTE] on_object_deleted:", ex) @@ -9565,6 +9577,10 @@ def _on_command_end(sender, e): doc.Views.RedrawEnabled = prev doc.Views.Redraw() except Exception: pass + eb = sc.sticky.get("elemente_bridge") + if eb is not None: + try: eb._send_state() + except Exception: pass gb = sc.sticky.get("gestaltung_bridge") if gb is not None: try: gb._send_selection() diff --git a/rhino/gestaltung.py b/rhino/gestaltung.py index 996b24b..fc7ab61 100644 --- a/rhino/gestaltung.py +++ b/rhino/gestaltung.py @@ -1517,12 +1517,11 @@ def _install_selection_listener(bridge): Curve aufraeumen damit beim naechsten Toggle keine Geister-Referenz steht.""" if sc.sticky.get("_dossier_undo_active"): return if sc.sticky.get("_elemente_regen_busy"): return - # Bulk-Delete (SelAll + Delete): pro-Object Hatch-Sync ueberspringen - # — bei 6000 Objekten waere das massive Overhead. Hatch-Verweise - # wuerden zwar nicht aufgeraeumt aber das ist tolerierbar - # (Sticky-Cache laeuft auch ohne Cleanup ab, alte Eintraege bleiben - # nur unsichtbar liegen). - if sc.sticky.get("_dossier_bulk_op_active"): return + # Bulk-Op (SelAll + Delete): KEIN frueher Bail — der UserString- + # Schnellcheck unten (kein _FILL_KEY/_FILL_OWNER_KEY → return) + # filtert OSM/Swisstopo-Curves billig raus. Hatch-gekoppelte Curves + # MUESSEN ihre Hatch mitnehmen, sonst bleiben Geister-Hatches + # liegen (Curve+Hatch zerfallen als Einheit). obj = args.TheObject if obj is None or obj.Id in _processing: return