Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

I'm only getting one level of undo with pop method / undo button

Mentor ,
Aug 22, 2013 Aug 22, 2013

Hi.  Why does this code only produce one level of undo?  I thought each time the pop method is triggered on an array the array shrinks and you can continue to pop as long as the array is not less than 0.

Here's my code:

import flash.display.MovieClip;

import flash.display.Shape;

import flash.events.MouseEvent;

import flash.events.Event;

//http://www.kirupa.com/forum/showthread.php?309502-As3-Spiral-effect .. this is the one used previously in other files

//http://hub.tutsplus.com/tutorials/create-a-basic-drawing-application-in-flash--active-1627 .. this is the one used here

var my_mc:MovieClip=new MC();

var container:MovieClip=new MovieClip();

stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);

stage.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);

var shape:Shape=new Shape();

var myArr:Array=new Array();

var myArrRedo:Array = new Array();

var myArrObj:Array= new Array();

var undo_btn:MovieClip=new Btn_mc_undo();

var redo_btn:MovieClip=new Btn_mc_redo();

undo_btn.x=10;

undo_btn.y=350;

redo_btn.x=110;

redo_btn.y=undo_btn.y;

addChild(undo_btn);

addChild(container);

stage.addChild(redo_btn);

var nums:int;

undo_btn.addEventListener(MouseEvent.MOUSE_DOWN, undoEvent);

redo_btn.addEventListener(MouseEvent.MOUSE_DOWN, redoEvent);

function undoEvent(e:MouseEvent):void{

   

   

    container.removeChild(myArrObj.pop());

   

}

function redoEvent(e:MouseEvent):void{

    // nothing yet

}

var num:int=0;

function startDrawing(e:MouseEvent):void{

    shape=new Shape();

    container.addChild(shape);

   

    shape.name=String(num);

    myArr.push(shape.name);

    myArrObj.push(shape);

    shape.graphics.lineStyle(3, 0xcccccc);

    shape.graphics.moveTo(mouseX, mouseY);

    stage.addEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);

    num++;

   

}

function stopDrawing(e:MouseEvent):void{

    stage.removeEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);

}

function whileDrawing(e:MouseEvent):void{

    shape.graphics.lineTo(mouseX, mouseY);

}

a couple of these lines are left over from troubleshooting (such as the num++);

TOPICS
ActionScript
2.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , Aug 22, 2013 Aug 22, 2013

What I offered works.  Maybe you have something else going on in the file that you haven't accounted for.

If you put a trace(e.target) in your drawing function you will see it calls the drawing function when you click the button(s).  

Here's a link to a working sample file using your code with some adjustments for missing content...

http://www.nedwebs.com/Flash/AS3_Draw_Undo.fla

Another cure might be to create a separate drawing area from the buttons and target that area instead of the stage for yo

...
Translate
LEGEND ,
Aug 22, 2013 Aug 22, 2013

Your undo is probably working flawlessly... the problem is that when you click the undo button you are effectively going thru the motions of drawing a new shape, adding a new one to the array, which is then removed when you release the button.

You might get around this by putting a conditional on the drawing code that excludes processing it when the event target is one of the buttons....

function startDrawing(e:MouseEvent):void{
   if(e.target != undo_btn){
        shape=new Shape();
        container.addChild(shape);

        shape.name=String(num);
        myArr.push(shape.name);
        myArrObj.push(shape);
        shape.graphics.lineStyle(3, 0xcccccc);
        shape.graphics.moveTo(mouseX, mouseY);
        stage.addEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);
        num++;
    }
}

function stopDrawing(e:MouseEvent):void{
   if(e.target != undo_btn){
       stage.removeEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);
    }
}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Aug 22, 2013 Aug 22, 2013

Thanks for responding Ned.  This doesn't work.  I did read however after posting this that there is a solution for creating complex undos, meaning an undo that is beyond just one level deep.  The code above only goes down to one level then stops undoing.  I will research the solutions that I have found once they arrive in the mail.

-markerline

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 22, 2013 Aug 22, 2013

What I offered works.  Maybe you have something else going on in the file that you haven't accounted for.

If you put a trace(e.target) in your drawing function you will see it calls the drawing function when you click the button(s).  

Here's a link to a working sample file using your code with some adjustments for missing content...

http://www.nedwebs.com/Flash/AS3_Draw_Undo.fla

Another cure might be to create a separate drawing area from the buttons and target that area instead of the stage for your drawing listeners.

It would also be a good idea to use a CLICK listener for the buttons rather than a MOUSE_DOWN.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Aug 22, 2013 Aug 22, 2013

Responding to your second-to-last post ....  you're right I tested your file out and I found a bug in Flash or perhaps something intended by design.

Your file has an undo button placed on the stage and named in the properties panel.  In my file I was calling the undo button from the library through ActionScript on Frame 1 (linkage) and when tracing all of the events I could get a result that the undo button was being pressed but I also simultaneously got results that I was still drawing on the stage at the button press.  Perhaps a z-depth issue though I thought I addressed that by calling the addChild of the undo button after the shape container.  So in essence what I'm saying is that if you place a button on the stage and call AS3 on it it will react independent of stage calls to the drawing canvas.  If you get a chance perhaps you can add your button in your file to the library and troubleshoot what I experienced.  Although I know you're very busy.

Thank you.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 23, 2013 Aug 23, 2013

If you run the trace of the e.target in the drawing function it will tell you what object is being interacted with.  You might find that for the button(s) it is actually something inside the buttons rather than the button itself.

