Actionscript 3: Preventing mouse events *except* for a specific button/movieclip? - actionscript-3

Is there a way to block mouse events except for a specific MovieClip or Sprite?
i.e. I know that to prevent ALL mouse clicks, I can write something like:
stage.addEventListener(MouseEvent.CLICK, onPreventClick, true, 0, true);
...
private function onPreventClick(e:MouseEvent) {
e.stopImmediatePropagation();
e.preventDefault();
}

You can check e.currentTarget to find the object who fired the Event and doing your filtering according to that.

Related

keycode for MouseEvent?

So to my understanding, there are keycodes to represent the keystrokes, for example:
public function left(e:KeyboardEvent):void
{
if (e.keycode == 65)
{
leftKey = true;
}
}
I want to do something similar with this logic and apply it for Mouse Events. I've searched on Google but haven't found much results for Flashdevelop AS3. Would there be a keycode to represent Mouse Events?
For example:
stage.addEventListener(MouseEvent.MOUSE_DOWN, down);
stage.addEventListener(MouseEvent.MOUSE_MOVE, move);
stage.addEventListener(MouseEvent.CLICK, click);
public function down(e:MouseEvent):void
{
if (e.keycode == ?)
}
public function move(e:MouseEvent):void
{
if (e.keycode == ?)
}
public function click(e:MouseEvent):void
{
if (e.keycode == ?)
}
Thanks in advance!
When you fire a mouse event that has a listener attached to it, then the function associated with that listener will get called. Period. You don't need to then, again, check to see if the mouse event happened. That's the whole beauty of event listeners. Just to make sure you get it, I'll post an example.
stage.addEventListener(MouseEvent.CLICK,mClick);
Great. We added a listener to the stage. Now, any time you click anywhere on the stage, this listener will cause that mClick function to get called. Now we write the mClick function.
private function mClick(me:MouseEvent):void{
trace("me.target.x",me.target.x);
trace("me.target.y",me.target.y);
}
me is just a variable we chose to represent the event that triggered this function. Event is a class. A MouseEvent is a subclass of Event. So we are saying that me is an Event of sublcass MouseEvent and that this is the expected input for this function. If you were to try to call this function elsewhere in your code it would throw an error saying that this function expected some sort of input.
me.target is the thing that caused the event to get triggered. In this case it is the mouse, so me.target.x will be the x position of the mouse at the time that the mouse was clicked.
That is all there is to it. You have just confused yourself a little bit by trying to apply a specific solution to a different problem, namely, how to register key presses on a keyboard. They are handled slightly fundamentally differently. With a keyboard, we check listen for if the keyboard had a key pressed and then in the event handler, we determine which key was pressed. With mouse events we would have a different listener for mouse move, mouse click, left mouse click and middle mouse click. Since each of those specific events has their own listener, we don't have to evaluate which button was pressed in the handler:
public function left(e:KeyboardEvent):void
{
if (e.keycode == 65)
{
leftKey = true;
}
}
The e is the thing that caused the event. In this case, the Keyboard key. Each key has a keycode. But instead of writing a different listener for every single key on the keyboard, we can just write one listener and one function and then evaluate which key was pressed inside the function. As stated before, with the mouse, the left mouse button gets its own event listener, so no need (or ability) to check that in the event listener. There are properties like ROLL_OVER and MOUSE_UP and MOUSE_DOWN. Look at the documentation for a full list.

MOUSE OUT is being called inside MovieClip

I added a MOUSE_OVER event listener to my MovieClip, then i added MOUSE_OUT just like this :
mc.addEventListener(MouseEvent.MOUSE_OVER, boxItemMouseOver, false, 0, true);
protected function boxItemMouseOver(e:MouseEvent):void
{
trace("mouse over");
var boxItem:MovieClip = e.currentTarget as MovieClip;
boxItem.addEventListener(MouseEvent.MOUSE_OUT, boxItemMouseOut, false, 0, true);
boxItem.removeEventListener(MouseEvent.MOUSE_OVER, boxItemMouseOver);
}
protected function boxItemMouseOut(e:MouseEvent):void
{
trace("mouse out");
var boxItem:MovieClip = e.currentTarget as MovieClip;
boxItem.addEventListener(MouseEvent.MOUSE_OVER, boxItemMouseOver, false, 0, true);
boxItem.removeEventListener(MouseEvent.MOUSE_OUT, boxItemMouseOut);
}
But whenever i move the mouse inside my MovieClip, the MOUSE_OUT event function is being called, although i still didn't leave the area taken by the MovieClip.
I managed to find out where my Problem is, but still can't fix it, i'm adding to my SWF a Cursor that replaces the icon of the mouse (I hide the mouse), once i add it the problem occurs, here is a simple example.
Code : Simple Source Code, Couple of classes
Set mouseChildren to false on boxItem.
1.. u have 'trace("mouse over")' in both functions
2.. first remove mouse over listener, than add mouse out listener
3.. i don't get, why do u need to declare new variable 'boxItem' when u can just write e.target.removeEventListener(..)
4.. it's impossible what u are talking, i caught several unnecessary code in few lines, so there is big chance u are doing somth wrong in your code, show us bigger piece of your code..
p.s. also, try mouseEnabled to false along with mouseChildren to false, but i doubt it will work
Listen for ROLL_OUT instead. MOUSE_OUT is dispatched when cursor left any of the nested chidlren of you MovieClip.

How to do "if Single Click" instead of "if MouseDown" in AS3?

