Changing parameters of operators that manipulate a mesh

Hi, all.

I was under impression when I change the values of properties of operator, every time the operator is executed it runs on a snapshot of the mesh that was taken when the operator was invoked.

For instance, my operator manipulates the mesh, extrudes it and assigns values to custom properties via layers. As I see it, every time I change the property value, the operator is applied to the mesh that was changed by previous execution of the operator. Perhaps it has something to do with manipulating the mesh via bmesh.

Long story short, this is more or less what I do:


        if bpy.context.mode != 'EDIT':
            bpy.ops.object.mode_set(mode = 'EDIT')

        mesh = bmesh.from_edit_mesh(context.active_object.data)
        fieldTypeLayer = mesh.faces.layers.int.get(pu.fieldTypeLayerName)

        for face in mesh.faces:
            face[fieldTypeLayer] = somealue
        
        extrudeVector = somevalue

        bpy.ops.mesh.extrude_region_move(params)

        bmesh.update_edit_mesh(context.active_object.data)


So basically, do I need to save a snapshot of a mesh on operator invoke and then before each execution restore our mesh from it, or am I missing something and blender is supposed to do it for me?

If you run operators with Redo support in the UI, the operator properties will show up in the Redo panel. On every change to these properties, the operation is reverted and re-executed with the new parameters (can’t tell you whether a snapshot technically exists though, but I would say yes).

If your own operator has the ‘REDO’ option set, an undo step should automatically be pushed to the stack. Otherwise you would need to push manually.

I had some read about how operators are executed, and so far I can’t understand how my operator is different. Perhaps it’s the way I update my edit mesh with bmesh, not sure.


bl_options = {'REGISTER', 'UNDO', 'PRESET'}

This is how my operator defined, that’s how all of my operators are defined, and all of them actually revert the mesh before executing the operator again. So your suggestions is to add ‘REDO’ to bl_options?

Never mind, it’s actually ‘UNDO’ - it’s kinda both. Undo support needs to be enabled in order to support the Redo functionality.

Note that you need to use operator properties and run the operator via a button, shortcut or spacebar menu. It won’t work (nothing shown in Redo panel) if you execute the operator from Text Editor or Python console. The entire operator will be re-run as you change properties in the redo panel via mouse drag or keyboard input - regardless of other operators that might be called inside your operator.

The operator is running from a menu item.

This is very weird, I’ll check the redo panel while executing the operator, or try to strip the code down, til I get to the root of the problem.

Thanks.

What happens if you undo your operator after execution? Does it return to the prior state, further back than that or not at all?

This is quite interesting!

I can’t undo the operation. I’ve started following the undo history and this is what I’ve found.

Undo history before running the operator:


After I run the problematic operator:


So for some reason, running the operator resets the undo history!

I’ll keep digging into it to find out what does that.

Well, if I remove this code from the very start of the operator, this doesn’t happen.


        if bpy.context.mode != 'EDIT':
            bpy.ops.object.mode_set(mode = 'EDIT')

No idea how switching to edit mode can mess up undo history.

For some reason links to images got invalid, uploaded new ones.

Well, there a different undo stacks for different modes. Is the mode switch really necessary or can you make it a pre-condition in a poll-check?

That explains alot. Yes, I can definitely make the operator mode sensitive and allow it running only in edit mode.

Thanks, codeman :slight_smile: