Page 1 of 1

SDL Geting text input

Posted: Thu May 20, 2010 7:00 am
by adikid89
I'm trying to get text input for a console... but it doesn't seem to be working, and I'm pretty lost to figure out what the problem.
Here is some code. The console is not receiving any input. I mean... c = getKey() is 0 every time.

Code: Select all

void Console::handle_input(SDL_Event& event)
{
	SDL_EnableUNICODE(SDL_ENABLE);
	
			if(event.type == SDL_KEYDOWN) {
				handleKey(event.key);
			}
		

	SDL_EnableUNICODE(SDL_DISABLE);
}
void Console::handleKey(const SDL_KeyboardEvent &event)
{
	switch(event.keysym.sym) {
		case SDLK_BACKSPACE:
			if(console_input.size()) {
				console_input.erase(--index,1);
			} break;
		case SDLK_DELETE:
			if(index < console_input.size()) {
				console_input.erase(index,1);
			} break;
		case SDLK_LEFT:
			if(index <= 0) index = 0;
			else index--;
			break;
		case SDLK_RIGHT:
			if(index >= console_input.size()) index = console_input.size();
			else index++;
			break;
		default:
			char c = getKey(event);
			if(c) console_input += c; 
			break;
	}
}
char Console::getKey(const SDL_KeyboardEvent& event)
{
	if(SDL_EnableUNICODE(SDL_QUERY) == SDL_ENABLE) {
		Singleton<Log>::getInstance()->print("SDL_EnableUNICODE == SDL_ENABLE)");
	} else {			
		Singleton<Log>::getInstance()->print("SDL_EnableUNICODE == SDL_DISABLED returning)");
		return '0';
	}
	const int INTERNATIONAL_MASK = 0xFF80, UNICODE_MASK = 0x7F;
	
	int uni = event.keysym.unicode;
	if(!uni) {
		return 0; //this always gets executed
	} else if( ( uni & INTERNATIONAL_MASK ) == 0 ) {
        return static_cast<char>(uni & UNICODE_MASK); //this never gets executed
    } else // we have a funky international character. one we can't read :(
    {
        // we could do nothing, or we can just show some sign of input, like so:
        return 0;
    }
}
Here is the function that calls the console::update() function:
renderConsole() gets executed every about 40ms.

Code: Select all

void Game::renderConsole()
{
	SDL_Event event;
	if(SDL_PollEvent(&event)) {
		if(event.type == SDL_QUIT) gameState->setState(EXIT);
		else if(event.type == SDL_KEYDOWN) {
			if(event.key.keysym.sym == SDLK_BACKQUOTE) {
				gameState->setState(GAMEOVER);
			}
		}
	}
	Log* log = Singleton<Log>::getInstance();
	Console* console = Singleton<Console>::getInstance();
	console->update(event);
}
Any idea on why the console is not getting any input whatsoever?

Re: SDL Geting text input

Posted: Thu May 20, 2010 8:17 am
by RyanPridgeon
I know there's no error handling, and it will only work correctly for ASCII input, but out of interest does this work?

Code: Select all

char Console::getKey(const SDL_KeyboardEvent& event)
{
  return (char) event.key.keysym.unicode;
}

Re: SDL Geting text input

Posted: Thu May 20, 2010 9:13 am
by adikid89
RyanPridgeon wrote:I know there's no error handling, and it will only work correctly for ASCII input, but out of interest does this work?

Code: Select all

char Console::getKey(const SDL_KeyboardEvent& event)
{
  return (char) event.key.keysym.unicode;
}
I doubt it ... i kinda figured out what the problem was(I put the code inside handleKey() in a while(!done) loop, so now it gets all the input, I guess it was wasting inputs somewhere else in the code)...But even so it's not really that good. I would sure like to hear some better ideas.

L.E.: Anyone got any idea on why is SDL_PollEvent taking certain keys twice? (backspace, arrow keys, other probably). Here is the code:

Code: Select all

void Console::handleKey()
{ 
	bool done = false;
	SDL_Event events;
	while(!done) {
		render();
		SDL_Delay(30);
		if(SDL_PollEvent(&events)) {
			if(events.type == SDL_QUIT) 
				Singleton<GameState>::getInstance()->setState(EXIT);
			switch(events.key.keysym.sym) {
				case SDLK_BACKSPACE:
					if(console_input.size() >= 1) {
						console_input.erase(--index,1);
						Singleton<Log>::getInstance()->print("%s", console_input.c_str());
					} break;
				case SDLK_DELETE:
					if(index < console_input.size()) {
						console_input.erase(index,1);
					} break;
				case SDLK_LEFT:
					if(index <= 0) index = 0;
					else index--;
					break;
				case SDLK_RIGHT:
					if(index >= console_input.size()) index = console_input.size();
					else index++;
					break;
				case SDLK_RETURN:
					done = true;
					parseCommand();
					console_input.clear();
					index = 0;
					break;
				case SDLK_ESCAPE:
					done = true;
					Singleton<GameState>::getInstance()->setState(GAMEOVER);
					break;
				case SDLK_BACKQUOTE: //not working
					if(!_active) {
						Singleton<GameState>::getInstance()->setState(GAMEOVER);
						_active = true;
					}
					else _active = false;
					done = true;
					break;
				case SDLK_HOME:
					index = 0;
					break;
				case SDLK_END:
					index = console_input.size() -1;
					break;
				case SDLK_UP:
					console_input = getInfoUp();
					index = console_input.size() -1;
					break;
				case SDLK_DOWN:
					console_input = getInfoDown();
					index = console_input.size() - 1;
					break;
				default:
					char c = getKey(events.key);
					if(c) {
						console_input += c; 
						Singleton<Log>::getInstance()->print("%s", console_input.c_str());
						index++;
					}
					break;
			}
		}
	}
	
}

Re: SDL Geting text input

Posted: Thu May 20, 2010 1:18 pm
by eatcomics
It should really be while (SDL_PollEvents(&events))
that I believe is where your problems are coming from, but also maybe not, I don't see a real reason this would be unless the input isn't being cleared, well now that I think about it, if you're holding down the button, the loop doesn't get done, and it just keeps taking in the key, instead of exiting... But yeah I think while (poll events)
will work

Re: SDL Geting text input

Posted: Thu May 20, 2010 1:22 pm
by X Abstract X
Some events are being reported twice because you're checking for both presses and releases of keys. You can find out which event it is like this.

if (event.type == SDL_KEYDOWN)

if(event.type == SDL_KEYUP)

Re: SDL Geting text input

Posted: Thu May 20, 2010 3:17 pm
by adikid89
X Abstract X wrote:Some events are being reported twice because you're checking for both presses and releases of keys. You can find out which event it is like this.

if (event.type == SDL_KEYDOWN)

if(event.type == SDL_KEYUP)
OMG .. I didn't notice that.. thanks :D. Works like a charm now :P .