Delete-Cascade in EINEN Undo-Record — Cmd+Z stellt Wand + Volumen wieder her
Bug: Bei Wand-Loeschen lief das Delete von wand_axis als Rhino-Undo-Record A,
unsere Idle-Cascade (Volume-Delete, Oeffnungs-Cleanup) lief 500 ms spaeter
in separaten Records B/C/D. Cmd+Z popte nur den letzten Record → nur das
Volume kam zurueck, oder umgekehrt nur die Achse.
Fix: BeginUndoRecord("Element-Loeschen") in _on_command_begin fuer Delete-
Cmds. _flush_pending_cascades_sync laeuft in _on_command_end SOFORT (kein
500-ms-Wait noetig — bei explizitem Delete kommt die Source nicht zurueck)
und WAEHREND der Record offen ist. EndUndoRecord schliesst den Record.
Resultat: Rhinos User-Delete + alle Cascade-Deletes = EIN Cmd+Z.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+87
-1
@@ -9519,6 +9519,65 @@ def _suppress_redraw_until_cmd_end():
|
||||
print("[ELEMENTE] suppress redraw:", ex)
|
||||
|
||||
|
||||
def _flush_pending_cascades_sync(doc):
|
||||
"""Verarbeitet die wand_cascade- und source_cascade-Queues SOFORT
|
||||
(ohne 500-ms-Wait). Aufgerufen aus _on_command_end fuer Delete-Cmds:
|
||||
der User hat explizit geloescht, die Source kommt nicht zurueck —
|
||||
also kein Grund zu warten. Vorteil: laeuft noch im selben Undo-Record
|
||||
wie Rhinos User-Delete → ein Cmd+Z stellt alles wieder her.
|
||||
"""
|
||||
pending_cascade = sc.sticky.get("_elemente_pending_wand_cascade")
|
||||
if isinstance(pending_cascade, dict) and pending_cascade:
|
||||
to_run = [(wid, info.get("openings", []))
|
||||
for wid, info in list(pending_cascade.items())]
|
||||
pending_cascade.clear()
|
||||
for wall_id, op_ids in to_run:
|
||||
still_there = False
|
||||
for obj in doc.Objects:
|
||||
m = _read_meta(obj)
|
||||
if m and m.get("id") == wall_id and m.get("type") == "wand_axis":
|
||||
still_there = True
|
||||
break
|
||||
if still_there: continue
|
||||
_was = sc.sticky.get(_REGEN_BUSY, False)
|
||||
sc.sticky[_REGEN_BUSY] = True
|
||||
try:
|
||||
for op_id in op_ids:
|
||||
for vol_obj in _find_all_volumes(doc, op_id):
|
||||
try: doc.Objects.Delete(vol_obj.Id, True)
|
||||
except Exception: pass
|
||||
for obj, _m in _find_objects_by_wall_id(doc, op_id):
|
||||
if _m.get("type") == "oeffnung_point":
|
||||
try: doc.Objects.Delete(obj.Id, True)
|
||||
except Exception: pass
|
||||
finally:
|
||||
sc.sticky[_REGEN_BUSY] = _was
|
||||
|
||||
pending_src = sc.sticky.get("_elemente_pending_source_cascade")
|
||||
if isinstance(pending_src, dict) and pending_src:
|
||||
to_run_src = list(pending_src.items())
|
||||
pending_src.clear()
|
||||
for src_id, info in to_run_src:
|
||||
still_there = False
|
||||
for obj in doc.Objects:
|
||||
m = _read_meta(obj)
|
||||
if m and m.get("id") == src_id and m.get("type") == info.get("type"):
|
||||
still_there = True
|
||||
break
|
||||
if still_there: continue
|
||||
_was = sc.sticky.get(_REGEN_BUSY, False)
|
||||
sc.sticky[_REGEN_BUSY] = True
|
||||
try:
|
||||
for vol_id in info.get("volumes", []):
|
||||
try: doc.Objects.Delete(vol_id, True)
|
||||
except Exception: pass
|
||||
finally:
|
||||
sc.sticky[_REGEN_BUSY] = _was
|
||||
parent_id = info.get("parent")
|
||||
if parent_id:
|
||||
_queue_regen(parent_id)
|
||||
|
||||
|
||||
def _on_command_begin(sender, e):
|
||||
try:
|
||||
name = getattr(e, "CommandEnglishName", "") or ""
|
||||
@@ -9541,6 +9600,16 @@ def _on_command_begin(sender, e):
|
||||
sc.sticky["_dossier_bulk_redraw_prev"] = bool(doc.Views.RedrawEnabled)
|
||||
doc.Views.RedrawEnabled = False
|
||||
except Exception: pass
|
||||
# Undo-Record umschliesst Rhinos User-Delete + unsere Cascade
|
||||
# (Volume-Delete, Oeffnungs-Delete) in EINEM Cmd+Z-Schritt.
|
||||
# Sonst bleibt nach Cmd+Z nur die Achse uebrig (Volumen kamen aus
|
||||
# separatem Idle-Record und der hatte schon gepop't).
|
||||
try:
|
||||
serial = doc.BeginUndoRecord("Element-Loeschen")
|
||||
sc.sticky["_dossier_bulk_undo_serial"] = serial
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] bulk undo record begin:", ex)
|
||||
sc.sticky["_dossier_bulk_undo_serial"] = None
|
||||
return
|
||||
# Diagnose: andere Commands sehen wir hier vorbeiziehen — wenn _Delete
|
||||
# einen anderen Namen hat als 'Delete', sehen wir's und koennen den
|
||||
@@ -9570,9 +9639,26 @@ def _on_command_end(sender, e):
|
||||
# refresh ans Gestaltung-Panel.
|
||||
if sc.sticky.get(_BULK_ACTIVE_KEY):
|
||||
sc.sticky[_BULK_ACTIVE_KEY] = None
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
# Cascade synchron flushen WAEHREND der Undo-Record noch offen ist
|
||||
# und RedrawEnabled noch False ist (kein Flicker, ein Cmd+Z fuer
|
||||
# alles). Nur fuer Delete-Cmds relevant — andere Bulk-Cmds queuen
|
||||
# nichts.
|
||||
try:
|
||||
if doc is not None:
|
||||
_flush_pending_cascades_sync(doc)
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] bulk cascade flush:", ex)
|
||||
# Undo-Record schliessen — alles seit BeginUndoRecord (User-Delete +
|
||||
# Cascade) wird als EIN Cmd+Z behandelt.
|
||||
try:
|
||||
serial = sc.sticky.pop("_dossier_bulk_undo_serial", None)
|
||||
if serial is not None and doc is not None:
|
||||
doc.EndUndoRecord(serial)
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] bulk undo record end:", ex)
|
||||
try:
|
||||
prev = sc.sticky.pop("_dossier_bulk_redraw_prev", True)
|
||||
doc = Rhino.RhinoDoc.ActiveDoc
|
||||
if doc is not None:
|
||||
doc.Views.RedrawEnabled = prev
|
||||
doc.Views.Redraw()
|
||||
|
||||
Reference in New Issue
Block a user