How can I use Undo for an EditorWindow?

So I have made a few custom inspectors before and used the Undo system but how do you use it for an EditorWindow when there are no objects to pass to Undo.RecordObject(), I just want to be able to undo changes to local variables.
Here is what I have

namespace RapidIconUIC
{
    public class RapidIconWindow : EditorWindow
    {
        static RapidIconWindow window;

        public AssetList assetList;
        public DraggableSeparator leftSeparator, rightSeparator;
        public AssetGrid assetGrid;
        public IconEditor iconEditor;

        [MenuItem("Tools/RapidIcon")]
        static void Init()
        {
            window = (RapidIconWindow)GetWindow(typeof(RapidIconWindow), false, "RapidIcon");
            window.minSize = new Vector2(870, 600);
            window.Show();
        }

        private void OnEnable()
        {
            //A load of init stuff, including this:
            iconEditor = new IconEditor(assetGrid, window);
            iconEditor.LoadData();
        }

        private void OnDisable()
        {
            //Saves some variables to EditorPrefs
            iconEditor.SaveData();
        }

        void OnGUI()
        {
            if (!window)
                Init();

            //A load of stuff including:
            iconEditor.Draw(window.position.width - rightSeparator.value, window);
        }
    }
}

Then in the IconEditor class (doesn’t derive from anything), I have a bunch of variables that are changed with GUI controls e.g.

void DrawTransformControls()
        {
            EditorGUI.BeginChangeCheck();
            Vector3 camPos = EditorGUILayout.Vector3Field("Camera Position", currentIcon.cameraPosition);
            //And some others
            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(this, "IconEditor Undo"); //Can't do this as IconEditor is not an Object
                currentIcon.cameraPosition = camPos; //bad example as I'm changing another object here, but sometimes I do just change a local variable to the IconEditor class
                //currentIcon also cannot be converted to an Object either anyway
                UpdateIcon(currentIcon);
            }
        }

So how can I add undo functionality in this script, and others like it

Thanks :slight_smile:

You can mark IconEditor as Serializable, and then pass the RapidIconWindow to the IconEditor to record that.

When doing Undo/Serialization in an Editor Window, it’s the editor window itself you’re serializing, as it’s a ScriptableObject that Unity does some magic to. Exactly the rules for what serializes and why is undocumented and a bit esoteric, but for the most part it works as usual.

Thanks, I will give that a go :slight_smile:

That worked, thanks a lot :smile:

Hello, Sir, it’s been a year but I hope you can explain a little bit more about “passing the RapidIconWindow to the IconEditor”
I have a trouble in trying to implement this Undo system. My code looks like this inside the Editor:

[System.Serializable]
[CustomEditor(typeof(ChatAsset))]
public class Editor_ChatAsset : Editor
{
    public override void OnInspectorGUI()
    {
        if (GUILayout.Button("Open Window"))
        {
            Window_ChatAsset.Open((ChatAsset)target);
        }
        EditorGUILayout.Space();
        base.OnInspectorGUI();
    }
}

If you’re wondering what Window_ChatAsset.Open() does:

    public static void Open(ChatAsset chatAsset)
    {
        Window_ChatAsset window = GetWindow<Window_ChatAsset>("Chat Asset Editor");
        window.serializedObject = new SerializedObject(chatAsset);
    }

I don’t really understand how Undo works, and I have read many articles and threads about. Nothing works, or to put it more precise, I don’t know how to make it work. Please help…

Is the problem not resolved yet? Try this.

[Serializable]
    public class TestWindow : EditorWindow
    {
        [SerializeField] private float test = 0;
        private static TestWindow testWindow;
        private static SerializedObject serializedTestWindow;



        [MenuItem("Test/OpenTestWindow")]
        private static void OpenTestWindow()
        {
            testWindow = GetWindow<TestWindow>(false);
            serializedTestWindow = new SerializedObject(testWindow);
        }
        private void OnGUI()
        {
            Undo.RecordObject(serializedTestWindow.targetObject, "test");
            test = EditorGUILayout.FloatField(nameof(test), test);
        }
    }

Open window and change test property. And try undo.