Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Code Snippets / [DBP] - Better mouse management

Author
Message
Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 30th Oct 2012 12:27 Edited at: 25th Jan 2013 09:38
This thread prompted me to write this snippet. It'll handle all the timing and flags necessary for checking the various states of the mouse buttons and pointer.

Simply call gosub initMouse at the top of your program then at the top of your game loop make a call to updateMouse().

With the exception of the mouse X,Y values, all the rest return boolean values.

Command list:
__mouse.leftButton.down
__mouse.leftButton.clicked
__mouse.leftButton.doubleClicked
__mouse.leftButton.tripleClicked
__mouse.leftButton.clickCount
__mouse.rightButton.down
__mouse.rightButton.clicked
__mouse.rightButton.doubleClicked
__mouse.rightButton.tripleClicked
__mouse.rightButton.clickCount
__mouse.scrollButton.down
__mouse.scrollButton.clicked
__mouse.scrollButton.doubleClicked
__mouse.scrollButton.tripleClicked
__mouse.scrollButton.clickCount
__mouse.scrollButton.scrollUp
__mouse.scrollButton.scrollDown
__mouse.isMoving
__mouse.pos.x
__mouse.pos.y
__mouse.leftButton.isDragging
__mouse.leftButton.hasDragged
__mouse.dragStartPos.x
__mouse.dragStartPos.y
__mouse.dragEndPos.x
__mouse.dragEndPos.y


You can use __mouse.private.doubleClickDelay to set the double click delay, however, it already pulls it from the system automatically.


V.1



V.2



V.3


"You're not going crazy. You're going sane in a crazy world!" ~Tick
Burning Feet Man
11
Years of Service
User Offline
Joined: 4th Jan 2008
Location: Sydney, Australia
Posted: 30th Oct 2012 12:40
Good stuff. For me, I preferred having my Mouse as an array, as per the original thread. It's much easier to loop, as you're essentially doing the same checks for each mouse button.


Mouse(1) = Left Mouse Button
Mouse(2) = Right Mouse Button

It makes it a dash easier to switch around the controls too, say if you wanted to pan with the middle mouse button, but then someone prefers the right mouse button to pan, all that's needed to be changed is a simple number.

Help build an online DarkBASIC Professional help archive.
DarkBasic Help Wikia
Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 30th Oct 2012 14:25
Oh ok, so that's why you wanted to use arrays.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Sasuke
13
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 30th Oct 2012 16:12
That's pretty, thanks Phaelax

Note: Vector2D should be Point2D since Vectors are floats and Points are integers.
Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 24th Jan 2013 05:16
Nice snippet, will definately use it and credit you.

I would like to add a triple click feature for alt actions; EG in firefox treble click selects the whole text of an element.

What would you suggest; adding clicks per second and triggering if greater than 2?

Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 24th Jan 2013 08:42 Edited at: 24th Jan 2013 09:21
I've updated the code, newest version is in first post.

Basically, I replaced this:



With this:


That's about the gist of it. I never planned on supporting more than a double click, but rewriting it now can support any click count you want. I added a tripleClick command, but you can easily just called clickCount and check for any number of clicks you want.

For instance, if you wanted a quadruple click, you'd write the code as such:


You have to add the check in there for if the button is clicked, otherwise you'll have to manually check that your action isn't repeated multiple times. The clickCount will return the current click count for as long as the 'double click' time delay lasts beyond the last click.

I'm not too fond of the way it resets the click counters for each button. Because you'd have to update 3 statements if you added a new button. Not a big issue for this snippet, but I think it's a bad practice to have to manually keep things in parallel in such a way.

I have also added in scroll commands so you know when the mouse is scrolled up or down.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 24th Jan 2013 09:19
Wow that was fast. Nice one. Can't wait to use it.

Its going to be used to select a line of text in a text box (instead of word select with double click) and for alternative icon/button actions.

Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 24th Jan 2013 09:30
I had to look at the code for a minute to remember how it worked. At first, it confused me how the double click feature even worked in the first place! At least now if you start a series of clicks, clicking any other button.


If you just grabbed the code, get it again once you see this post. I correct a mistake and updated the click counter variables slightly to address the poor design issue I felt it had.

And if you think of any other mouse commands I should add, let me know.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 25th Jan 2013 06:13 Edited at: 25th Jan 2013 06:18
Quote: "And if you think of any other mouse commands I should add, let me know."


Since I will use your library I am going to lay out a plan of what mouse features I need. You can add these commands if you want, but unless you beat me to it, I will create them over time.

I am also taking the opportunity to think about this carefully because it is a good opportunity to wrap this topic up.

