Download

Undo Python Script

The description here seems very clearly, but my test code is not working. The undo entry “My Transaction Test” is in the Undo-History, but it is not undoing the translation. Anyone can help?



import unreal
actors = unreal.EditorLevelLibrary.get_selected_level_actors()
location = actors[0].get_actor_location()
with unreal.ScopedEditorTransaction("My Transaction Test") as trans:
      location.z += 28
      actors[0].set_actor_location(location, False, True)

Maybe I have to explicit set the enter and exit points of the commands to undo?
https://api.unrealengine.com/INT/PytonAPI/class/ScopedEditorTransaction.html

Did you manage to get this working?

I seem to only get AttributeErrors that unreal is missing the ScopedEditorTransaction. Are there even more plug-ins required beyond the “Editor Scripting Utilities” and “Python Editor Script Plugin”?

Seeing as I couldn’t find it I attemped to recreate and think I got it working.


class Undo(object):
    def __init__(self, context, desc, primary_object=None):
        self.context = context
        self.desc = desc
        self.primary_object = primary_object

    def __enter__(self):
        self.transaction = unreal.SystemLibrary.begin_transaction(
            self.context,
            self.desc,
            self.primary_object
        )

    def __exit__(self, type, value, traceback):
        self.exit = unreal.SystemLibrary.end_transaction()

    def __cancel__(self):
        unreal.SystemLibrary.cancel_transaction(self.transaction)

And I can then use it as follows


world = unreal.EditorLevelLibrary.get_editor_world()
it = unreal.SelectedActorIterator(world)

with Undo('UndoTest', unreal.Text("My Undo Test")) as undo:
    for actor in it:

        unreal.SystemLibrary.create_copy_for_undo_buffer(actor)
        unreal.SystemLibrary.transact_object(actor)

        actor.add_actor_local_offset(
            offset, 
            sweep=False, 
            teleport=True
        )

In this situation (since you’re not setting properties directly via set_editor_property) you need to call modify on the object before you change it, as this notifies the transaction system that it is going to change and needs to be tracked. We could perhaps do this automatically when calling non-pure methods on an object from Python.

Which version of UE4 are you using. I think this was only added in 4.21.

I tried it in both 4.21 and 4.22 and it did not show up in dir(unreal)

I don’t know why that would be. It shows up fine for me in 4.22, and is defined in PyEditor.cpp (which is a core PythonScriptPlugin file, so there’s nothing external you could have disabled).

Doesn’t seem to be the only thing, unreal.MaterialEditorInstanceConstant is also missing. Tried in 4.21, 4.22 and our own modified version of 4.22

Its been some time since this was asked, but its still a problem. I found this post, so this is for others that stumble upon it as well.

Here is my work around:

The help() doc for the class has the list of the properties. Each class property is surrounded by double ` characters. I am not sure if every class is well documented with the help() function so this could be error prone. This feels like a fragile solution but for the StaticmeshActor it seems to match the docs.

get class list of properties for unreal.StaticMeshActor

unreal.StaticMeshActor — Unreal Python 4.26 (Experimental) documentation

obj = unreal.StaticMeshActor
doc = obj.doc
tokens = doc.split(’``’)
class_properties = tokens[1::2]

quick print of the properties

for property in class_properties:
print property

Hopefully there will be a get_class_properties function at some point.

Ryan

[USER=“2003”]Jamie Dale[/USER] you are kind of right, but actually even the example from the documentation does not work.



import unreal
obj = unreal.MediaPlayer()
with unreal.ScopedEditorTransaction("My Transaction Test") as trans:
    obj.set_editor_property("play_on_open", True)
    obj.set_editor_property("vertical_field_of_view", 60)


It does not create the history entry, even if it is calling only [FONT=Courier New]set_editor_property(). It only works if I insert [FONT=Courier New]obj.modify() before setting the properties and it looks painful if I have to do this for every change I want to do.

Is this still on the table?

Refer to UnrealEnginePython Plugin

if you modify property, you must call modify method for undo transaction.

https://docs.unrealengine.com/en-US/PythonAPI/class/_ObjectBase.html?highlight=modify#unreal._ObjectBase.modify

this is my chinese blog post for undo transaction research.