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)
|
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):
|
def _on_command_begin(sender, e):
|
||||||
try:
|
try:
|
||||||
name = getattr(e, "CommandEnglishName", "") or ""
|
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)
|
sc.sticky["_dossier_bulk_redraw_prev"] = bool(doc.Views.RedrawEnabled)
|
||||||
doc.Views.RedrawEnabled = False
|
doc.Views.RedrawEnabled = False
|
||||||
except Exception: pass
|
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
|
return
|
||||||
# Diagnose: andere Commands sehen wir hier vorbeiziehen — wenn _Delete
|
# Diagnose: andere Commands sehen wir hier vorbeiziehen — wenn _Delete
|
||||||
# einen anderen Namen hat als 'Delete', sehen wir's und koennen den
|
# 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.
|
# refresh ans Gestaltung-Panel.
|
||||||
if sc.sticky.get(_BULK_ACTIVE_KEY):
|
if sc.sticky.get(_BULK_ACTIVE_KEY):
|
||||||
sc.sticky[_BULK_ACTIVE_KEY] = None
|
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:
|
try:
|
||||||
prev = sc.sticky.pop("_dossier_bulk_redraw_prev", True)
|
prev = sc.sticky.pop("_dossier_bulk_redraw_prev", True)
|
||||||
doc = Rhino.RhinoDoc.ActiveDoc
|
|
||||||
if doc is not None:
|
if doc is not None:
|
||||||
doc.Views.RedrawEnabled = prev
|
doc.Views.RedrawEnabled = prev
|
||||||
doc.Views.Redraw()
|
doc.Views.Redraw()
|
||||||
|
|||||||
Reference in New Issue
Block a user