To the point:
Bug report Creating Lattice object with script with {“REGISTER”, “UNDO”} if parameters was changed in Undo window and mesh was in Edit mode - undo last changes to the mesh or last action
This could be the known issue, but I need a workaround.
Video from bugreport
The code (as I can't upload file)
import bpy
class TEST_OT_register_undo(bpy.types.Operator):
bl_idname = "test.register_undo"
bl_label = "Register Undo"
bl_description = "Some description."
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_options = {"REGISTER", "UNDO"}
orientation_types = (('GLOBAL', 'Global', ''),
('LOCAL', 'Local', ''),
('CURSOR', 'Cursor', ''))
orientation: bpy.props.EnumProperty(
name="Orientation", items=orientation_types, default='LOCAL')
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(self, "orientation", text="Orientation", expand=True)
@classmethod
def poll(self, context):
# Checks for mesh in edit mode
active_object = context.active_object
return active_object is not None and active_object.type == 'MESH' and active_object.mode == "EDIT"
def execute(self, context):
self.createLattice(context)
if self.orientation == 'GLOBAL':
bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL'
elif self.orientation == 'LOCAL':
bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL'
elif self.orientation == 'CURSOR':
bpy.context.scene.transform_orientation_slots[0].type = 'CURSOR'
return {'FINISHED'}
def createLattice(self, context):
object_active = bpy.context.view_layer.objects.active
lattice_data = bpy.data.lattices.new('SimpleLattice')
lattice_obj = bpy.data.objects.new(object_active.name + '_SimpleLattice', lattice_data)
context.scene.collection.objects.link(lattice_obj)
return lattice_obj
classes = (
TEST_OT_register_undo,
)
def register():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
if __name__ == "__main__":
register()
For now I only have a “solution” how to force it by copying selected objects and deleting them, and then selecting originals with bpy.ops.ed.undo_push() at the end, and only after this actions, mesh data stay untouched.
See def for_edit_mode (self, context):
Updated code
import bpy
class TEST_OT_register_undo(bpy.types.Operator):
bl_idname = "test.register_undo"
bl_label = "Register Undo"
bl_description = "Some description."
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_options = {"REGISTER", "UNDO"}
orientation_types = (('GLOBAL', 'Global', ''),
('LOCAL', 'Local', ''),
('CURSOR', 'Cursor', ''))
orientation: bpy.props.EnumProperty(
name="Orientation", items=orientation_types, default='LOCAL')
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(self, "orientation", text="Orientation", expand=True)
@classmethod
def poll(self, context):
# Checks for mesh in edit mode
active_object = context.active_object
return active_object is not None and active_object.type == 'MESH' and active_object.mode == "EDIT"
def execute(self, context):
self.for_edit_mode(context)
self.createLattice(context)
if self.orientation == 'GLOBAL':
bpy.context.scene.transform_orientation_slots[0].type = 'GLOBAL'
elif self.orientation == 'LOCAL':
bpy.context.scene.transform_orientation_slots[0].type = 'LOCAL'
elif self.orientation == 'CURSOR':
bpy.context.scene.transform_orientation_slots[0].type = 'CURSOR'
return {'FINISHED'}
def createLattice(self, context):
object_active = bpy.context.view_layer.objects.active
lattice_data = bpy.data.lattices.new('SimpleLattice')
lattice_obj = bpy.data.objects.new(object_active.name + '_SimpleLattice', lattice_data)
context.scene.collection.objects.link(lattice_obj)
return lattice_obj
def for_edit_mode (self, context):
active_object = context.view_layer.objects.active
if active_object.mode == "EDIT":
objects_originals = context.selected_objects
bpy.ops.object.mode_set(mode = 'OBJECT')
bpy.ops.object.duplicate()
objects_duplicated = context.selected_objects
# removing objects with its data
for obj in objects_duplicated:
purge_data = [o.data for o in context.selected_objects if o.data]
bpy.data.batch_remove(context.selected_objects)
bpy.data.batch_remove([o for o in purge_data if not o.users])
for obj in objects_originals:
obj.select_set(True)
context.view_layer.objects.active = active_object
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.ed.undo_push()
classes = (
TEST_OT_register_undo,
)
def register():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister():
from bpy.utils import unregister_class
for cls in reversed(classes):
unregister_class(cls)
if __name__ == "__main__":
register()
My skills and knowledge do not allow me to think globally,
so maybe some one have a better idea how to do this?