The library as it stands covers most typical game mouse commands; to be honest any more commands would be more of a convinience than a necessity, but for the few working on large games, there is that small percentange of end users who want to go extreme and then there is the latest gimmicks and technologies.

I'd say multi-button mouse events would be good to add.

Mouse button 4,5,6 etc ; although I can't seem to get DBPRO to detect my 5th button... It detects mouse button 4 in the 4th bit ( 8 ), but not button 5 ( 16 ).


The other things that are vital for most people is 1st mouse over events, 2nd dragging, and 3rd, mouse gestures.



Mouse over

Basic
Most mouse events require a clicking zone, and most DBP programmers would have to check what zones the mouse is over before firing a click event.
Any additional features and alternatives of that shouldn't be a bad idea to throw in. Feel three to use that code if you need.

Intermediate
In intermediate projects, one would need to know how long the mouse over event occurs for and how long the mouse is idle for
. Good example is renaming files with slow double click whilst keeping the mouse still. Or mouse hints, although some hints wouldn't need a delay or could simply transition if they did.

Another practical feature is storing the idle position, and use it to determine how far the mouse moved from the idle position. If the mouse moved by 1 or 2 pixels, it would be harsh to consider that a mouse move event in certain situations. Having a movement vector could allow one to determine whether the mouse moved enough to warrant taking a specific action; maybe even an idle threshold.

Having an event data UDT would be a good idea, something that supplies information about mouse movement; you never know what might come handy.

Advanced
For those few advanced projects out there; I really doubt there will be many guys making advanced projects, so the basics come first. However, us guys need to structure mouse over events into zones. We'd want to know what mouse over zone has the focus, is topmost and highest in priority (See dragging intermediate for an example).

Checking for a button click in an area and an object click in the same area at the same time for example is inevitable as it stands. If a UI zone covers an object zone, the UI zone would have the priority.

Dragging

Basic
I think most DBP users would have liked a drag function which returns a start location, current mouse location, release location and release button.

Intermediate
Similar to other mouse events, a zone, an area of influence would be taken into consideration. Anyone creating draggable windows and items would need to determine what list of zones the drag event started from, what zone/s the mouse is currently in whilst the button is held, and what zone/s the mouse release occured in. What is being dragged is the responsibility of another library, however it would be wise to store the zone ID/S in the event which could be used as an external pointer to the external item being dragged.

If any zone is under the mouse, we'd need a way to be aware of this in the form of a list. Matrix1 zones are a good example.

Advanced
For those few advanced projects that end up using this; I think again, we would need ordering of zones of influence. Whilst on the intermediate level, all zones are listed, on the advanced level, the zone of highest priority / topmost zone would need to be indicated somehow.

If the start drag zones are 1,2 and 3; if the topmost drag zone happens to be 3, then zone 3 is set as the primary drag zone; although 1 and 2 are were technically being dragged, the programmer could choose to refer to the primary zone, or perhaps the zones could be sorted in an ordered list.

Also, if the drag zones are 1,2 and 3; if the topmost zone is 3 but the zone with the highest priority is 1, then 1 is the primary / first drag zone. Where would this be useful? Modal UI, without having to remember the layering order of 100s of zones, simply raise priority to overshadow all underlying mouse zones.

Also, if the drop zone is 4, 5, and 6; the topmost or highest priorty drop zone would need to be determined.

Additionally, relationships between zones; returning if there is a drag drop event occuring in two zones in the same group, or that share a flag in a 32bit/64bit variable. So for example, the user cannot drag a button macro onto a character, or a game file onto an action button.


Gestures

Basic
Once gesture mode is switched on some how; dragging with a mouse / button down to the left, right, up or down could trigger a simple scroll / pan / rotate gesture UDT property for scroll, pan or rotate based elements. The difference between this and simply using the MouseMove functions is that there needs to be a minimum and maximum motion for the gesture to be detected.

Intermediate
I once was asked to make a martial arts game for someone where the character would perform certain moves using mouse gestures (might point this idea to Dimis). I've lost the source code but what I think I did was record nodes during mouse movements after idle events, start from the first node once the motion stopped, then checked what primitive directions each node was facing and added each direction's name to a string

EG: "LEFT-UP-LEFT", or "UP-HOLD-DOWN-HOLD", or "LEFT-UP-UP-UP" for a long L shape or "DOWNLEFT-UPLEFT" for diagonal v motion

After a second the string use used as a bound command.

So, for tablet / laptop users, this stuff would be great. In fact I have a standard desktop mouse which can be programmed to perform different actions by gesturing in staight lines and L shapes.

Most 3D games don't support it, but its getting more popular, especially in the touch screen / netbook / tablet market. For each keyboard button and shortcut, multiply that by the amount of gestures you can do, gives you unlimited range of fast actions, which can be illustrated with on screen feedback.

