From 944f2f701a21f521805dc638a7703d2a1026e44e Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sun, 16 Jul 2023 22:58:56 +1000 Subject: [PATCH] Fix #3288. Implement undo / redo until specified named transaction. Fix fundamental undo bug where Blender doesn't track the undo UUID property if you toggle edit mode. This also has the nice side effect of implementing "Jump to point in history" so you can now use the Edit > Undo History menu. --- src/blenderbim/blenderbim/bim/handler.py | 4 +-- src/blenderbim/blenderbim/bim/ifc.py | 34 +++++++++++++++++------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/handler.py b/src/blenderbim/blenderbim/bim/handler.py index c8147ac556..27e9f34c7a 100644 --- a/src/blenderbim/blenderbim/bim/handler.py +++ b/src/blenderbim/blenderbim/bim/handler.py @@ -209,7 +209,7 @@ def loadIfcStore(scene): def undo_post(scene): if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction: IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction - IfcStore.undo() + IfcStore.undo(until_key=bpy.context.scene.BIMProperties.last_transaction) purge_module_data() tool.Ifc.rebuild_element_maps() @@ -218,7 +218,7 @@ def undo_post(scene): def redo_post(scene): if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction: IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction - IfcStore.redo() + IfcStore.redo(until_key=bpy.context.scene.BIMProperties.last_transaction) purge_module_data() tool.Ifc.rebuild_element_maps() diff --git a/src/blenderbim/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py index 4104157c5f..c94fb009a3 100644 --- a/src/blenderbim/blenderbim/bim/ifc.py +++ b/src/blenderbim/blenderbim/bim/ifc.py @@ -366,21 +366,35 @@ class IfcStore: IfcStore.future = [] @staticmethod - def undo(): + def undo(until_key=None): BrickStore.undo() if not IfcStore.history: return - event = IfcStore.history.pop() - for transaction in event["operations"][::-1]: - transaction["rollback"](transaction["data"]) - IfcStore.future.append(event) + + while IfcStore.history: + if IfcStore.history[-1]["key"] == until_key: + return + + event = IfcStore.history.pop() + for transaction in event["operations"][::-1]: + transaction["rollback"](transaction["data"]) + IfcStore.future.append(event) @staticmethod - def redo(): + def redo(until_key=None): BrickStore.redo() + if not IfcStore.future: return - event = IfcStore.future.pop() - for transaction in event["operations"]: - transaction["commit"](transaction["data"]) - IfcStore.history.append(event) + + has_encountered_key = False + while IfcStore.future: + if has_encountered_key and IfcStore.future[-1]["key"] != until_key: + return + elif IfcStore.future[-1]["key"] == until_key: + has_encountered_key = True + + event = IfcStore.future.pop() + for transaction in event["operations"]: + transaction["commit"](transaction["data"]) + IfcStore.history.append(event)