SFML community forums
General => General discussions => Topic started by: Laurent on July 05, 2011, 11:19:34 pm
-
Hi
I've totally broken the sf::Input class. It has disappeared and is replaced with three new static classes: sf::Keyboard, sf::Joystick and sf::Mouse. These are now connected directly to the OS functions, and thus are no longer connected to a particular window.
The consequence is that there's no more bug related to focus, etc.
I've added a few features to joysticks: you can check their connection state, via sf::Joystick::IsConnected or the new JoystickConnected / JoystickDisconnected events.
I've also renamed/reorganized a few things.
I've implemented sf::Window::GetCursorPosition.
Special note on sf::Mouse::GetPosition: to be useful, it doesn't return the position in desktop coordinates, but rather in coordinates relative to the current focus window (the one which has the mouse cursor over it).
The OS X implementation is not done yet, but it will be updated by Hiura as soon as he can.
The C, .Net bindings and the online doc are up-to-date.
Have fun :)
-
Awesome Laurent, thanks! Luckily I only have a few references to the input class. Any chance of getting a Mouse Released event added to the sf::Mouse class?
-
Amazing job Laurent. It feels far more structured than before.
-
Just now that I thought my Action system would be finished :D
The three classes are not directly linked to a window, so I will need to filter the correct events out (since realtime inputs are also able to trigger callbacks). Is there a way to check whether a SFML window is currently focussed? Or do you have another suggestion?
In general, the separation of sf::Input sounds like a good solution, I have to examine it in detail :)
-
When I thought I could start working on GGE because rbSFML was done you come in and ruin everything for me =/
Ah well it's nice with the system and much needed but it means major remake in rbSFML and GGE... maybe shouldn't pick up more projects that depends on SFML2? :wink:
UPDATE: I would like to propose a change... It feels kind of stupid to have to pass the ID of the joystick all the time. Couldn't you wrap this inside an object better?
sf::Joystick joystick0( 0 );
-
Those are great news, good work Laurent :)
-
Any chance of getting a Mouse Released event added to the sf::Mouse class?
Sorry, I don't get what you mean. There is a MouseButtonReleased event, and it has nothing to do with sf::Mouse.
I would like to propose a change... It feels kind of stupid to have to pass the ID of the joystick all the time. Couldn't you wrap this inside an object better?
- it would't be consistent at all with the two other classes
- I don't like the semantics that the class would have ;)
-
Can we somehow find out whether a realtime input state belongs to the SFML window (especially for sf::Mouse)? I believe it is sometimes useful to check if the mouse is being clicked inside the window.
sf::Mouse::GetPosition() returns the position in two different coordinate systems, depending on whether the mouse is above a window or not? Isn't that confusing without a further option to check which coordinate system is actually used?
-
Can we somehow find out whether a realtime input state belongs to the SFML window (especially for sf::Mouse)? I believe it is sometimes useful to check if the mouse is being clicked inside the window.
No, the purpose of these classes is to get rid of any window/event stuff. It just says what happens on the devices.
But don't forget events... ;)
sf::Mouse::GetPosition() returns the position in two different coordinate systems, depending on whether the mouse is above a window or not?
Indeed.
Isn't that confusing without a further option to check which coordinate system is actually used?
To be honest, I don't know what to do with this function. I tried to make it useful while still being simple. But in fact people should now use Window::GetCursorPosition -- it's just that it's not symmetrical at all with sf::Keyboard, sf::Joystick and sf::Mouse::IsButtonPressed.
-
But don't forget events... ;)
That means, to check for mouse buttons currently held down inside a window, I have to implement a bool array for all states and adapt its elements upon each MouseButtonEvent? Basically, the work formerly done by sf::Input must now be handcrafted, is there no simpler way?
Something like sf::Window::IsFocussed() should already be enough, this might be useful in other cases, too. Or I catch the focus events and enable/disable my callbacks accordingly.
To be honest, I don't know what to do with this function. I tried to make it useful while still being simple.
I fear that the current implementation is neither useful nor simple :P
I don't see how sf::Mouse::GetPosition() can be meaningfully used if the caller doesn't know what coordinates he gets back and has no way to find it out. Maybe an optional bool output parameter could help. But I see that this doesn't solve the actual dilemma... :?
-
Well, there is this:
static const Window* GetMouseFocusWindow()
But I think a sf::Window::IsFocussed() would be better even for other situations.
Maybe to avoid confusions there should be something like:
static Vector2i GetPosition() // get position in global coordinates
static Vector2i GetPosition(const Window& window) // get position in window coordinates
-
That means, to check for mouse buttons currently held down inside a window, I have to implement a bool array for all states and adapt its elements upon each MouseButtonEvent? Basically, the work formerly done by sf::Input must now be handcrafted, is there no simpler way?
"Button currently held down inside a window" is a flawed concept. What if the mouse leaves the window with the button still down? Or if the button is released outside the window? Or if it is pressed outside and moved over the window while still pressed? Do you say "true" or "false" in these situations?
I think people don't need more than two things: the current mouse position, and the pressed/released events. But maybe you have a use case in mind?
Something like sf::Window::IsFocussed() should already be enough, this might be useful in other cases, too. Or I catch the focus events and enable/disable my callbacks accordingly.
Don't forget that there are several definitions of focus (at least two): the keyboard focus and the mouse focus.
There's the Window::GetMouseFocusWindow() functions which is publicly available. I wanted to keep it as hidden/internal as possible, but if you feel like it may help you, you can use it ;)
I don't see how sf::Mouse::GetPosition() can be meaningfully used if the caller doesn't know what coordinates he gets back and has no way to find it out. Maybe an optional bool output parameter could help. But I see that this doesn't solve the actual dilemma...
I think the only alternative is to completely disable this behaviour and make sf::Mouse::GetPosition() always return desktop coordinates.
Any other solution would just add more ugliness to this thing.
-
Maybe to avoid confusions there should be something like:
static Vector2i GetPosition() // get position in global coordinates
static Vector2i GetPosition(const Window& window) // get position in window coordinates
I don't like having two different functions that do the exact same thing (Mouse::GetPosition(Window) and Window::GetCursorPosition()).
With this function I just wanted to make it simple to get proper mouse coordinates for people that use a single window (99% of use cases), instead of having something nearly useless.
By the way, I copied this behaviour from SDL 1.3... :lol:
-
"Button currently held down inside a window" is a flawed concept. What if the mouse leaves the window with the button still down? Or if the button is released outside the window?
I would return true as long as the cursor is in the window and the button is pressed.
I think people don't need more than two things: the current mouse position, and the pressed/released events. But maybe you have a use case in mind?
Consider a shooter: As long as the left mouse button is held down, the player fires. When he clicks somewhere outside the window (for any reason), this shouldn't trigger the weapon. You can't work with events here unless you store bool flags on your own.
I think the only alternative is to completely disable this behaviour and make sf::Mouse::GetPosition() always return desktop coordinates.
Any other solution would just add more ugliness to this thing.
That's what I thought too, but then, people will always use sf::Window::GetCursorPosition() and sf::Mouse::GetPosition() is hardly ever used. And as you stated, it is not optimal with respect to the symmetry, if people still need the window to get the mouse state, but not the keyboard or joystick state.
-
Obviously I was assuming that the Window::GetCursorPosition() was replaced by Mouse::GetPosition(Window).
One looking for mouse coordinates would look first for the Mouse class than for the Window. It's expected that mouse stuff is obtained from the Mouse class.
When he clicks somewhere outside the window (for any reason), this shouldn't trigger the weapon.
Depends, you may want to be friendly and trigger it anyway, maybe the user clicked outside by accident and would loose the game because of that. If you want specific behavior when clicking inside/outside you should handle it yourself.
I think the actual solution for mouse state is the simplest and cleanest, I find it intuitive as well.
-
One looking for mouse coordinates would look first for the Mouse class than for the Window. It's expected that mouse stuff is obtained from the Mouse class.
sf::Window::GetCursorPosition() is the counterpart to sf::Window::SetCursorPosition(). So you needed to put that into sf::Mouse, too. sf::Mouse would be connected with sf::Window, although it is intended to represent the global state.
-
I would return true as long as the cursor is in the window and the button is pressed.
Fine, but then it's slightly more complex than what sf::Input did.
Consider a shooter: As long as the left mouse button is held down, the player fires. When he clicks somewhere outside the window (for any reason), this shouldn't trigger the weapon. You can't work with events here unless you store bool flags on your own.
Working with events and flags is a common technique, now it's just that SFML no longer does it for you.
In this situation, I think the programmer will rather track the focus events to disable many other things in the game when the window loses focus, so there's no problem in fact.
That's what I thought too, but then, people will always use sf::Window::GetCursorPosition() and sf::Mouse::GetPosition() is hardly ever used.
I could use it in the Shader example :D
And as you stated, it is not optimal with respect to the symmetry, if people still need the window to get the mouse state, but not the keyboard or joystick state.
So... no solution?
-
Fine, but then it's slightly more complex than what sf::Input did.
Wasn't sf::Input at least intended to behave like this (but maybe due to the sf::Event background, there were technical deviations, not to say bugs)?
Working with events and flags is a common technique, now it's just that SFML no longer does it for you.
We're spoiled, I know :P
In this situation, I think the programmer will track the focus events to disable many other things in the game when the window loses focus, so there's no problem in fact.
Maybe I should do that too in Thor. I could manually look for focus events and stop the realtime input if the window has no focus. If people want to react to input outside the window, they can still complain, this should be easily configurable. Relying on the user-side handling of focus events is not a good idea when callbacks are involved, because then every listener function would have to check if the call is valid.
I don't know how well you know my Action system, but the intention is to make it easy for the user to react to both one-time events and "realtime events" (that is, a condition of a realtime state is true).
So... no solution?
It seems like sf::Mouse::GetPosition() only for global state would be the cleanest solution, but be prepared for tons of questions "why doesn't this return the mouse position?" :D
But I'll spend some more thoughts on it... In case I have another idea (unlikely), I would inform you ;)
-
One looking for mouse coordinates would look first for the Mouse class than for the Window. It's expected that mouse stuff is obtained from the Mouse class.
sf::Window::GetCursorPosition() is the counterpart to sf::Window::SetCursorPosition(). So you needed to put that into sf::Mouse, too. sf::Mouse would be connected with sf::Window, although it is intended to represent the global state.
And instead, we have window connected to Mouse.
I still don't like those cursor methods on the Window :roll:, it's a bit out of context. I personally would prefer to have get/set position on Mouse, with overloading to make it relatively to a window.
As alternative I though on something like TransformToLocal & TransformToGlobal instead of those Get/SetCursorPosition. This way Window becomes independent of the Mouse, and Mouse can stick with global independent coordinates.
The drawback is requiring an extra step to get window mouse coordinates.
-
I still don't like those cursor methods on the Window :roll:
You are right, users probably associate mouse and cursor functionality first with sf::Mouse.
As alternative I though on something like TransformToLocal & TransformToGlobal instead of those Get/SetCursorPosition.
Or just sf::Window::GetPosition(). There is already a SetPosition(), anyway.
-
Wasn't sf::Input at least intended to behave like this (but maybe due to the sf::Event background, there were technical deviations, not to say bugs)?
sf::Input was meant to record/accumulate what happens with events. It was never supposed to adjust states according to what happened unfocused, but... yeah in the end it just looked buggy :)
But I'll spend some more thoughts on it... In case I have another idea (unlikely), I would inform you
Thanks!
I still don't like those cursor methods on the Window , it's a bit out of context. I personally would prefer to have get/set position on Mouse, with overloading to make it relatively to a window.
That sounds good indeed... maybe I should try this direction. What I don't like is that something specific to a window would have to be specialized (I'm talking about the OS specific imlpementation) in sf::InputImpl (the backend of sf::Mouse) instead of sf::WindowImpl, like all other window-related functions. But yeah, it's an internal detail.
As alternative I though on something like TransformToLocal & TransformToGlobal instead of those Get/SetCursorPosition. This way Window becomes independent of the Mouse, and Mouse can stick with global independent coordinates.
The drawback is requiring an extra step to get window mouse coordinates.
It's an interesting concept as well, but in the end I don't think it would be a good solution.
Or just sf::Window::GetPosition(). There is already a SetPosition(), anyway.
If you mean "window cursor = global cursor + window position", then you'd get wrong results because it wouldn't take the window decorations in account.
-
That sounds good indeed... maybe I should try this direction.
I also think this is a good solution. To make it clear, you could provide differently named functions instead of overloads:
static Vector2i GetPosition(const Window& relativeToWhich);
static Vector2i GetDesktopPosition();
What I don't like is that something specific to a window would have to be specialized (I'm talking about the OS specific imlpementation) in sf::InputImpl (the backend of sf::Mouse) instead of sf::WindowImpl, like all other window-related functions. But yeah, it's an internal detail.
You could still make a private function in sf::Window and call it from sf::Mouse. You need a friend, but compared with the alternative, this seems like an acceptable price to pay ;)
If you mean "window cursor = global cursor + window position", then you'd get wrong results because it wouldn't take the window decorations in account.
True, that just came into my mind, should have thought about it more :)
-
The way I see it (application programmer POV), there should be two modes:
Mouse pointer mode:
- Used when the user needs to point and click things
- The pointer behaves normally
- A function to get the pointer position (desktop coordinates, e.g. 0x0...1920x1080)
- A function to get the pointer position within the window (possibly negative or greater than the window dimensions, and may not always correspond 1:1 to desktop pixels, consider e.g. compositing WMs)
- Different cursors possible for different windows/areas (handled by the GUI)
- ButtonPress and other such events that store the pointer position at the time the event occurred (necessary for precise clicks)
Relative motion mode:
- Used in FPS games and with various GUI widgets (e.g. draggable spinctrls)
- Cursor hidden (or doesn't move)
- A function to get the number of dots the mouse has moved since the last time it was read
- When switching back to pointer mode, the cursor is made visible at the position where it was before switching to relative movement
In an ideal case dots are much more precise than pixels: 2000 DPI mice are common but a few people would want just one inch of movement to move the cursor all the way across the screen and more. Also, there is no acceleration nor smoothing applied to dots, where pixels are suspect to the usual Xorg/Windows/OSX processing. This also has implications when touchscreens or other such input devices are used.
-
I've implemented the new Mouse::Set/GetPosition functions, and removed Window::Set/GetCursorPosition.
-
And I've already committed the wrap for it to rbSFML :D
I'm on FIRE!
-
Sounds good! I think I can now begin with the adaption of my Action system.
You chose the overload of GetPosition() instead of a more clear GetDesktopPosition()... Don't you think this might confuse users, especially beginners that expect the mouse position to be relative to the the window, when they use the most simple call sf::Mouse::GetPosition()?
-
You chose the overload of GetPosition() instead of a more clear GetDesktopPosition()... Don't you think this might confuse users, especially beginners that expect the mouse position to be relative to the the window, when they use the most simple call sf::Mouse::GetPosition()?
That will be a good test to see if users read the doc :)
-
That will be a good test to see if users read the doc :)
You already know the test result, don't you? ;)
But in the end, your forum is flooded with beginner questions :P
Just thought it is never a bad idea to make the interface expressive enough, so that the documentation need only be considered in case of doubt.
-
I agree.
Maybe I'll think about it again in a few weeks (people will hate me if I change the same code everyday).
-
(people will hate me if I change the same code everyday)
People like me? :twisted:
Though I would be a bit annoyed because if you overload a function like that then I have to mimic that polymorphism by using variable length argument on the bindings method... And that is a lot trickier than just simply wrap a function. And if you then on the same day would change that to a not overloaded function. That would mean my hard work would be for nothing... Yeah... hate is a good word :P
-
people will hate me if I change the same code everyday
Don't they hate you even more if you change it every week, so that they have already adapted all their code and can change it again? ;)
But I think apart from bindings like Groogy's, this change isn't problematic. As we concluded earlier, the method to get the desktop position is nearly useless anyway :D
-
But I think apart from bindings like Groogy's
and the Mac port. :roll:
-
In C++, you can directly implement overloaded functions, while Groogy has to find ugly workarounds. For the Mac port, you only need to rename the function.
-
For the Mac port, you only need to rename the function.
I was referring to that. If it's only a rename thing then it's fine, goes fast and everybody is happy. But if the API changes everyday (like sf::Input to what's now) I'll get crazy (OS X is a mess for low-level application, really! When I'll commit the update for the new input system you'll understand my pain.).
Laurent, I'm of course not saying that you should not change anything. Hell no! But don't do it every day, please. :lol:
-
Well, I'm not unhappy either if the SFML API doesn't change every day, since I have much dependent code, especially in Thor. But sometimes, API breaks are worth the new features :)
-
Don't forget that:
- SFML 2 is not even in alpha state so I can change whatever I want, whenever I want :lol:
- once SFML 2 is officially released, I won't break the API anymore in the 2.x branch
-
Now that SFML has sf::Vector2u for unsigned int, why don't sf::Mouse::GetPosition() and sf::Mouse::SetPosition() use it?
For example, it would simplify the usage with sf::RenderWindow::ConvertCoords(), even more if there were a direct overload to take vectors instead of separate unsigned ints.
-
Now that SFML has sf::Vector2u for unsigned int, why don't sf::Mouse::GetPosition() and sf::Mouse::SetPosition() use it?
I didn't see any reason to disallow coordinates outside the screen.
For example, it would simplify the usage with sf::Window::ConvertCoords(), even more if there were a direct overload to take vectors instead of separate unsigned ints.
Hmm that's true.
-
I've implemented the keyboard and mouse part of the new input system. Could some of you check if it works fine on your computer too ? Thanks.
(Joystick part will follow soon.)
-
I'm a bit embarrassed to ask because it's probably really simple but,
What replaced the real-time input function GetInput()?
-
Nothing. The new system is only made of static class functions, so they can be called directly without instanciating or getting anything.
-
Ah I understand now. Thank you.
-
Nice!
Looks like I need to get the latest build and update JSFML. :D
-
:D Nice stuff! Think i'll wait until SFML2 is fully released before i updated my libraries again though, have toooo much to fix right now :P
-
Very nice! I love the new API for inputs. I went to update to the latest commit (since I was behind a few) and it totally broke my engine. I was wondering where some of the functions went haha I guess that's the price of development releases. Keep it up.
-
Don't forget that:
- SFML 2 is not even in alpha state so I can change whatever I want, whenever I want :lol:
- once SFML 2 is officially released, I won't break the API anymore in the 2.x branch
Laurent, if I understand correctly 1.6 isn't maintained anymore, and 2.0 isn't even in alpha yet and will probably have some major API changes in the future and should therefore not be used at all?
sammy
-
Absolutely.
-
Laurent, if I understand correctly ... should therefore not be used at all?
sammy
Not at all. Yes, it's true that some things may change, but that's hardly a problem, considering that SFML2 is actually far more stable than SFML 1.x. In fact, if you use an ATi Graphics Card with recent drivers, SFML 1.x based applications won't work at all. This problem has been fixed in SFML2.
-
No, SFML 1.6 works fine for my ATI card with the latest drivers. I still prefer SFML 2 though :D
-
No, SFML 1.6 works fine for my ATI card with the latest drivers. I still prefer SFML 2 though :D
What card do you use and what driver version? Laurent spent months trying to fix that bug.
-
The ATI bug happens only on Windows with dynamic libraries.
-
Absolutely.
new guy here. Does this mean use 2.0 or use 1.6?
-
new guy here. Does this mean use 2.0 or use 1.6?
It means use SFML 2.0, unless you need absolute API stability for the next few months.
-
It means use SFML 2.0, unless you need absolute API stability for the next few months.
In this case he can still use a fixed Git revision of SFML 2. The 1.6 API is only "stable" because it is unmaintained ;)
Once SFML 2 is released, there are certainly fewer API modifications to take care of than when coming from SFML 1.6. Plus, many new features and bugfixes are available.
-
I'm back some day ago on SFML, i see that input are changed, how can i control input keyboard for move a sprite? :)
-
You must now use sf::Keyboard::IsKeyPressed() instead of sf::Input::IsKeyDown(). And key enumerators are now inside the class sf::Keyboard instead of the namespace sf::Key.
Generally, sf::Input has been split into the 3 classes sf::Mouse, sf::Keyboard and sf::Joystick. More can be found at the documentation (http://www.sfml-dev.org/documentation/2.0/annotated.php)...
-
I'm not happy of this change. I understand that it makes more sense in terms of abstraction and OOP-design, but having input related to a window was much more easier to manage.
What's the best solution to make the new "global input" system behave like the old one? How can I check if the key/mouse-presses are inside a window?
-
I have had the same doubt, see the first page (http://www.sfml-dev.org/forum/viewtopic.php?p=34496#34496).
In short, you have two possibilities:
- Catch LostFocus and GainedFocus events, ignore realtime input as long as the window has no focus
- Store bool arrays on your own and flip their elements when the corresponding key/mouse/joystick events are fired
Both options are rather unconvenient compared to before. That's why I abstracted the functionality away in Thor's Action system, so that users don't have to manually watch out for focus events. I would recommend you to do something similar.
-
Couldn't Laurent release the previous method as an additional class or something? It seems to work much better. I tried catching/losing focus but when I work with InputBoxes it still gives a lot of problems :(
-
Couldn't Laurent release the previous method as an additional class or something?
He certainly could, but this is a bad idea. Users would get confused and would not know which method to use to get realtime input. The whole functionality formerly provided by sf::Input can also be achieved with sf::Mouse, sf::Keyboard and sf::Joystick. It is just this issue which is more complicated to achieve, in general the new input system is much cleaner.
I tried catching/losing focus but when I work with InputBoxes it still gives a lot of problems :(
Can you explain the problem more concretely? Maybe not here, I think you should open a new thread in the Window subforum ;)
-
It is just this issue which is more complicated to achieve, in general the new input system is much cleaner.
The most common case got a lot more complicated to make it "cleaner"?
I can't see any common use case where I would want to get the keyboard state while the window is unfocused. (except for a keylogger).
Keeping track of the window focus seems like the easiest way of doing the common case. Perhaps providing a window.HasFocus() method would make it simple again.
-
Keeping track of the window focus seems like the easiest way of doing the common case. Perhaps providing a window.HasFocus() method would make it simple again.
Indeed.
-
You could also handle it similiarly to sf::Mouse, while reflecting about non-malicious use cases of the first overload :D
class Keyboard
{
public:
static bool IsKeyPressed(Key key);
static bool IsKeyPressed(Key key, const sf::Window& window);
...
};
-
Sometimes you may be maybe switching between two or more windows so using the second version would be a pain in the neck if you want to share the keyboard state among the different windows. This is uncommon but still.