Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML 1.5: Bug in window.GetInput().IsKeyDown() ?  (Read 12965 times)

0 Members and 1 Guest are viewing this topic.

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« on: February 10, 2010, 08:49:16 am »
I am having a weird problem with GetInput() in combination with window.GetEvent() and sf::Event::MouseMoved.

Here is the offending code:
Code: [Select]
sf::Event event;

while(window.GetEvent(event))
{
...snip...
else if(event.Type == sf::Event::MouseMoved)
{
sf::Vector2f canvasMouseCoord = window.ConvertCoords(event.MouseMove.X, event.MouseMove.Y, &canvasCam);
// If we're in drag-mode (the left mouse button is down)
if(dragging)
{
// If a vertex is selected, drag it to the mouse position
if(selectedVertice != -1)
{
sf::Vector2f newPosition(canvasMouseCoord.x/meter_to_pixel, canvasMouseCoord.y/meter_to_pixel);

// If left shift and left control is held down, snap to 1cm
if(window.GetInput().IsKeyDown(sf::Key::LShift) && window.GetInput().IsKeyDown(sf::Key::LControl))
{
newPosition.x = floor((newPosition.x * 100.f) + .5f)/100.f;
newPosition.y = floor((newPosition.y * 100.f) + .5f)/100.f;
}
// If left control is held down, snap to 10cm grid
else if(window.GetInput().IsKeyDown(sf::Key::LControl))
{
newPosition.x = floor((newPosition.x * 10.f) + .5f)/10.f;
newPosition.y = floor((newPosition.y * 10.f) + .5f)/10.f;
}
shape.point[selectedVertice] = newPosition;
}
}
}
}
Everything works well when I only use left control, but if I use left control plus left shift, and move the mouse around real quick, then GetInput() doesn't seem to register when I let go of left shift - window.GetInput().IsKeyDown(sf::Key::LShift) simply keeps evaluating true.

If I hold the mouse still and press shift again, then the problem goes away.
This is the only place in the code where I do anything with keyboard events, at all.

Is this a bug, or am I using it wrong?

I am using Visual C++ 2008 Express on Windows XP.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #1 on: February 10, 2010, 10:53:01 am »
Hi

Can you give a complete and minimal example that I can copy, paste and test directly?
Laurent Gomila - SFML developer

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #2 on: February 10, 2010, 09:27:30 pm »
Hello Laurent,

Just so you know I haven't forgotten you, I am still working on your minimal example. I now think the problem is related to passing the RenderWindow object to a function. At least the problem goes away when I remove that line...

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #3 on: February 10, 2010, 10:16:45 pm »
Here you go, Laurent, I finally finished, and also learned a lot more about the bug, which I now think it is.
Code: [Select]
/***********************************************************
* Possible Window.GetInput() bug Minimal example
***********************************************************/

///////////////////////////////////////////////////////////
// Headers
///////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <sstream>
#include <string>

///////////////////////////////////////////////////////////
// Functions
///////////////////////////////////////////////////////////

template <class T>
std::string to_string( T input )
{
std::stringstream sstream;
sstream << input;
return sstream.str();
}

void my_function(sf::RenderWindow& window)
{
sf::Sleep(.1f);
}

///////////////////////////////////////////////////////////
// Application entry point
///////////////////////////////////////////////////////////

int main()
{
/////////////////////////////
// Setup variables
/////////////////////////////

sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "Possible Window.GetInput() bug Minimal example");

sf::String output;

/////////////////////////////
// Main loop
/////////////////////////////

while(window.IsOpened())
{
/////////////////////////
// Handle events
/////////////////////////
sf::Event event;

while(window.GetEvent(event))
{
if(event.Type == sf::Event::Closed)
window.Close();
}

/////////////////////////
// Draw
/////////////////////////
window.Clear();

my_function(window);

output.SetText( "LShift is down: " + to_string(window.GetInput().IsKeyDown(sf::Key::LShift)) + "\n" +
"LControl is down: " + to_string(window.GetInput().IsKeyDown(sf::Key::LControl)) );

window.Draw(output);

window.Display();
}

return EXIT_SUCCESS;
}
I have now learned that it hasn't got anything to do with the MouseMoved event, but with passing the RenderWindow to a function that takes a little time to complete.
The longer the function takes to complete, the faster the problem will occur, it seems.

This example will also show you that the problem does not happen with the left control key.

To invoke the bug, simply hold down the left shift key for a while (2-3 seconds is enough on this computer), and let go.
Window.GetInput().IsKeyDown(sf::Key::LShift) will now keep evaluating to true, until you press it again and let go.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #4 on: February 11, 2010, 12:06:38 am »
Thanks for the code :)

There seems to be a bug, indeed. I'll investigate that.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #5 on: February 11, 2010, 12:37:20 am »
I solved the problem. The fix will be in the 1.6 release.

Thanks a lot for your help.
Laurent Gomila - SFML developer

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #6 on: February 11, 2010, 03:09:20 am »
That was fast! And no problem about the code - that's the least I could do as payment for you making SFML. Great deal, I think!

Unfortunately, I may have found another one, also related to GetInput().

A wiser man than before, I am including a minimal example:
Code: [Select]
/***********************************************************
* Possible Window.GetInput() bug No. 2 Minimal example
***********************************************************/

///////////////////////////////////////////////////////////
// Headers
///////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>

///////////////////////////////////////////////////////////
// Application entry point
///////////////////////////////////////////////////////////

int main()
{
/////////////////////////////
// Setup variables
/////////////////////////////

sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "Possible Window.GetInput() bug No. 2 Minimal example");

bool mouseClicked = false;

sf::String output;

/////////////////////////////
// Main loop
/////////////////////////////

while(window.IsOpened())
{
/////////////////////////
// Handle events
/////////////////////////
sf::Event event;

while(window.GetEvent(event))
{
if(event.Type == sf::Event::Closed)
window.Close();
else if(event.Type == sf::Event::MouseButtonPressed)
{
if(event.MouseButton.Button == sf::Mouse::Left)
mouseClicked = true;
else if(event.MouseButton.Button == sf::Mouse::Right)
{
mouseClicked = false;
output.SetText("");
}
}
else if(event.Type == sf::Event::MouseMoved)
{
if(window.GetInput().IsMouseButtonDown(sf::Mouse::Left) && mouseClicked == false)
output.SetText("Mouse was down before it was clicked!");
}
}

/////////////////////////
// Draw
/////////////////////////
window.Clear();

window.Draw(output);

window.Display();
}

return EXIT_SUCCESS;
}
With this program, if I click the left mouse button, while moving the mouse around, window.GetInput().IsMouseButtonDown(sf::Mouse::Left) evaluates to true before I get the chance to handle the MouseButtonPressed event with Window.GetEvent().

I can see how this could be interpreted as a "feature", but intuitively, shouldn't IsMouseButtonDown() only evaluate true after the MouseButtonPressed event has happened? Otherwise, IsMouseButtonDown() can't really be used as a true substitute manually handling "is down" states.

Oh, and in the program, you can use the right mouse button to reset.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #7 on: February 11, 2010, 08:16:08 am »
Quote
shouldn't IsMouseButtonDown() only evaluate true after the MouseButtonPressed event has happened?

It does. But it can't happen after you handle the event.

Quote
Otherwise, IsMouseButtonDown() can't really be used as a true substitute manually handling "is down" states.

Well, your example doesn't look like a real one. In real code I don't think that it is really an issue.
Laurent Gomila - SFML developer

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #8 on: February 11, 2010, 04:32:57 pm »
Well, actually, I stumbled on it while making my current project - a kind of drawing program for making polygons.

-When a left mouse down event happens over a vertex, that vertex is selected.

-When a left mouse down event happens over a  face, if the conditions are right, a new vertex is created and selected.

-When a left mouse down event happens over empty space, any selected vertex is deselected.

Anytime the user moves the mouse with the left mouse button down, it means that they are dragging something.

-If a vertex is selected, then that vertex is repositioned.

-If no vertex is selected, then the view is moved.


So you can probably see why, in this case, IsMouseButtonDown() is not suitable as a substitute for manually handling the "left mouse button is down" case.

Also, I don't deliberately think up ways to make SFML act undesirably. When I report something, it is because I am having a real issue with it, in real code. Of course, you can't see that from a minimal example.  :wink:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #9 on: February 11, 2010, 04:45:51 pm »
I see.

I agree with your conclusion
Quote
in this case, IsMouseButtonDown() is not suitable as a substitute for manually handling the "left mouse button is down" case.

But I don't think that there is a solution to this problem, I can't make sf::Input aware of the mouse button down event after you process it in your event loop.

sf::Input is a convenience class, it does nothing that you can't do with events. So just don't use it in the situations where it is not suitable ;)
Laurent Gomila - SFML developer

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #10 on: February 11, 2010, 05:35:29 pm »
Not being an expert, and completely disregarding the fact that there could be more than one window, it seems like you could just let Window.GetEvent() set the state of the IsMouseButtonDown(sf::Mouse::Left). Of course, that would require a proper event loop, to work correctly.

I suggest the following solutions:

For SFML 1, document the cases where IsMouseButtonDown() cannot be used as a true substitute manually handling "is down" states.

For SFML 2, try to think up a new system that is both convenient, and easy to fully grasp for beginners.
Maybe such a system is as simple as the one described above?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #11 on: February 11, 2010, 05:56:50 pm »
Quote
it seems like you could just let Window.GetEvent() set the state of the IsMouseButtonDown(sf::Mouse::Left)

It does (if you never call GetEvent, IsMouseButtonDown will never be true), but it still happens before your own code.
Laurent Gomila - SFML developer

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #12 on: February 12, 2010, 02:01:09 am »
OK, but then maybe I didn't explain myself well enough.

What I mean is that you could let Window.GetEvent() update the Window.GetInput().IsMouseButtonDown(sf::Mouse::Left) state only when Event.Type is sf::Event::MouseButtonPressed and Event.MouseButton.Button is sf::Mouse::Left.

Does this make sense?

OniLinkPlus

  • Hero Member
  • *****
  • Posts: 500
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #13 on: February 12, 2010, 02:54:23 am »
Quote from: "model76"
OK, but then maybe I didn't explain myself well enough.

What I mean is that you could let Window.GetEvent() update the Window.GetInput().IsMouseButtonDown(sf::Mouse::Left) state only when Event.Type is sf::Event::MouseButtonPressed and Event.MouseButton.Button is sf::Mouse::Left.

Does this make sense?
I think that's what he does.
I use the latest build of SFML2

model76

  • Full Member
  • ***
  • Posts: 231
    • View Profile
SFML 1.5: Bug in window.GetInput().IsKeyDown() ?
« Reply #14 on: February 12, 2010, 04:55:13 am »
Quote from: "OniLink10"
I think that's what he does.
Yes, maybe he does it in myWindow->DoEvents(). I wasn't able to find that method... But if it is done just before the event is popped, and not while filling the event cue, then the problem should go away, no?