Implement undo for pset template operators. See #1475.

This commit is contained in:
Dion Moult
2021-07-06 14:21:02 +10:00
parent 597b5ffbd6
commit 32e7083e21
4 changed files with 123 additions and 26 deletions
+2
View File
@@ -124,6 +124,7 @@ 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()
purge_module_data()
IfcStore.update_undo_redo_stack_objects()
IfcStore.reload_linked_elements(objects=[bpy.data.objects.get(o) for o in IfcStore.undo_redo_stack_objects])
@@ -138,6 +139,7 @@ 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()
purge_module_data()
IfcStore.update_undo_redo_stack_objects()
IfcStore.reload_linked_elements(objects=[bpy.data.objects.get(o) for o in IfcStore.undo_redo_stack_objects])
+12 -22
View File
@@ -71,19 +71,19 @@ class IfcStore:
def add_element_listener(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
def update_undo_redo_stack_objects():
"""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.
"""
if bpy.context.active_object:
objects = set([o.name for o in bpy.context.selected_objects + [bpy.context.active_object]])
else:
@@ -183,22 +183,12 @@ class IfcStore:
if is_top_level_operator:
IfcStore.get_file().end_transaction()
IfcStore.add_transaction_operation(
operator, rollback=IfcStore.rollback_ifc_operator, commit=IfcStore.commit_ifc_operator
operator, rollback=lambda d: IfcStore.get_file().undo(), commit=lambda d: IfcStore.get_file().redo()
)
IfcStore.end_transaction(operator)
return result
@staticmethod
def rollback_ifc_operator(data):
IfcStore.get_file().undo()
blenderbim.bim.handler.purge_module_data()
@staticmethod
def commit_ifc_operator(data):
IfcStore.get_file().redo()
blenderbim.bim.handler.purge_module_data()
@staticmethod
def begin_transaction(operator):
IfcStore.undo_redo_stack_objects = set()
@@ -64,10 +64,8 @@ class CreateProject(bpy.types.Operator):
def rollback(self, data):
IfcStore.file = None
blenderbim.bim.handler.purge_module_data()
def commit(self, data):
blenderbim.bim.handler.purge_module_data()
IfcStore.file = data["file"]
@@ -106,10 +104,8 @@ class CreateProjectLibrary(bpy.types.Operator):
def rollback(self, data):
IfcStore.file = None
blenderbim.bim.handler.purge_module_data()
def commit(self, data):
blenderbim.bim.handler.purge_module_data()
IfcStore.file = data["file"]
@@ -121,10 +117,12 @@ class SelectLibraryFile(bpy.types.Operator):
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
def execute(self, context):
IfcStore.begin_transaction(self)
old_filepath = IfcStore.library_path
result = self._execute(context)
self.transaction_data = {"old_filepath": old_filepath, "filepath": self.filepath}
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
@@ -229,10 +227,12 @@ class AssignLibraryDeclaration(bpy.types.Operator):
definition: bpy.props.IntProperty()
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.library_file.begin_transaction()
result = self._execute(context)
IfcStore.library_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
@@ -263,10 +263,12 @@ class UnassignLibraryDeclaration(bpy.types.Operator):
definition: bpy.props.IntProperty()
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.library_file.begin_transaction()
result = self._execute(context)
IfcStore.library_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
@@ -378,11 +380,13 @@ class EditHeader(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
IfcStore.begin_transaction(self)
self.transaction_data = {}
self.transaction_data["old"] = self.record_state()
result = self._execute(context)
self.transaction_data["new"] = self.record_state()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
@@ -9,20 +9,46 @@ from blenderbim.bim.ifc import IfcStore
class AddPsetTemplate(bpy.types.Operator):
bl_idname = "bim.add_pset_template"
bl_label = "Add Pset Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.pset_template_file.begin_transaction()
result = self._execute(context)
IfcStore.pset_template_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
ifcopenshell.api.run("pset_template.add_pset_template", IfcStore.pset_template_file)
Data.load(IfcStore.pset_template_file)
updatePsetTemplates(self, context)
return {"FINISHED"}
def rollback(self, data):
IfcStore.pset_template_file.undo()
def commit(self, data):
IfcStore.pset_template_file.redo()
class RemovePsetTemplate(bpy.types.Operator):
bl_idname = "bim.remove_pset_template"
bl_label = "Remove Pset Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.pset_template_file.begin_transaction()
result = self._execute(context)
IfcStore.pset_template_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
if props.active_pset_template_id == int(props.pset_templates):
bpy.ops.bim.disable_editing_pset_template()
@@ -33,10 +59,17 @@ class RemovePsetTemplate(bpy.types.Operator):
updatePsetTemplates(self, context)
return {"FINISHED"}
def rollback(self, data):
IfcStore.pset_template_file.undo()
def commit(self, data):
IfcStore.pset_template_file.redo()
class EnableEditingPsetTemplate(bpy.types.Operator):
bl_idname = "bim.enable_editing_pset_template"
bl_label = "Enable Editing Pset Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
@@ -53,6 +86,7 @@ class EnableEditingPsetTemplate(bpy.types.Operator):
class DisableEditingPsetTemplate(bpy.types.Operator):
bl_idname = "bim.disable_editing_pset_template"
bl_label = "Disable Editing Pset Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
@@ -63,6 +97,7 @@ class DisableEditingPsetTemplate(bpy.types.Operator):
class EnableEditingPropTemplate(bpy.types.Operator):
bl_idname = "bim.enable_editing_prop_template"
bl_label = "Enable Editing Prop Template"
bl_options = {"REGISTER", "UNDO"}
prop_template: bpy.props.IntProperty()
def execute(self, context):
@@ -78,6 +113,7 @@ class EnableEditingPropTemplate(bpy.types.Operator):
class DisableEditingPropTemplate(bpy.types.Operator):
bl_idname = "bim.disable_editing_prop_template"
bl_label = "Disable Editing Prop Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = context.scene.BIMPsetTemplateProperties
@@ -88,8 +124,18 @@ class DisableEditingPropTemplate(bpy.types.Operator):
class EditPsetTemplate(bpy.types.Operator):
bl_idname = "bim.edit_pset_template"
bl_label = "Edit Pset Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.pset_template_file.begin_transaction()
result = self._execute(context)
IfcStore.pset_template_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
ifcopenshell.api.run("pset_template.edit_pset_template", IfcStore.pset_template_file, **{
"pset_template": IfcStore.pset_template_file.by_id(props.active_pset_template_id),
@@ -105,6 +151,13 @@ class EditPsetTemplate(bpy.types.Operator):
bpy.ops.bim.disable_editing_pset_template()
return {"FINISHED"}
def rollback(self, data):
IfcStore.pset_template_file.undo()
def commit(self, data):
IfcStore.pset_template_file.redo()
class SavePsetTemplateFile(bpy.types.Operator):
bl_idname = "bim.save_pset_template_file"
@@ -118,8 +171,18 @@ class SavePsetTemplateFile(bpy.types.Operator):
class AddPropTemplate(bpy.types.Operator):
bl_idname = "bim.add_prop_template"
bl_label = "Add Prop Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.pset_template_file.begin_transaction()
result = self._execute(context)
IfcStore.pset_template_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
pset_template_id = props.active_pset_template_id or int(props.pset_templates)
ifcopenshell.api.run("pset_template.add_prop_template", IfcStore.pset_template_file, **{
@@ -128,13 +191,29 @@ class AddPropTemplate(bpy.types.Operator):
Data.load(IfcStore.pset_template_file)
return {"FINISHED"}
def rollback(self, data):
IfcStore.pset_template_file.undo()
def commit(self, data):
IfcStore.pset_template_file.redo()
class RemovePropTemplate(bpy.types.Operator):
bl_idname = "bim.remove_prop_template"
bl_label = "Remove Prop Template"
bl_options = {"REGISTER", "UNDO"}
prop_template: bpy.props.IntProperty()
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.pset_template_file.begin_transaction()
result = self._execute(context)
IfcStore.pset_template_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
ifcopenshell.api.run("pset_template.remove_prop_template", IfcStore.pset_template_file, **{
"prop_template": IfcStore.pset_template_file.by_id(self.prop_template)
@@ -142,12 +221,28 @@ class RemovePropTemplate(bpy.types.Operator):
Data.load(IfcStore.pset_template_file)
return {"FINISHED"}
def rollback(self, data):
IfcStore.pset_template_file.undo()
def commit(self, data):
IfcStore.pset_template_file.redo()
class EditPropTemplate(bpy.types.Operator):
bl_idname = "bim.edit_prop_template"
bl_label = "Edit Prop Template"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.pset_template_file.begin_transaction()
result = self._execute(context)
IfcStore.pset_template_file.end_transaction()
IfcStore.add_transaction_operation(self)
IfcStore.end_transaction(self)
return result
def _execute(self, context):
props = context.scene.BIMPsetTemplateProperties
ifcopenshell.api.run("pset_template.edit_prop_template", IfcStore.pset_template_file, **{
"prop_template": IfcStore.pset_template_file.by_id(props.active_prop_template_id),
@@ -160,3 +255,9 @@ class EditPropTemplate(bpy.types.Operator):
Data.load(IfcStore.pset_template_file)
bpy.ops.bim.disable_editing_prop_template()
return {"FINISHED"}
def rollback(self, data):
IfcStore.pset_template_file.undo()
def commit(self, data):
IfcStore.pset_template_file.redo()