[Finished] [ARCed] Undo/Redo Action Framework

Started by Ryex, April 09, 2011, 07:45:29 pm

Previous topic - Next topic

Ryex

April 09, 2011, 07:45:29 pm Last Edit: October 10, 2011, 07:18:17 pm by Ryex
Undo/Redo Action Framework




Description

In order to facilitate the undo and redo functionality of an editor we need to be able to track and reverse changes we make to the project data.
in order to do this we need a Framework that can wrap the functionality.

the framework should consist of two parts

1) A manager:

  • The manager should contains two stacks of action objects. actions that have been done and can be undone, and actions that have been undone and can be redone.

  • The manager should properly track history changes and keep data safe. ie if a action is undo and then a new action is done. the redo stack should be cleared as the first action can't safely be redone.

  • In the facilitation of a future "history" feature like you would find in Photoshop methods should be made that can do batch calls to undo or redo several actions at once going forward or backward in the history.

  • The ability to configurable limit the number of actions in the stacks should also be available as this system has the potential to eat up a lot of memory.


2) An Action template:

  • The idea is that when we want to modify project data we create an action object of the type we need, fill in the necessary data, and then call some sort of commit method on the action object. the Action should add itself to the top of the undo stack and record any data it needs to undo it's changes and then make it's changes.

  • When an undo call is made the the manager it pulls the action on the top of the stack calls a reverse method on it. the reverse method should record any data it needs to redo itself, and then undo it's past changes. the action then be moved to the top of the redo stack.

  • When a redo call to the manger pulls the action on the top of the redo stack and should call the commit method again and move it to the top of the undo stack.

  • This class should be a template that real action objects subclass.





Priority

High



Prerequisites

None



Assigned

None



Everything else

This system should be included in the Core library in it's own module name "Actions". Don't worry about doing the house keeping code to register the system to the Kernel, I'll take care of that.
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Zeriab

Consider using a doubly-linked list as the structure for recording actions in a sequential manner. You can then go forward and backwards in time (undo/redo) by moving a pointer around the list. It's easier than the hassle of moving data between two data structures.

*hugs*

Blizzard

Since we're using Python, a normal Python array will be used for this.
I think a simple data structure with an action ID, the previous state and the new state should be enough for an undo/redo functionality.
Check out our game brands:

Daygames
Game Night Games
Chugnar Games

Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Ryex

I'm not sure what your saying.I thought that two lists was pretty simple
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

ForeverZer0

* I think * what he means is each action has an ID, and is stored in array. Then when the Undo is executed, it simply goes back through the array, reads the ID and then knows what protocol to use to make the action.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Ryex

Alright, G_G I was hoping that you would be the one to do this but we can't wait any longer. I'm going to do it tonight. I'll probably finish it too. if you've done ANY work on it commit the work as it will likely save me time.
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Ryex

October 10, 2011, 07:14:36 pm #6 Last Edit: October 10, 2011, 07:18:34 pm by Ryex
ok
Action framework done
to create an action you subclass the ActionTemplate class from the Action.py in the Core
the init method should take any data that the action need to know in order to change data in the project. it should also call the __init__ method of the super class
super(<classname>, self).__init__()

the subclass should then define a "do_apply" method (no arguments) that will a)record data in the project necessary for the action to be undone and b) set the new data in the project
then the action needs to have a "do_undo" method (no arguments) that will a)record data so the action can be redone and b) use recorded data from the do_apply method to undo the action
the recorded data can be recorded to the action object itself
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

ForeverZer0

You so sexy.

The pieces of the editor are coming along nicely. Now comes the horrible task of linking them all together. :P
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

I suggest you alias do_apply with do_redo as well. This will make the code easier to read because when you call the event for the redo button, the code will read "action.do_redo".
Check out our game brands:

Daygames
Game Night Games
Chugnar Games

Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Ryex

actualy it will read
action.apply()
the apply method of the action class will add the action to the action stack if it not in the stack already and call the do_apply method in the middle in the template class the do_apply method does nothing it just has a simple pass statement. then all we to do to create create an actual action is subclass and make the do_apply and do_undo methods actually do something along with make the init method collect data to carry out the action.

I suppose I'll make one action as an example for how it will work.

also, there is no alias in python. a similar effect can be achieved but we don't need to do that here.
I no longer keep up with posts in the forum very well. If you have a question or comment, about my work, or in general I welcome PM's. if you make a post in one of my threads and I don't reply with in a day or two feel free to PM me and point it out to me.<br /><br />DropBox, the best free file syncing service there is.<br />

Blizzard

I meant alias in general, not literally Ruby's function. xD

class Woman(object):
   def do(self):
       # hurr hurr hurr code comes here
   def do_again(self):
       self.do()
Check out our game brands:

Daygames
Game Night Games
Chugnar Games

Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.