I want to do a single click and have it not repeat the function if my mouse is still down if that makes any sense.
Currently I have it:
if (mouseDown)
{
avatar.moveABit( 0, -2);
sfxSoundChannel = moveSound.play();
}
and if I keep my Mouse Down it keeps repeating that. I want it to only work with a single click, and have to keep tapping to do it instead of leaving the mouse down.
You probably want
MouseEvent.MOUSE_CLICK
I would add an event listener on the object that is being clicked to listen for the click, and on the click run the handler function which would contain your move and soundplay code.
See this documentation.
You need MouseEvent.CLICK like so:
//Create a function (which moves avatar) to be called on mouse click
function moveAvatar(e:MouseEvent):void
{
avatar.moveABit( 0, -2);
sfxSoundChannel = moveSound.play();
}
stage.addEventListener(MouseEvent.CLICK, moveAvatar); //add mouse click event listener
EDIT: moveABit should not be using ENTER_FRAME event.
I don't know if I understood it correctly, maybe we'll need more of your code to understand what you really want.
I'm assuming that you're using some kind of loop (setInterval, Event.ENTER_FRAME) to check if the mouse button is down or not. If you are, I think you should change that to only fire inside a function like this:
function OnMouseDownHandler(event:MouseEvent):void
{
avatar.moveABit( 0, -2);
sfxSoundChannel = moveSound.play();
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDownHandler, false, 0, true);
If you use MouseEvent.CLICK event the OnMouseDownHandler Method will be fired only when you release the mouse button, using MouseEvent.MOUSE_DOWN will behave more like a "Tap".

Is every MOUSE_DOWN guaranteed a MOUSE_UP?

Are there any circumstances under which a Flash application could receive two MouseEvent.MOUSE_DOWN without a MouseEvent.MOUSE_UP in between?
In my ActionScript 3 application, I want to track the user dragging a sprite. My plan is to listen for a MouseEvent.MOUSE_DOWN, start an indefinitely repeating timer that records the mouse position, and stop the timer on MouseEvent.MOUSE_UP. Is that a good plan?
Click but do not release the button.
While keeping the button down move the cursor outside.
Release the button outside.
Come back inside and click again.
You will get two down event without an up event.
A better solution to drag-and-drop might be to listen MOUSE_MOVE event and in the event handler check buttonDown property. If the button is down while moving, this will be true, otherwise false.
EDIT: For stage even if you release the button outside the flash window then up event is fired. So for stage this can work, but still instead of timer using MOUSE_MOVE with buttonDown looks better to me. You can check yourself with the following code:
public class StageEventTest extends Sprite
{
public function StageEventTest()
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
}
private function onDown(evt:MouseEvent):void {
trace("down");
}
private function onUp(evt:MouseEvent):void {
trace("up");
}
private function onMove(evt:MouseEvent):void {
trace("move", evt.buttonDown);
}
}
it will miss the mouse up event if the mouse is outside of the stage and continue it's mouse tracking when mousing over the stage since the mouse up event was never called. this likely problem can be mitigated by using Event.MOUSE_LEAVE - forward the mouse leave event to the mouse up event handler so that if the user mouses away from the stage the mouse up event will be called.
Yes, but unless you are listening to the stage, I think you can miss the mouseup event if the mouse has gone outside the Flash movie. Nothing beats an experiment though.
Below you can find the code I always use for custom dragging. Normally, it should work fine. I listen to the MOUSE_MOVE-event for repositioning and tracking the sprite, but you can just as well use the Event.ENTER_FRAME-event or use a timer instead.
ObjectToDrag.addEventListener(MouseEvent.MOUSE_DOWN, startCustomDrag);
public function startCustomDrag(e:MouseEvent):void
{
_prevX= e.stageX;
_prevY= e.stageY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject); //REPLACE BY TIMER OR Event.ENTER_FRAME
stage.addEventListener(MouseEvent.MOUSE_UP, stopCustomDrag);
}
private function dragObject(e:MouseEvent):void
{
ObjectToDrag.x += _prevX - e.stageX; //OR ANY OTHER CALCULATION
ObjectToDrag.y += _prevY - e.stageY; //OR ANY OTHER CALCULATION
_prevX= e.stageX;
_prevY= e.stageY;
}
public function stopCustomDrag(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject); //REPLACE BY TIMER OR Event.ENTER_FRAME
stage.removeEventListener(MouseEvent.MOUSE_UP, stopCustomDrag);
}

Is it possible to remove an eventListener temporarily (i.e. until a function has been executed)

I am doing actionscript 3 at the moment and was wondering if it was possible to remove and eventListner temporarily. I know of removeEventListener, however, that removes the eventListener completely and i cannot click the button again.
If you want some more details, here the exact problem. I have function that when a button is pressed, an object appears. In the function which makes this object there is an eventListener which leads to a function which allows the user to press that object. When you press that object it disappear and the button will animate. However, since the original eventListener still exists, you can press the object while in motion and create a new object. So to the point: What i want to do is disable the eventListener while the button is moving, and reactivate it when it stops.
The best way is to simply use a flag which tells the function if the animation is complete or not. Here's an example of what I'm talking about using TweenLite as tween library:
public class CreateButton extends Sprite{
private var animating:Boolean = false;
public function CreateButton(){
this.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
}
private function onClick(event:MouseEvent):void{
if(this.animating == false){
// Trigger creation functionality
TweenLite.to(this, 0.5, {/* Parameters for the actual animation */ onComplete:animationComplete});
this.animating = true;
}
}
private function animationComplete():void{
this.animating = false;
}
}
It is best practice to remove the listener if it's functionality is to be disabled. You could however set the .mouseEnabled to false if you want to disable it's click functionality without removing the listener.