changing index position on startDrag() - actionscript-3

I am making a dragable map and there are few thing on top of the map(UI). When the map is double clicked it enables drag. But it's changing the index position, basically, it going over the UI. what's the easiest way to control the index position of the map?
The click and drag event is controlled in mapZoom class.
this.addEventListener(MouseEvent.MOUSE_DOWN, enableDrag);
public function enableDrag(e:MouseEvent):void
{
this.startDrag();
}

i think the best way is to add two children to your root (main) clip. thee use the first (that is always below the second) for the map and the second for UI

Related

Flash Action Script 3: drag movie clip issue

I am new to as3. I create a rectangle and convert it to symbol. Then I go into the symbol and create two sliders. Also, I make the symbol draggable.
controlPanel_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragStartF);
controlPanel_mc.addEventListener(MouseEvent.MOUSE_UP, dragEndF);
function dragStartF(e:MouseEvent){
e.currentTarget.startDrag();
}
function dragEndF(e:MouseEvent){
e.currentTarget.stopDrag();
}
It works fine, but I can't use the slider. If I drag the slider, the entire movie clip moved. How can I solve this problem? Cheers!
Without more info on the structure of your FLA-file I assume that controlPanel_mc is the container containing the rectangle[background] and the two sliders.
What it seems like you did in your code was to add event listener to the container, what that means is that "if a click occures anywhere on this object, do the following". Since that clip "owns" the 2 sliders, the sliders will not get any MOUSE_DOWN-events since the parent is always the one handling the event first.
You probably want to convert the background into a symbol and add the eventListeners to that object instead.
bg.addEventListener(MouseEvent.MOUSE_DOWN, onBgClick);
bg.addEventListener(MouseEvent.MOUSE_UP, onBgRelease);
function onBgClick(e:MouseEvent){
controlPanel_mc.startDrag();
}
function onBgRelease(e:MouseEvent){
controlPanel_mc.stopDrag();
}
That should solve your issue :)

How to set mouse click to do not hit transparent pixels

Imagine a painting program. I have two imagens overlaping each other. I must be able to click on the image behind if I click on a transparent part of the above one.
I add an event listener on each image. So I must prevent the first one to dispatch click event in order to the behind one dispatch it.
(I mean, I already check for transparent pixels, but i can't cancel that event to the other imagem dispatch it.)
There is some dirty solution. Say your "images" are encapsulated in Sprites, otherwise you can't attach a listener to a Bitmap object or a Shape object. MovieClips - well, should still work, although checking alpha is a lot harder. You have your listeners attached to those sprites. First, that sprite in itself can check transparency, and if not transparent, proceed the event. To get what's behind, you can call stage.getObjectsUnderPoint(), this will return an Array of DisplayObjects, with foreground being on top. So you might have one single listener that would call this to enumerate what's under the point, then do as Roman Trofimov advises to determine that object's transparency. Once you'll find a non-transparent object, you do:
// "b" is a non-transparent DisplayObject found beforehand
while (b && (!(b is InteractiveObject))) b = b.parent;
if (b) {
var p:Point = new Point(e.stageX, e.stageY);
p = b.globalToLocal(p);
b.dispatchEvent(new MouseEvent('click', true, true, p.x, p.y));
}
This will dispatch a click event to the object that's able to receive events, and is opaque enough to obscure the background.
The MovieClip property 'mouseEnabled' can prevent click events from triggering on objects in front of other objects, for example, take two movie clips of the same size and same position:
mc1.addEventListener(MouseEvent.CLICK, click1);
function click1(e:MouseEvent) : void
{
trace("1");
}
mc2.addEventListener(MouseEvent.CLICK, click2);
function click2(e:MouseEvent) : void
{
trace("2");
}
mc1.mouseEnabled = false;
Output would be "2" as the click would essentially go 'through' mc1.
In flex you can add mouseEnabledWhereTransparent="false" to components. Not fully sure if that variable is available to you though
Generally, you will always get first event from first sprite (if it was not capture phase ot priority change). But as I understand, you need to check was it transparent and if not - stop bubbling this event.
To stop event - use event.stopImmediatePropagation() in event handler.
To determine transparency:
1) If it is just only the one bitmap, you can check its .bitmapData with method .getPixel32, it returns you alpha value.
2) If it is combined sprite (vector and bitmap), you need to manually render it to Bitmap using BitmapData.draw and then use solution from second case
3) To understand if it was absolutelly miss click, you can try this method: Check transparency

