Search code examples
actionscript-3flashgraphicsundo-redo

Clearing the last graphic drawn? (Undo/Redo drawing)


public function drag(e:MouseEvent)
    {
        lineDraw(mouseX, mouseY);
        e.updateAfterEvent();

    }
    public function lineDraw(X:int, Y:int):void
    {
        currentX = X;
        currentY = Y;

        graphics.lineStyle(size, color)
        graphics.moveTo(previousX, previousY)
        graphics.lineTo(currentX, currentY)

        previousX = currentX;
        previousY = currentY;
    }

Very simple code I made that allows me to draw lines with my mouse. Function drag is triggered on MOUSE_MOVE after MOUSE_DOWN.

My question is: how would I go about clearing the last line drawn? Basically, a ctrl+z/undo function that can be repeat as many times as i want.

Would I have to rewrite my code completely and push every single line drawn into an array, and then work my way backwards through the array, removing lines as I click "undo"? Or is there another better, easier solution to this?

Thanks! :)


Solution

  • Here is an example: See code comments for explanations

    private var undoStates:Vector.<Shape> = new Vector.<Shape>(); //holds all your undo states (HAS TO BE SHAPE SINCE AS3 DOESN"T LET YOU ISNTANTIATE A GRAPHICS OBJECT DIRECTLY)
    private var redoStates:Vector.<Shape> = new Vector.<Shape>(); //holds all your redo states
    private var undoLevels:int = 1; //how many undo levels you'd like to have
    private var redoLevels:int = 1;
    
    public function undo() {
        if (undoStates.length > 0) {  //make sure there is an undo state before preceeding
            //add redo state
            redoStates.push(getState());
    
            //if redo states are more than redoLevels, remove the oldest one
            if (redoStates.length > redoLevels) redoStates.splice(0, 1);
    
            //make the the last undo state the current graphics
            graphics.clear(); //not sure if this line is required, can't recall if copyFrom clears first
            graphics.copyFrom(undoStates.pop().graphics); //pop removes the last item from the array and returns it
        }
    }
    
    public function redo() {
        if (redoStates.length > 0) {
            //add undo state
            addUndo();
    
            //make the the last undo state the current graphics
            graphics.clear(); //not sure if copy from (the next line) clears or not
            graphics.copyFrom(redoStates.pop().graphics);
        }
    }
    
    private function getState():Shape{
        var state:Shape = new Shape();
        state.graphics.copyFrom(graphics);  //copy the current graphics into a new Graphics object
        return state;
    }
    
    private function addUndo():void {
        undoStates.push(getState()); //add the current state to the undo array
    
        //if more undo states than undoLevels, remove the oldest one
        if (undoStates.length > undoLevels) undoStates.splice(0, 1);
    }
    
    public function lineDraw(X:int, Y:int):void {
        currentX = X;
        currentY = Y;
    
    
        //create undo state before we draw more
        addUndo();
    
        graphics.lineStyle(size, color)
        graphics.moveTo(previousX, previousY)
        graphics.lineTo(currentX, currentY)
    
    
        previousX = currentX;
        previousY = currentY;
    }