Advanced
I don't have Windows 8 or a device that supports multiple drags at the same time. But I think I am way outnumbered. If you know how all of that stuff works, please do provide us with a helper library, perhaps as an addon to code for such systems.


Thanks for all the code you have already provided.

Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 25th Jan 2013 09:24 Edited at: 25th Jan 2013 09:44
Quote: "'d say multi-button mouse events would be good to add."


You mean just doing something like detecting if both left and right mouse buttons are down at the same time?




I think zones would be more up to the GUI than the mouse system. Letting the GUI determine which zones/components have top layer focus.

I don't have Win8, so I don't know what you mean about multiple drags. But as far as gestures go in general, I don't have a clue where to begin.

I've added dragging events, but I'm still trying to see if there's a better way to manage multiple buttons so I don't have to repeat so much code. For now, you can drag with the LEFT button.



Once the drag feature has been triggered, isDragging will continue to return 1 until the button is released. hasDragged will only return 1 once the button is released, allowing you know the drag operation has completed. To initiate a drag, hold down the mouse button then start moving. It's only triggered once the mouse moves more than 5px from the starting position.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 25th Jan 2013 09:37 Edited at: 25th Jan 2013 09:38
I could add functionality to trigger events when a mouse enters or leaves a zone/component, but the reason I say it should be up to implements a GUI is because DB has no set standard for GUI components and how that info is stored. If you were to maintain array of all regions the mouse can enter along with each zone's current layer (think z-index), then it's a simple matter of looping through them all and checking each one. Not overly complex, but I didn't want this library to require multiple functions, just one easy all inclusive function.

For handling an unknown number of buttons I'd probably have to rewrite it using arrays some how. Who needs more than a 3 button mouse anyway


Btw, updated code is in first post.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 25th Jan 2013 09:40 Edited at: 25th Jan 2013 09:46
Quote: "You mean just doing something like detecting if both left and right mouse buttons are down at the same time?
"


Detecting mouse buttons other than left, right and middle. I have a 7 button mouse.

Quote: "I think zones would be more up to the GUI than the mouse system. Letting the GUI determine which zones/components have top layer focus"


100% true in logic, but not easiest in DBPRO. Proove me wrong, but in most cases there is no GUI system. Sometimes you only have objects and sprites.

Sure, if you use BBB GUI, then no need for this library.

IF you use Top GUI, which supports no double/triple click or dragging other than windows, then you'd have to tweak it to work with your library; and it alone has 7k lines and 100s of click conditions.

Would be 10 times easier writting something like: If __mouse.rightButton.downZone = 10 And guiButton(paramters) or perhaps If MouseZone(1).leftClicked And guiButton(paramters) than going into Diggseys code and adding zone parameters to all of his functions. Quite scary. If you haven't used it; it can have windows overlapped, but only one layer of panels, no panels in panels.

So say I drag a panel (icon) over another, you get problems.

If this was C++ or something then yes, we could override his classes, but not in DBPRO, so I will prefer to add my zone conditions to your 500 lines than in his 7k.

I am going to work soon, so will be back later.

Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 25th Jan 2013 10:01 Edited at: 25th Jan 2013 10:06
Oops, we posted about the same time.

Perhaps zones and gestures could be done seperately. A UDT in the main library could be a means of integration, simply run functions that are available. Add what ever one needs.

I get the impression you don't want to use Matrix1 utilities zone commands, there are zone groups and theres a Point In Zone function there but it has no layering features.

Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 26th Jan 2013 05:19 Edited at: 26th Jan 2013 06:28
Minor question, how do you detect first whether the user double clicked before checking if they single clicked?

Something like this?


Oh, and...

Quote: "Who needs more than a 3 button mouse anyway"


You should try it out for yourself, you would never go back to 3 buttons. I got DBPRO snippets in my mouse memory, I can drag one way to insert a function seperator, click a certain button to run certain other macros...

Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 26th Jan 2013 13:59
Quote: "Minor question, how do you detect first whether the user double clicked before checking if they single clicked?"

You don't really. If you double click, a single click action is triggered as well. Windows response the same way. Just try triple clicking the browser address bar. Click once, the caret moves to position, double click it selects a word, triple selects the whole string. Triple clicking won't skip a single or double click.

"You're not going crazy. You're going sane in a crazy world!" ~Tick
Chris Tate
DBPro Master
10
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 26th Jan 2013 20:34
OK, that makes sense. I'll keep that in mind.

Login to post a reply

Server time is: 2019-08-24 08:40:48
Your offset time is: 2019-08-24 08:40:48