If you assign the MOUSE_DOWN/UP listener to the stage, then anytime you use the mouse down/up interaction it will register for those stage listeners.  That's why I suggest you should create a drawing area that is separate from the buttons and assign the listener for drawing to that instead of the stage.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Aug 23, 2013 Aug 23, 2013

Thanks.  You're absolutely right about the stage listening to too much and discrete containers listening to just the right things.

Now, if I can only get the ReDo button to work.  The undo pops everything from the array one at a time so I would have to assign a new array, something like a RedoArray which stores deleted DisplayObjects from the undo calls.  I got it somewhat to work but not really.  I can post the code if you'd be interested.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 23, 2013 Aug 23, 2013

Your redo versus undo can get complicated to manage depending on how you want it to work.  That's probably the first thing you need to think thru in detail.  If you want to show what you have so far and explain what it doesn't do that you want it to, feel free to do so.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Aug 23, 2013 Aug 23, 2013

So what this application does is draw on the screen in the container area.  when you lift up the mouse button it stops drawing.  you can move to a new place and it will draw again starting at that new mouseX,mouseY position.  If you undo 5 drawings and you have drawn 5 drawings, the stage will become empty.  However this is where it gets tricky.  If you draw 5 times and you undo the 5th one then Redo the 5th one it will reappear on the stage.  But if you hit undo again it won't undo the 5th element.  Rather it takes away the 4th element.  When you hit redo the 4th element comes back.  During this entire time the 5th element has remained on the stage unaffected.

This can be replicated for all of the instances of drawings on the stage's container.

Here is the code.

=====================================================================================================================================

import flash.display.MovieClip;

import flash.display.Shape;

import flash.events.MouseEvent;

import flash.events.Event;

import flash.display.DisplayObject;

//http://www.kirupa.com/forum/showthread.php?309502-As3-Spiral-effect .. this is the one used previously in other files

//http://hub.tutsplus.com/tutorials/create-a-basic-drawing-application-in-flash--active-1627 .. this is the one used here

var container2:MovieClip = new MovieClip();

var container:MovieClip=new ContainerMC();

container.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);

container.addEventListener(MouseEvent.MOUSE_UP, stopDrawing);

var shape:Shape=new Shape();

var myArr:Array=new Array();

var myArrRedo:Array = new Array();

var myArrObj:Array= new Array();

var myArrRedo2:Array = new Array();

var undo_btn:MovieClip=new Btn_mc_undo();

var redo_btn:MovieClip=new Btn_mc_redo();

undo_btn.x=10;

redo_btn.x=110;

redo_btn.y=undo_btn.y;

container.width=550;

container.height=300;

container.y=0;

container2.addChild(undo_btn);

container2.y=310;

addChild(container);

addChild(container2);

container2.addChild(redo_btn);

var nums:int;

undo_btn.addEventListener(MouseEvent.CLICK, undoEvent);

redo_btn.addEventListener(MouseEvent.CLICK, redoEvent);

function undoEvent(e:MouseEvent):void{

   

    trace("undo"+" myArrObj: "+myArrObj+" myArrRedo: "+myArrRedo);

   

    container.removeChild(myArrObj.pop());

    trace("pop myArrObj:"+myArrObj+" myArrRedo: "+myArrRedo);

   

}

function onRedo():void{

   

    myArrRedo2.push(shape as DisplayObject);

    trace(myArrRedo2+" myArrRedo2");

}

function redoEvent(e:MouseEvent):void{

   

    container.addChild(myArrRedo2[num-1]);

    num--;

}

var num:int=0;

function startDrawing(e:MouseEvent):void{

   

    if(e.target!=undo_btn&&e.target!=redo_btn){

    shape=new Shape();

    container.addChild(shape);

   

    shape.name=String(num);

    myArr.push(shape.name);

    myArrObj.push(shape);

    shape.graphics.lineStyle(3, 0x111111);

    shape.graphics.moveTo(container.mouseX, container.mouseY);

    onRedo();

    container.addEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);

    num++;

    trace(num+" num inside if");

    trace("inside if");

    }

    trace("outside if");

   

   

   

   

}

function stopDrawing(e:MouseEvent):void{

    if(e.target!=undo_btn&&e.target!=redo_btn){

    container.removeEventListener(MouseEvent.MOUSE_MOVE, whileDrawing);

    trace("stopped drawing");

    }

   

}

function whileDrawing(e:MouseEvent):void{

    shape.graphics.lineTo(container.mouseX, container.mouseY);

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 23, 2013 Aug 23, 2013

At a quick glance it looks like you are forgetting to add the redone object back into the myArrOb array.  You probably need to remove it from the redone array as well.  As I said, you need to think this thru in detail.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Aug 23, 2013 Aug 23, 2013
LATEST

Thanks.  Right now I can't seem to resolve the issue.  But I'll meditate on it for a couple of days and hopefully get back to this post with positive results. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Aug 22, 2013 Aug 22, 2013

Just a quick update.  I skimmed briefly the contents of an e-book on ActionScript 3.0 and this was the book I was counting on for assistance but the content was far too abstract.  I don't think there was one complete non-theoretical example in the whole text!  I haven't gotten far enough to be able to parse theory into concrete examples.  Not by any means of the imagination.

I hope I can find something else in the meantime.  Thanks for your assistance thus far.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Aug 22, 2013 Aug 22, 2013

The solution lies in managing the listeners and event handlers you have in place.  YOu don't need to research beyond what you have already.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines