Hello everyone
I’ve got a problem; remember when we were discussing possible SDL_GetKeyState drawbacks and why it’s better to use events? Since then I rewritten my input manager to use events just like you adviced me to do; it worked perfectly (well, at least it helped me to overcome “bug” that couldn’t let you type uppercase characters :-)) until today, when I discovered that my edit control in GUI doesn’t respond to keypresses. I fixed it, but then, I’ve seen that actuall test demo (that operates with keyboard just like real game will do) doesn’t respond to keypresses. I fixed it, but then again, GUI wasn’t working as expected - when pressing anything combined with shift, that key reported keypresses even when in reality, it was released long ago. I’ve investigated code and it all comes to one line of code, let me show you:--------------------------
// it’s called at the beginning of main loop:
bool SC :: InputTask :: Start()
{
// ignore to speed things up in the Kernel and InputTask Update sections that loop through all received events.
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
SDL_EnableUNICODE(1);
if ( SDL_EnableKeyRepeat(300, 30) == -1)
logError2(“Input”, “Couldn’t set key repeat value.”)
// SDL_GetKeyState returns a reference to the key state array, not a copy, so we must copy it manually
tmpKeys = SDL_GetKeyState( &keyCount );
actKeys = new uchar[keyCount];
if (!actKeys) return false;
oldKeys = new uchar[keyCount];
if (!oldKeys)
{
Stop();
return false;
}
// twice to flush any pending keypresses
SDL_PumpEvents();
SDL_PumpEvents();
memset(oldKeys, 0, keyCount);
memset(actKeys, 0, keyCount);
return true;
}
// it’s called every frame
void SC :: InputTask :: Update()
{
SDL_PumpEvents();
// this construction dispatches up to 8 keypresses each frame
maxEventCount = 8;
// copy actual keypresess to old ones
memcpy( oldKeys, actKeys, keyCount);
// memset(actKeys, 0, keyCount); // ### it’s here !!!
while ( (SDL_PollEvent ( &event )) && (maxEventCount))
{
if (event.type == SDL_KEYDOWN)
{
if ((event.key.keysym.unicode ) == 0)
actKeys[event.key.keysym.sym] = 1;
else
actKeys[event.key.keysym.unicode] = 1;
}
else if (event.type == SDL_KEYUP)
{
actKeys[event.key.keysym.sym] = 0; // ***
}
--maxEventCount;
}
}
The problem really lies in that the key realeses doesn’t have unicode codes attatched, so if we press ie. shift + 1 (which on my keyboard produces !) then it’s keysym.sym and keysym.unicode will vary, and therefore -> in this line (***) it won’t toggle old unicode off, which will forever produce keypresses for !.
I’ve found possible solution to this: each frame, clear actual keys so that even when sth was pressed, it won’t stay forever (###). It makes GUI work, but test game won’t respond to any keypressess at all. If I comment that line (just like it’s now) then game will work, but GUI will suffer.
Though, there’s hope - when I allow for dynamically choosing of in what mode should input manager work (bool flag: clear each frame actKeys or not clear), then, if I remember to switch modes, GUI and game should work correctly. However, I don’t like to remember about such things - it’s counter intuitive and introduces stupid “bugs”, it would be good if it was handled by input manager internally (in some way or another).
Ehhmm, so, now the question What are other alternatives to my solution? It would be best if there was some way to dig to that unicode code even for releases… but it’s probably impossible.
Thanks in advance!
–
Koshmaar
<Of all the things I’'ve lost, I miss my mind the most>
GG: 3928072
http://jnr.sourceforge.net/
www.pongowar.prv.pl
www.liero-turbo.prv.pl