AS3 setChildIndex to front

Is there a way to send a specific movieClip to the front of all other movieClips on stage?
I know about setChildIndex, but I can't figure out a way to to calculate the top position dynamically.
You can use setChildIndex() with numChildren.
setChildIndex(childClip, numChildren - 1);
You don't need to use setChildIndex.
addChild is sending child on the top of all clips.
You may be thinking that addChild will double add your MC, but it will not, the second time it will just update it's child index.
By default, flash adds the movieclip to the top of the display list, so you can just repeat adding of the child to the container.
stage.addChild(bottom);
stage.addChild(top);
// top is now on bottom.
stage.addChild(bottom);
// bottom is now on top.
The movieclip(mc) is added on the canvas,
canvas.setChildIndex(mc, 0);
The canvas is added on the stage,
stage.setChildIndex(canvas, 0);
/* Bring Any Clicked Object to the Front
Clicking on any symbol on the Stage moves it in front of all other instances.
*/
// This code makes all symbol instances on stage clickable by making them listen for the CLICK event.
for (var fl_ChildIndex:int = 0;
fl_ChildIndex < this.numChildren;
fl_ChildIndex++)
{
this.getChildAt(fl_ChildIndex).addEventListener(MouseEvent.CLICK, fl_ClickToBringToFront);
}
// This is the function that moves the clicked object to the front of the display list
function fl_ClickToBringToFront(event:MouseEvent):void
{
this.addChild(event.currentTarget as DisplayObject);
}
From Adobe Flash Professional Code Snippets.

Using hitTest instead of mouseOver / mouseOut

Almost all of the Flex components have mouseOver/mouseOut or rollOver/rollOut events. Requires that these events called not the mouse cursor, but on the other element, such as Image or Bitmap.
For example, there is a Colomn Chart and image animations above it and I need to get the data (colomn value or index) when the image is over the column. If it were a component, then I would use hitTest. But what to do if it is chart?
Can't you tell the image/bitmap to not be mouseEnabled?
i can't understand your question properly, eventhough i m trying this...
if you add mouselisteners on the chart and whenever the event is dispatch check..
position.x = event.currentTarget.mouseX;
position.y = event.currentTarget.mouseY;
then you can try with hitTest.
or
if(obj.hitTestPoint(position.x,position.y)){
}
this might be work....

Movieclip stacking in Actionscript

I'm building a game of which the interface is one of the first items to load on screen. Sound button, pause and all the bits -
During the game - all manor of things are dynamically added and removed to the stage. Therefore my interface goes behind my game scene.
How do I ensure the movieclip always stays on top?
Can I override the addChild of my Document Class and every time a new child is added, I restack the interface to the top?
You can use setChildIndex to rearrange objects that are already contained within a MovieClip or Sprite. For example, if you have an object called container, which contains a redBall, blueBall and many other ball objects, you can use the following to make sure redBall is behind everything else:
container.setChildIndex(redBall, 0);
Equally you can make sure that blueBall will be displayed infront of everything else using:
container.setChildIndex(blueBall, container.numChildren-1);
addChildAt will sort you out for adding children straight into their correct position, and setChildIndex will allow you to re-position objects already placed. Hope that helps.
debu
Look into addChildAt, it allows you to specify the index that the new object should be added too.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObjectContainer.html#addChildAt%28%29
A good strategy is to keep all interface elements in one parent Sprite/MovieClip, and all game assets in another. (With the interface one on top)
With your guys suggestion I made this, apparently, if you addChild an object already on the screen, it's simply reindex'd to the top. Does this look ok?
private var topLevelChildrenArray:Array = [];
public function addTopLevelChild(child:DisplayObject):DisplayObject
{
topLevelChildrenArray.push(child)
return this.addChildAt( child, this.numChildren - 1 );
}
override public function addChild(child:DisplayObject):DisplayObject
{
this.addChildAt(child, this.numChildren);
for each(var topChild:DisplayObject in topLevelChildrenArray)
{
super.addChild(topChild);
}
return child
}