How to undo a python script

pymel

#1

Select polygonal edges, run:

def run():
    listEdges = pm.ls(sl = 1, flatten=True)
    pm.polyDuplicateEdge(listEdges, splitType=0, offset=0.1)

run()

Then run:

pm.undo()

And get the error: # Error: line 1: RuntimeError: file C:\pmcmds.py line 133: Undo is temporarily unavailable. Try exiting the current tool.

While if you press CTR + Z in a viewport it will undo properly. What I am doing wrong?

I need to undo my script cos I wish to make it interactive, so the user can adjust parameters with a HUD slider (offset for example). Each time user release slider I undo the previous execution and run again with a new value.


#2

Does pm.polyDuplicateEdge put you in a tool context? Because it sounds like something is, given the error message when running pm.undo.


#3

Well… I activate the select tool, select edges, run script. The select tool remains after running script.
If I execute a script with undo, it will undo.

def run():
    listEdges = pm.ls(sl = 1, flatten=True)
    pm.polyDuplicateEdge(listEdges, splitType=0, offset=0.1)

run()
pm.undo()

But its not working step by step.


#4

But may be my idea of interactivity implementation is wrong? Are there other options to achieve same functionality?


#5

Im unable to recreate the issue you’re having, but you might try using the UndoChunk context manager as described in Practical Programming with Python:

class UndoChunk(object):
    # an undo context manager
    def  __enter__(self):
        pm.undoInfo(openChunk=True)
    def __exit__(self, *_):
        pm.undoInfo(closeChunk=True)

with UndoChunk():
    run()

#6

The chunk context manager is a great way to roll a bunch of operations into a single chunk, so that it can be treated as a single operation. But I don’t think that is what you’re asking for here right?

Also, when running your code above, I get no issues.
Might be worth double checking your undo settings, something might be wonky there.


#7

Thanks, R.White!
The same solution I found posted here by Robert. That does not work as well.

Also, when running your code above, I get no issues.

You select an edge, run the first part of the code, then run pm.undo() and it rolls back???
Cos for me it’s working only if I run all (with pm.undo) at once…

By undo settings you mean if its turned on or not? I checked, it is.


#8

I’m curious. Is this something that needs to be handled with pymel? I can’t seem to have any problems using Maya’s standard python interpreter and the undo queue.


#9

In this particular case, pm.undo is really no different than cmds.undo, the pymel one has a better docstring, but is probably a tiny bit slower due to being a wrapper around cmds.undo.
Where pymel really differs, is when any function returns a node, as pymel returns a class representing that node instead of just a string. undo doesn’t return a node, it just executes an action, so no appreciable difference.


#10

Thanks. Well. It’s just that I’ve heard about it before, that you need to enclose your code to be able to undo it, but I guess I’ve never understood why since any of my scripts “undos” fine.
So I wondered if this was something particularly for Pymel, but is it really a Python thing?


#11

Nope, its a Maya thing.
If you want to be able to undo a whole chunk of code at once, you’d build something like @WeatherMan’s example up above.

Otherwise you’re just calling the undo command, same as when you hit Z.

Otherwise you’re off in the deep end of creating a custom tool using the API and having to implement doIt, undoIt, and redoIt. Which then the regular undo / redo commands take advantage of.


#12

For me the problem still exists. I check on another computer — its works fine… I delete prefs, no difference. Settings/preferences > Undo: turned ON

Have no Idea what to check next to find the reason why my Maya does not want to do it!


#13

I get that “Try exiting the current tool.” error sometimes when I accidentally drag a node in the outliner, and the operation seems to get stuck until I change to a manipulator and back again.

I’m wondering if you have any installed plugin or tool which is causing that sort of context switch.

I can select an edge, run your code, and run pm.undo() without issue.

(Also, in default Maya hotkeys, you only have to hit z to undo. Ctrl is optional.)


#14

How can I find if I have any plugin which causing context switch?


#15

No idea. That’s just the fuzziest clue I could think of. I see that error about once a week, but almost always from dragging things with my Wacom in the outliner.