SabreCSG icon indicating copy to clipboard operation
SabreCSG copied to clipboard

2DSE: Undo/Redo support in the 2D Shape Editor window.

Open Henry00IS opened this issue 6 years ago • 6 comments

Over at Twitter Wulightsun asked how to CTRL+Z undo.

I had significant trouble implementing this because there's no game object associated with the shape editor window which Unity needs in order to undo things.

Henry00IS avatar Dec 17 '18 11:12 Henry00IS

Perhaps you could store some contextual information on a scriptable object instance

sabresaurus avatar Dec 17 '18 11:12 sabresaurus

I'm not certain - but if you're serializing these states in an EditorWindow seeing as that inherits from ScriptableObject you can probably register an Undo on it in the usual ways.

vertxxyz avatar Dec 17 '18 23:12 vertxxyz

@vertxxyz you are a genius! The EditorWindow is indeed a ScriptableObject and I am able to record undo history, thank you so much! Luckily nearly all of the properties are serialized for JSON so this is pretty straightforward.

Henry00IS avatar Dec 25 '18 18:12 Henry00IS

I created a pull request #201. When I close the 2D Shape Editor window the undo/redo history remains. Is there a way to discard it or what's the best practice to handle this?

Henry00IS avatar Dec 25 '18 19:12 Henry00IS

A discussion on Discord revealed that I am not keeping to the Unity paradigm where every action causes a reaction in an object, scene or setting. The 2D Shape Editor would need its own undo/redo stack while the window has focus and/or have all undo/redo history of actions taken in that window cleared when it's closed (it calls OnDestroy and does in fact garbage collect the window).

Currently, if the user were to sketch up a 2D project but then change their mind, they'd have to press CTRL+Z say 50+ times to get back to scene changes, even when the window has been closed, a most unfortunate situation.

Modifications in the 2D Shape Editor project may be mixed with scene activity. If you were to make a note of the current group identifier when the window is shown to then call Undo.RevertAllDownToGroup when the window is closed it essentially discards all of the editor activity but also undoes any scene modifications done while the window was open.

I also had a look at the reference source but the undo stack is extremely native and it appears that reflection can't help me solve this issue. There also doesn't appear to be a way to intercept and cancel undo/redo events which would have let me take control over the situation.

Optimal Solution

  • A custom undo/redo stack just for the editor window.
  • Intercept undo/redo events if the window has focus to use the custom stack instead.
  • Clean separation between Unity editor's stack and the editor window's stack.

... but this may not be possible.

Henry00IS avatar Dec 26 '18 11:12 Henry00IS

I came up with a simple trick:

When the window receives focus I force a fake undo operation onto the stack called "2DSE", then when you redo the group name is and remains "2DSE" and when you undo, nothing happens once (as it's my fake history entry) and the group name changes to whatever the previous action was. Now I can differentiate between undo and redo and implement a custom stack. When the window loses focus I remove my "2DSE" history. It's invisible to the user.

Henry00IS avatar Dec 26 '18 14:12 Henry00IS