Sign in to follow this  
the_qwert

A simple Undo/Redo feature? (VC# 2008 express + WinForms + SDL.NET)

Recommended Posts

the_qwert    100
I've been making on a tile editor for a re-make of Legend of Zelda: Link's Awakening I'm working on, an I found myself at a bit of a hold-up when I tried to implement an Undo / Redo feature. The problem I've been having is basically this: I draw a pixel to the image, and hit the redo button, and the program changes the pixel back to it's original state, but only until it updates the surface (via the updateCurrentTile() method below) I have the image stored to, whereupon it brings it back to the state before I hit the undo button (nullifying the effects of the undo). Right now I'm using an instance of the Stack class to store the history states, and I'm pushing a new state on the stack whenever a mouse button is pressed, and popping one off when the user hits Undo. Here's the parts of the source that should be having some effect: Sorry if it's a bit disjointed though, I'm mostly a self-taught programmer, so I'm not sure if I'm doing things as people normally would.
        public struct Tile
        {
            public short DefaultPalette;

            public Surface Image;
            public Surface Image1x;
            public Surface Image2x;
            public Surface ImageFullSize;

            public byte[,] ColorData;

            public double scale;

            public Tile(Tile t)
            {
                this = t.Clone();
            }

            public Tile Clone()
            {
                Tile t = new Tile();

                t.DefaultPalette = this.DefaultPalette;
                t.Image = this.Image;
                t.Image1x = this.Image1x;
                t.Image2x = this.Image2x;
                t.ImageFullSize = this.ImageFullSize;
                t.ColorData = this.ColorData;
                t.scale = this.scale;

                return t;
            }
        }
...

        //The tile that is currently being edited.
        public static Tile curTile;

        //History stack for undo actions.
        public static Stack<Tile> tileUndoStack;

...

        public bool updateCurrentTile()
        {
            Color[,] TileColor = new Color[TileSize, TileSize];

            for (int i = 0; i < TileSize; i++)
            {
                for (int j = 0; j < TileSize; j++)
                {
                    try
                    {
                        byte color = curTile.ColorData[i, j];

                        TileColor[i, j] = Palettes[curPalette].colors[color];

                        //curTile.ColorData[i, j] = color;
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
            }

            curTile.Image.SetPixels(new Point(0, 0), TileColor);
            curTile.Image1x = curTile.Image.CreateScaledSurface(curTile.scale, false);
            curTile.Image2x = curTile.Image.CreateScaledSurface(2.0 * curTile.scale, false);
            curTile.ImageFullSize = curTile.Image.CreateScaledSurface(10.0 * curTile.scale, false);

            return true;
        }


        //Called when a mouse button is clicked over the SDL WinForm control
        private void surfaceControl1_MouseDown(object sender, MouseEventArgs e)
        {

            if (e.X >= 70 && e.X < 390)
            {
                if (e.Y >= 70 && e.Y < 390)//If the cursor is over the edit-able tile
                {
                    tileUndoStack.Push(curTile);//Make's a history state

                    int x = (int)(Math.Floor(((e.X - 70) / 10.0) / curTile.scale));
                    int y = (int)(Math.Floor(((e.Y - 70) / 10.0) / curTile.scale));

                    if (e.Button == MouseButtons.Left)
                    {
                        if (curTile.ColorData[x, y] != curColor[0])
                        {
                            curTile.ColorData[x, y] = curColor[0];// Change that pixel's color to the currently selected color for the left mouse button
                            updateCurrentTile();
                        }
                    }
                    else if (e.Button == MouseButtons.Right)
                    {
                        if (curTile.ColorData[x, y] != curColor[1])
                        {
                            curTile.ColorData[x, y] = curColor[1];// Change that pixel's color to the currently selected color for the right mouse button
                            updateCurrentTile();
                        }
                    }
                }
            }
        }


        //Called when the user click the undo button
        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Mode == EditorMode.Tile)
            {
                if (tileUndoStack.Count > 0)
                {
                    int index = tileUndoStack.Count - 1;

                    curTile = tileUndoStack.Pop();

                    updateCurrentTile();

                    if (tileUndoStack.Count == 0)
                    {
                        Action enableAction = delegate() { undoToolStripMenuItem.Enabled = false; };
                        this.BeginInvoke(enableAction);

                    }
                }
            }
        }


I've found that the problem seems to be occuring when updateCurrentTile is called in undoToolStripMenuItem_Click(). Thanks in advance for any help!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this