1

I have problem with drag and drop function and object selection.

I create simple flash arranger (add table icon to stage - room). I have button which create new instance of table icon, wchich i can drag and drop over the stage.

Problem is that i can drag and drop only last added icon. If i add new instance od icon i can not take (drag and drop) any icon created before :/

my code here: main class

import flash.events.MouseEvent;
import flash.events.Event;
import com.adobe.images.JPGEncoder;
import flash.geom.Point;

btn_middleTable.addEventListener(MouseEvent.CLICK, f_middleIco);
btn_bigTable.addEventListener(MouseEvent.CLICK, f_bigIco);
btnSave.addEventListener(MouseEvent.CLICK, f_save);

function f_middleIco(event:MouseEvent):void
{
    var middle:MiddleIco = new MiddleIco();
    middle.x = 20;
    middle.y = 20;
    stage.addChild(middle);
    trace("created");
}

function f_bigIco(event:MouseEvent):void
{
    var big:BigIco = new BigIco();
    big.x = 20;
    big.y = 20;
    stage.addChild(big);
    trace("created");
}

function f_save(event:MouseEvent)
{
    var jpgEncoder:JPGEncoder;
    jpgEncoder = new JPGEncoder(90);

    var bitmapData:BitmapData = new BitmapData(stage.width, stage.height);
    bitmapData.draw(stage, new Matrix());
    var img = jpgEncoder.encode(bitmapData);

    var file:FileReference = new FileReference();
    file.save(img, "filename.png");
}

icon instance package:

package  {

    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.geom.Point;

    public class BigIco extends MovieClip {
            public var active:Boolean;

        public function BigIco() {
            // constructor code
            this.addEventListener(Event.ENTER_FRAME, f_move);
            this.addEventListener(MouseEvent.MOUSE_DOWN,downf);
            this.addEventListener(MouseEvent.MOUSE_UP,upf);
        }

        public function f_move(e:Event)
        {
            if(active==true)
            {
                startDrag();
            }
            else if(active==false)
            {
                stopDrag();
            }
        }

        public function downf(e:MouseEvent)
        {
            active = true;
        }
        public function upf(e:MouseEvent)
        {
            active = false;
        }
}
}

what can i do to have ability to select every icon (instance) which is actually over mouse cursor?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gwynbleid
  • 29
  • 1
  • 1
  • 6
  • Note that while my answer completely removes `f_move`, in that method, there's no need for `else if(active==false)` - if `active` is not true, it's false, so `else` would be enough. You can also shorten `if(active==true)` to `if (active)`. – JimmiTh Jul 13 '13 at 09:35
  • One last thing: Except for rather advanced cases, it's not a good idea to use `stage.addChild()` to add instances to the main timeline - because you're not actually adding them to the timeline, but "next to it" in the display hierarchy (the main timeline that you see in Flash is, itself, a child of `stage`). It works here, but in other cases it may result in hard to find bugs, and what you actually want here is `this.addChild()`. See e.g. http://stackoverflow.com/questions/13096993/correct-use-of-addchild – JimmiTh Jul 13 '13 at 21:59

1 Answers1

0

Theory: startDrag and stopDrag aren't meant to be called repeatedly - but they will be, once every frame, for every clip you add, because you're using an ENTER_FRAME listener.

I haven't tested this, but calling stopDrag may actually stop any dragging - including on other clips - because you're only allowed to drag a single Sprite (and hence MovieClip) in the first place.

So, if that theory holds, startDrag() on your first icon will be cancelled immediately by f_move() on the new icon calling stopDrag().

But there's no need for you the ENTER_FRAME listener in any event. This should give the same result (except it actually works) - simply calling the drag methods immediately in the mouse listeners:

public class BigIco extends MovieClip {
    public var active:Boolean;

    public function BigIco() {
        // constructor code
        this.addEventListener(MouseEvent.MOUSE_DOWN, downf);
        this.addEventListener(MouseEvent.MOUSE_UP, upf);
    }

    public function downf(e:MouseEvent)
    {
        // Unless you're going to use 'active' for other stuff,
        // you can remove this line:
        active = true; 
        startDrag();
    }
    public function upf(e:MouseEvent)
    {
        // Same here:
        active = false;
        stopDrag();
    }
}

Other than that, I can't spot any real problems in your code.

EDIT: "Perfect" version, also detecting mouse up if pointer isn't over icon:

public class BigIco extends MovieClip {

    public function BigIco() {
        // Only add mouse down listener here. We'll add up when needed below:
        this.addEventListener(MouseEvent.MOUSE_DOWN,downf);
    }

    public function downf(e:MouseEvent)
    {
        // Add event listener to stage, so as to be triggered even if
        // the pointer isn't over the icon when releasing the button.
        // Note that this will also work even with the mouse *outside*
        // the stage/swf area:
        stage.addEventListener(MouseEvent.MOUSE_UP,upf);
        startDrag();
    }
    public function upf(e:MouseEvent)
    {
        // Remember to remove the event listener after use:
        stage.removeEventListener(MouseEvent.MOUSE_UP, upf);
        stopDrag();
    }
}
JimmiTh
  • 7,389
  • 3
  • 34
  • 50
  • if I leave only mous down and mouse up event i can't drop my icon ;/ `package { import flash.display.MovieClip; import flash.events.MouseEvent; import flash.events.Event; import flash.geom.Point; public class BigIco extends MovieClip { public var active:Boolean; public function BigIco() { this.addEventListener(MouseEvent.MOUSE_DOWN,downf); this.addEventListener(MouseEvent.MOUSE_UP,upf); } public function downf(e:MouseEvent) { startDrag(); } public function upf(e:MouseEvent) { stopDrag(); } } }` – Gwynbleid Jul 13 '13 at 18:55
  • Works fine for me - and has in around 20-30 earlier projects. But if you release the mouse button when the cursor isn't actually over the clip, it won't be notified. For that, you'll need to handle MOUSE_UP on the stage instead - so that it gets triggered no matter where the mouse cursor is. – JimmiTh Jul 13 '13 at 18:59
  • Will try do something with that, thanks. If i will have trouble i will write. thanks for help :). – Gwynbleid Jul 13 '13 at 19:24
  • And just for demonstration's sake, here's the exact same file, with your original timeline code, and the code I listed above: https://dl.dropboxusercontent.com/u/14034871/StackOverflow/patio2.zip (temporary link, will remove it and this comment when seen). Works exactly the same - without spaghetti code. ;-) – JimmiTh Jul 13 '13 at 21:46
  • Thanks, i will look at it. I make spaghetti code because I dont know any programing la nguage well :/ I know only basic things :). Thanks again – Gwynbleid Jul 14 '13 at 05:29
  • Don't worry about the spaghetti - it's just a way to describe code that is tangled, not really a criticism - especially not when it comes to Flash, where a lot of bugs and quirks sometimes *force* us to do some messy stuff. In this case, however, I don't think it's needed. – JimmiTh Jul 14 '13 at 08:42