Undo block

Hi,

I’m trying to create an operators that does a bunch of operations and undo them all at the end.
The operations looks like delete some UV channels on selected objects, export them, restore UVs.

I found the method bpy.ops.ed.undo_push, but I can’t get it to do anything.

Example of what I’m trying to do:

import bpy
from ...libs.selection import Selection


class EXPORT_OT_test(bpy.types.Operator):
    bl_idname = "exporter.test"
    bl_label = "test"
    bl_description = "test"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):

        bpy.ops.ed.undo_push(message='Add Undo State')

        objs = Selection.get_selected_objects()

        for obj in objs:
            for i in range(10):
                print("Move!")
                obj.location.x += 1

        bpy.ops.ed.undo()

        return {'FINISHED'}

Anyone knows how this works?
Thanks!

        bpy.ops.ed.undo()

        return {'FINISHED'}

        return {'PASS_THROUGH'}

You might need to add return {"PASS_THROUGH"} at the end of your code. Or outside of the function.

Also, don’t you need to add a run function for your class function?

if __name__ == '__main__':
  execute(self, context)

Didn’t change anything with return {"PASS_THROUGH"}

The operator is launched from a panel, so I don’t need the if __name__ == '__main__' part, but tried with it anyway, didn’t change anything either.

so the objects get moved, but no undo is executed after.

I’m curious why you’re bothering with Undo at all- if your goal is just to export UVs, you don’t need to delete and restore anything

no, I don’t want to export the UVs.
My goal is to export the mesh in fbx format without some UV layers.
So I need to delete those layers, export the mesh then restore the UV layers.

I could save the file before the export and then reload, but I would like to avoid this if possible.

In that case, you still don’t need to undo. You can cache the mesh with UV layers in your code to a variable, remove the UV layers from the copy, and export.

Pseudo-code:

new_mesh= <object>.copy()
export(new_mesh)

Relying on undo is bad practice, you’re doing a destructive operation and hoping the RAM will fix everything. If there’s a corruption in the RAM, if Blender crashes, etc, the UV layers are permanently gone.

Copying the mesh data is a non-destructive action, even if something goes wrong, the original mesh is unaffected

2 Likes

yeah I agree with you that undo wasn’t the best idea, making a copy is way better.

That being said, I don’t see it appearing in the outliner after I do the copy, I will need to investigate this more.

thanks for the idea though! :slight_smile:

A copied object doesn’t appear in the outliner until you assign it to a collection and, IIRC, a scene :slight_smile:

ok yes, I got it working the way I want now. Just have to deal with the naming of the duplicates.

Thanks again!

1 Like