Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411516 Posts in 69380 Topics- by 58436 Members - Latest Member: GlitchyPSI

May 01, 2024, 08:46:26 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Advanced Mouse Handling in AS3
Pages: [1]
Print
Author Topic: Advanced Mouse Handling in AS3  (Read 4424 times)
bateleur
Level 10
*****



View Profile
« on: July 15, 2010, 05:10:35 AM »

I have an AS3 Sprite for which I need to handle a variety of complex mouse interations. I have event handlers installed for:

* MOUSE_DOWN
* MOUSE_UP
* MOUSE_MOVE
* CLICK
* DOUBLE_CLICK

And am having to write some rather nasty hacky code as a result. The trouble is, when the user performs a mouse down-move-up sequence this results in a CLICK event at the end (as well as the MOUSE_UP I actually want). And similarly there are other cases where you can generate unwanted combinations of CLICK, DOUBLE_CLICK and MOUSE_UP.

What I actually want is the following:

* Moving the mouse with the button down means I never get CLICK or DOUBLE_CLICK.
* If DOUBLE_CLICK would fire then CLICK will never also fire.

But I can't come up with any way to implement this other than keeping records of what I receive, waiting a few frames and then sorting everything out with the benefit of hindsight.

So I thought it was worth asking... is there a less horrible way to achieve the same result?
Logged

Cagey
Level 1
*



View Profile WWW
« Reply #1 on: July 15, 2010, 05:22:21 AM »

The way i usually do this sort of thing is for each listener i set a boolean flag. For example in the CLICK listener i set mouseClicked to true. Then in an ENTER_FRAME listener you do all your logic that is dependant on the mouse/key listeners, and reset the applicable values to false (in this case you would reset mouseClicked to false at the end of each frame).

Hope that makes sense.
« Last Edit: July 15, 2010, 05:32:06 AM by Cagey » Logged

Jonathan Whiting
Level 2
**



View Profile WWW
« Reply #2 on: July 15, 2010, 05:32:06 AM »

It sounds to me like you'd be best off dumping the CLICK and DOUBLE_CLICK handlers, and just writing some code using the raw MOUSE_DOWN, MOUSE_MOVE and MOUSE_UP events to get the exact effects you want.

To be able to discount double clicks as also being a single click event you will have to (at minimum) store the time you first clicked, and when the "double-click" time has expired without another click decide that it must have only been a single click, and trigger whatever you like.  It's a bit of a pain, but afaik it can't be helped.
Logged

st33d
Guest
« Reply #3 on: July 15, 2010, 07:37:52 AM »

What I usually do is have a few global variables.

frameCount

mousePressed
mousePressedCount
mouseReleasedCount

At the end of each ENTER_FRAME event frameCount is increased by one (it would take 2 years for the game running constantly to reach int.MAX_VALUE).

Then I have these two events:

Code:
public function mouseDown(e:MouseEvent = null):void{
mousePressedCount = frameCount;
mousePressed = true;
}

public function mouseUp(e:MouseEvent = null):void{
mouseReleasedCount = frameCount;
mousePressed = false;
}

I no longer have to whack all the mouse interaction into those events. At anywhere in my code I can simply test

if(frameCount == mousePressedCount)

And I know that the user has just clicked down the mouse in that exact frame.
Logged
agj
Level 10
*****



View Profile WWW
« Reply #4 on: July 15, 2010, 09:12:31 AM »

I have a class that reads mouse ups and mouse downs, and sends an event for each click it detects, keeping a count of them; so if you want a single click, or a double click specifically, you check that variable.
Logged

Triplefox
Level 9
****



View Profile WWW
« Reply #5 on: July 15, 2010, 09:33:15 AM »

I agree with the suggestions to not use CLICK or DOUBLE_CLICK on something that also has MOUSE_DOWN and MOUSE_UP. The CLICK events are a convenience for designers, and when you start writing fine-grained behaviors they just get in the way. GUI stuff always has a lot of fiddly tuning involved to feel good. Example:

HorizSlider.hx

This is code describing a horizontal slider bar in the little GUI I rolled up for Fireball. You'll notice that I wrap Flash mouse events into my own input event system so that I can do mock events, and I have the widgets poll for events rather than attach listeners, so that I can disable behavior by changing which loop I'm using, rather than changing state on a bunch of free-floating objects.

To get the slider's behavior close to that of a Windows-type bar, I have to consider multiple concerns:

Am I touching the bar, or the slider on the bar?
Where did I touch the bar?
Am I dragging the slider(i.e. did my mouse down start on the slider, and are consecutive moments occurring while the mouse is down?)
If I'm using the keyboard, is the slider focused, and how much do I move it?

And then I have stuff to draw it. This is the part that I dislike the most since it gets really specific to one graphic design idea and to Flash's graphics APIs.

I can easily imagine that if I wanted behaviors for click, double-click, and drag all at once, I'd be keeping some timers around as well as the held state.
Logged

bateleur
Level 10
*****



View Profile
« Reply #6 on: July 15, 2010, 12:04:17 PM »

Thanks for the answers guys... although all this amounts to is confirming I have no good options.

Using ENTER_FRAME is my existing hack for which I was expressing distaste.

Not using CLICK is all very well, but not using DOUBLE_CLICK is poor style because the user sets their double click timing via their OS so it's not for me to redefine how long it should be.

Not to worry. I'll just sulk. Like this: Panda
Logged

agj
Level 10
*****



View Profile WWW
« Reply #7 on: July 15, 2010, 06:46:12 PM »

I was wondering if there was a way to check the double click speed set in the system, kind of how you can check how many lines the mouse wheel advances per notch, but I didn't find anything.
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #8 on: July 16, 2010, 02:26:38 PM »

You cannot have mutually exclusive CLICK and DOUBLE_CLICK. The amount of latency it would cause to implement this is unacceptable. You need to rethink how your UI works, not only because of the latency issue, but also because users expect that CLICK-DOUBLE_CLICK has the same effect as just DOUBLE_CLICK. While it is possible to "undo the click" when getting the double click, I would strongly recommend clicking be a safe, idempotent, operation.

Note if you are trying to distinguish between dragging and double clicking, life is easier. Dragging can be triggered by mouse movement while down, rather than mouse down, which makes it feasible to be mutually exclusive.
Logged
bateleur
Level 10
*****



View Profile
« Reply #9 on: July 17, 2010, 02:39:07 AM »

I would strongly recommend clicking be a safe, idempotent, operation.

It sort of is... but because it brings up a menu (with double click being "don't bother with the menu, just give me the default action") the resulting flicker on double click just looks bad.
Logged

Draknek
Level 6
*


"Alan Hazelden" for short


View Profile WWW
« Reply #10 on: July 17, 2010, 02:58:30 AM »

Double-click for default action seems unintuitive to me.

Can you bring up the menu so that the default action is always under the mouse cursor? Then you get basically the same thing but don't need to special-case double-clicking.
Logged

agj
Level 10
*****



View Profile WWW
« Reply #11 on: July 17, 2010, 09:23:42 AM »

The current solution seems fine. Just wait a bit after the first click, and if no double-click is triggered, open the menu. This behavior can be found in some Windows programs' taskbar icon, for instance.
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #12 on: July 17, 2010, 02:19:25 PM »

Why not have the menu triggered by click-and-hold? Or you can apply a quick fade to the menu, to make it's flicker less jarring without compromising latency.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic