Sign in to follow this  

[SOLVED] Help with DirectInput cursor screen position.

This topic is 3661 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, Is there a commonly used way of creating screen coordinates from relative/absolute directinput cursor coordinates? One idea I thought of was to add the current absolute position to the top-left screen position of the client rectangle. In addition, I'd GetClientRect() and use those bounds to clip the cursor. Another idea I thought of was to use ClipCursor() to have windows do the clipping for me, however I'm not sure if this will play nice with DirectInput. In the past I've just used windows directly for mouse input because it was MUCH MUCH easier, however since I'm using SDL now I can't exactly do that. I don't want to get into the details as to why I'm not using SDL's input routines. SDL doesn't work very well in that area, let's leave it at that. I haven't tried any of those ideas yet, mainly because I'm pessimistic about how well they would work. Could you guys give me a few ideas? Thanks. [Edited by - MrDoomMaster on December 5, 2007 11:07:07 AM]

Share this post


Link to post
Share on other sites
You should never be using DirectInput for mouse input. And if you need screen coordinates, that just screams "GUI" to me, which means DirectInput is completely unsuitable. Just use either window messages or GetCursorPos().

DirectInput will usually be slower than using window messages (Although it'll be a tiny, tiny difference), since all it does is create a new thread to read window messages for you.
DirectInput is far more complicated to implement than using window messages.
DirectInput doesn't apply pointer balistics to the mouse cursor, meaning the mouse feels really weird - like a Mac cursor. In Windows, try moving the mouse 6 inches really fast, then do it really slowly and notice how the distance travelled is different - that's pointer balistics.
DirectInput works in a different coordinate system, making it's responsiveness dependant on the mouse DPI (Which you don't want for a GUI app, and you can get via Raw Input otherwise).

Overall, the one, single reason to use DirectInput for mouse input is if you really need high DPI mouse input, and you really need to run on Windows 98 (Which is over a decade, and 4 Windows versions old).

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
You should never be using DirectInput for mouse input. And if you need screen coordinates, that just screams "GUI" to me, which means DirectInput is completely unsuitable. Just use either window messages or GetCursorPos().

DirectInput will usually be slower than using window messages (Although it'll be a tiny, tiny difference), since all it does is create a new thread to read window messages for you.
DirectInput is far more complicated to implement than using window messages.
DirectInput doesn't apply pointer balistics to the mouse cursor, meaning the mouse feels really weird - like a Mac cursor. In Windows, try moving the mouse 6 inches really fast, then do it really slowly and notice how the distance travelled is different - that's pointer balistics.
DirectInput works in a different coordinate system, making it's responsiveness dependant on the mouse DPI (Which you don't want for a GUI app, and you can get via Raw Input otherwise).

Overall, the one, single reason to use DirectInput for mouse input is if you really need high DPI mouse input, and you really need to run on Windows 98 (Which is over a decade, and 4 Windows versions old).


What about using DirectInput for keyboard state?

Additionally, it would be a lot more difficult (it seems) to do relative cursor motion using GetCursorPos() in windows. I can't continuously reset the position of the cursor since I also care about the absolute screen position too. So, I could just GetCursorPos() and calculate the delta from the last GetCursorPos() and couple that with ClipCursor(), however once the cursor reaches the edge of the clip rectangle, it won't be able to move any further and thus the mouse is moving with no delta calculated, when in fact it *should* still report relative movement.

Any ideas for the two inquiries above? Thanks for your input, you really have shown me the light. You know, I never liked DirectInput to begin with. It's hard to initialize and too much code bloat. In addition, relative cursor movement reported by GetDeviceState() for a mouse doesn't work properly when the cursor moves outside of the client rect bounds.

Share this post


Link to post
Share on other sites
Quote:
Original post by MrDoomMaster
What about using DirectInput for keyboard state?

Nope, the Windows API does a better job of that too. Microsoft themselves say (somewhere in this article) that DirectInput is now only useful for joystick input. Between Windows messages and GetAsyncKeyState, you have all the keyboard control you need.

As for the implementation details of Windows mouse input, it really isn't so difficult. In windowed mode, developers tend to hide the mouse and reset its position as you guessed. It sounds pretty messy, but it's no different from what DirectInput does under the hood. This will give you effectively boundless relative coordinates from which you can very easily recompute the absolute coordinates if necessary. The only bother is locking and freeing the mouse in a way that won't annoy the user. In particular, make sure that you handle alt-tab correctly or things will get very irritating.

Share this post


Link to post
Share on other sites
Quote:
Original post by TheAdmiral
Quote:
Original post by MrDoomMaster
What about using DirectInput for keyboard state?

Nope, the Windows API does a better job of that too. Microsoft themselves say (somewhere in this article) that DirectInput is now only useful for joystick input. Between Windows messages and GetAsyncKeyState, you have all the keyboard control you need.

As for the implementation details of Windows mouse input, it really isn't so difficult. In windowed mode, developers tend to hide the mouse and reset its position as you guessed. It sounds pretty messy, but it's no different from what DirectInput does under the hood. This will give you effectively boundless relative coordinates from which you can very easily recompute the absolute coordinates if necessary. The only bother is locking and freeing the mouse in a way that won't annoy the user. In particular, make sure that you handle alt-tab correctly or things will get very irritating.


However if you continuously modify the cursor position for the purpose of calculating a relative position, you will be unable to get the screen position. For example, each object in my code that is interested in receiving mouse motion events register a virtual function, which gets called anytime the mouse moves. It contains both absolute (screen position) and relative coordinates. For example:

virtual void HandleMouseMotion( unsigned int screenX, unsigned int screenY, int relativeX, int relativeY );

See? It's difficult to figure out a way to calculate one without completely prohibiting the ability to calculate the other.

Share this post


Link to post
Share on other sites
Quote:

However if you continuously modify the cursor position for the purpose of calculating a relative position, you will be unable to get the screen position.



Just pick a starting location, set it as the absolute location, then keep adding the relative position to your absolute location.

Or of course, the easier way to do this is to only "lock" the cursor position when you're using the mouse for control input (such as looking around in FPS), and then "unlock" the mouse and use the Windows cursor position when you need a pointer for a GUI or menu.

Share this post


Link to post
Share on other sites
I get the information from directInput with a couple of functions in my home-made directInput class. GetMouseXPos and GetMouseYPos.
Then all you have to do is create a sprite structure with at least the members posX, posY and visibility and a pointer to a SRV, update the posX and posY members with the mouse information every frame, turn visibility off when you're in a menu etc. That's at least the way I do it.

Share this post


Link to post
Share on other sites
By "reset the mouse position", what exactly do you mean?

When you start reading relative coordinates, you should store the current position of the mouse, then compare the position of the mouse each fram with that initial position. There's a Win32 function to read mouse input when it's not over your window (BeginCapture() or something similar).

As for keyboard input with DirectInput, that's even worse [smile] Link.

Share this post


Link to post
Share on other sites
Thanks guys.

Due to the information I've received in this thread (very valuable information at that), I've completely removed DirectInput from my input class. In addition, instead of sending both relative & screen position x,y coordinates to the same callback, I have now split it up into two callbacks.

One receives relative cursor motion, the other receives screen-space cursor motion (screen coordinates). There is also a function called 'ResetCursor()' which basically resets the cursor back to the center of the screen. This method is the last function you call in the relative motion callback. The screen space coordinates don't require such a function call.

The functions I'm using for input:

GetKeyboardState() - 0x07 and up (for keyboard input only)
GetAsyncKeyState() - 0x00-0x06 (for mouse button input)
GetCursorPos() - For grabbing cursor position.

Let me know if all of that sounds okay. Thanks guys!

Share this post


Link to post
Share on other sites
Sounds reasonable. Although personally I'd just use window messages and keep track of keys and buttons as they're pressed and as the mouse is moved. Pretty much the same as you have now though.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Sounds reasonable. Although personally I'd just use window messages and keep track of keys and buttons as they're pressed and as the mouse is moved. Pretty much the same as you have now though.


However I can't use windows messages because I'm using SDL. SDL has its own version of mouse/keyboard input control but it is buggy depending on your input settings in SDL.

Secondly I don't want to use it, especially for mouse input, since the overhead of windows constantly spamming WM_MOUSEMOVE messages is greater than a simple GetCursorPos() every tick of the game.

Thanks for the suggestions though.

Share this post


Link to post
Share on other sites
Quote:
Original post by MrDoomMaster
However I can't use windows messages because I'm using SDL. SDL has its own version of mouse/keyboard input control but it is buggy depending on your input settings in SDL.
Ah, fair enough.

Quote:
Original post by MrDoomMaster
Secondly I don't want to use it, especially for mouse input, since the overhead of windows constantly spamming WM_MOUSEMOVE messages is greater than a simple GetCursorPos() every tick of the game.
Well, the application window is getting sent WM_MOUSEMOVE message all the time anyway, whether you want/use them or not. But your first point is reason enough [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil SteveWell, the application window is getting sent WM_MOUSEMOVE message all the time anyway, whether you want/use them or not. But your first point is reason enough [smile]


Well if I wanted to go back to DirectInput and use exclusive mode on the mouse device, windows would not report the mouse messages according to the documentation. However that is out of the question, since that small benefit definitely does not outweigh the other bad things. In any case, I'm happy with what I have now. Thanks to you guys I have a great input class now. Thanks again.

Share this post


Link to post
Share on other sites
Ah, I see. If I remember correctly, when you request raw input (Which DInput does), you get raw input messages instead of mouse messages (Which makes sense, since mouse messages are a higher abstraction of raw input really).

In any case, the performance difference between any of this is so small it's really not worth worrying about.

Share this post


Link to post
Share on other sites

This topic is 3661 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this