mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 08:02:29 +00:00
Improve undo redo object linking robustness. See #1475.
This commit is contained in:
@@ -110,7 +110,9 @@ if bpy is not None:
|
|||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
bpy.app.handlers.depsgraph_update_post.append(on_register)
|
bpy.app.handlers.depsgraph_update_post.append(on_register)
|
||||||
|
bpy.app.handlers.undo_pre.append(handler.undo_pre)
|
||||||
bpy.app.handlers.undo_post.append(handler.undo_post)
|
bpy.app.handlers.undo_post.append(handler.undo_post)
|
||||||
|
bpy.app.handlers.redo_pre.append(handler.redo_pre)
|
||||||
bpy.app.handlers.redo_post.append(handler.redo_post)
|
bpy.app.handlers.redo_post.append(handler.redo_post)
|
||||||
bpy.app.handlers.load_post.append(handler.setDefaultProperties)
|
bpy.app.handlers.load_post.append(handler.setDefaultProperties)
|
||||||
bpy.app.handlers.load_post.append(handler.loadIfcStore)
|
bpy.app.handlers.load_post.append(handler.loadIfcStore)
|
||||||
|
|||||||
@@ -114,12 +114,23 @@ def loadIfcStore(scene):
|
|||||||
purge_module_data()
|
purge_module_data()
|
||||||
|
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def undo_pre(scene):
|
||||||
|
IfcStore.update_undo_redo_stack_objects()
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
def undo_post(scene):
|
def undo_post(scene):
|
||||||
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
||||||
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
||||||
IfcStore.undo()
|
IfcStore.undo()
|
||||||
IfcStore.reload_linked_elements(should_reload_selected=True)
|
IfcStore.update_undo_redo_stack_objects()
|
||||||
|
IfcStore.reload_linked_elements(objects=[bpy.data.objects.get(o) for o in IfcStore.undo_redo_stack_objects])
|
||||||
|
|
||||||
|
|
||||||
|
@persistent
|
||||||
|
def redo_pre(scene):
|
||||||
|
IfcStore.update_undo_redo_stack_objects()
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
@@ -127,7 +138,8 @@ def redo_post(scene):
|
|||||||
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
||||||
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
||||||
IfcStore.redo()
|
IfcStore.redo()
|
||||||
IfcStore.reload_linked_elements(should_reload_selected=True)
|
IfcStore.update_undo_redo_stack_objects()
|
||||||
|
IfcStore.reload_linked_elements(objects=[bpy.data.objects.get(o) for o in IfcStore.undo_redo_stack_objects])
|
||||||
|
|
||||||
|
|
||||||
@persistent
|
@persistent
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class IfcStore:
|
|||||||
library_path = ""
|
library_path = ""
|
||||||
library_file = None
|
library_file = None
|
||||||
element_listeners = set()
|
element_listeners = set()
|
||||||
|
undo_redo_stack_objects = set()
|
||||||
current_transaction = ""
|
current_transaction = ""
|
||||||
last_transaction = ""
|
last_transaction = ""
|
||||||
history = []
|
history = []
|
||||||
@@ -70,19 +71,36 @@ class IfcStore:
|
|||||||
def add_element_listener(callback):
|
def add_element_listener(callback):
|
||||||
IfcStore.element_listeners.add(callback)
|
IfcStore.element_listeners.add(callback)
|
||||||
|
|
||||||
|
"""Keeps track of selected object names, typically during undo and redo
|
||||||
|
|
||||||
|
When any Blender object is stored outside a Blender PointerProperty, such as
|
||||||
|
in a regular Python list, there is the likely probability that the object
|
||||||
|
will be invalidated when undo or redo occurs. Object invalidation seems to
|
||||||
|
only occur for selected objects either pre/post undo/redo event, including
|
||||||
|
selected objects for consecutive undo/redos.
|
||||||
|
|
||||||
|
So if I first select o1, then o2, then o3, then press undo, o3 will be
|
||||||
|
invalidated. If instead I press undo twice, o3 and o2 will be invalidated.
|
||||||
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def reload_linked_elements(should_reload_selected=False):
|
def update_undo_redo_stack_objects():
|
||||||
|
if bpy.context.active_object:
|
||||||
|
objects = set([o.name for o in bpy.context.selected_objects + [bpy.context.active_object]])
|
||||||
|
else:
|
||||||
|
objects = set([o.name for o in bpy.context.selected_objects])
|
||||||
|
IfcStore.undo_redo_stack_objects |= objects
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def reload_linked_elements(objects=None):
|
||||||
file = IfcStore.get_file()
|
file = IfcStore.get_file()
|
||||||
if not file:
|
if not file:
|
||||||
return
|
return
|
||||||
if should_reload_selected:
|
if objects is None:
|
||||||
objects = bpy.context.selected_objects
|
|
||||||
if bpy.context.active_object:
|
|
||||||
objects += [bpy.context.active_object]
|
|
||||||
else:
|
|
||||||
objects = bpy.data.objects
|
objects = bpy.data.objects
|
||||||
|
|
||||||
for obj in objects:
|
for obj in objects:
|
||||||
|
if not obj:
|
||||||
|
continue
|
||||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||||
continue
|
continue
|
||||||
element = file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
element = file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||||
@@ -183,6 +201,7 @@ class IfcStore:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def begin_transaction(operator):
|
def begin_transaction(operator):
|
||||||
|
IfcStore.undo_redo_stack_objects = set()
|
||||||
IfcStore.current_transaction = str(uuid.uuid4())
|
IfcStore.current_transaction = str(uuid.uuid4())
|
||||||
operator.transaction_key = IfcStore.current_transaction
|
operator.transaction_key = IfcStore.current_transaction
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user