Refactoring UserInput to accomidate future changes (i.e. joystick support)

This commit is contained in:
Don Honerbrink 2015-07-24 15:21:33 -05:00
parent b22dc3d72c
commit dd07817ede
8 changed files with 166 additions and 81 deletions

View File

@ -12,8 +12,8 @@
# Display
#######################################
fullscreen = no
horizontal = stretch # or enter in the screen pixel width (i.e 1024)
vertical = stretch # or enter in the screen pixel width (i.e 768)
horizontal = 400 # or enter in the screen pixel width (i.e 1024)
vertical = 300 # or enter in the screen pixel width (i.e 768)
layout = Default 16x9
hideMouse = yes
showParenthesis = yes

View File

@ -92,6 +92,8 @@ set(RETROFE_HEADERS
"${RETROFE_DIR}/Source/Collection/Item.h"
"${RETROFE_DIR}/Source/Collection/MenuParser.h"
"${RETROFE_DIR}/Source/Control/UserInput.h"
"${RETROFE_DIR}/Source/Control/InputHandler.h"
"${RETROFE_DIR}/Source/Control/KeyboardHandler.h"
"${RETROFE_DIR}/Source/Database/Configuration.h"
"${RETROFE_DIR}/Source/Database/DB.h"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.h"
@ -137,6 +139,7 @@ set(RETROFE_SOURCES
"${RETROFE_DIR}/Source/Collection/Item.cpp"
"${RETROFE_DIR}/Source/Collection/MenuParser.cpp"
"${RETROFE_DIR}/Source/Control/UserInput.cpp"
"${RETROFE_DIR}/Source/Control/KeyboardHandler.cpp"
"${RETROFE_DIR}/Source/Database/Configuration.cpp"
"${RETROFE_DIR}/Source/Database/DB.cpp"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.cpp"

View File

@ -0,0 +1,12 @@
#pragma once
#include <SDL2/SDL.h>
class InputHandler
{
public:
virtual bool update(SDL_Event &e) = 0;
virtual bool pressed() = 0;
virtual void reset() = 0;
};

View File

@ -0,0 +1,30 @@
#include "KeyboardHandler.h"
KeyboardHandler::KeyboardHandler(SDL_Scancode s)
: scancode_(s)
, pressed_(false)
{
}
void KeyboardHandler::reset()
{
pressed_= false;
}
bool KeyboardHandler::update(SDL_Event &e)
{
if(e.key.keysym.scancode == scancode_)
{
if(e.type == SDL_KEYUP) pressed_ = false;
if(e.type == SDL_KEYDOWN) pressed_ = true;
return true;
}
return false;
}
bool KeyboardHandler::pressed()
{
return pressed_;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "InputHandler.h"
class KeyboardHandler : public InputHandler
{
public:
KeyboardHandler(SDL_Scancode scancode);
bool update(SDL_Event &e);
bool pressed();
void reset();
private:
SDL_Scancode scancode_;
bool pressed_;
};

View File

@ -17,10 +17,18 @@
#include "UserInput.h"
#include "../Database/Configuration.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include "KeyboardHandler.h"
UserInput::UserInput(Configuration &c)
: config_(c)
, joystick_(NULL)
{
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
keyHandlers_[i] = NULL;
lastKeyState_[i] = false;
}
}
UserInput::~UserInput()
@ -59,46 +67,16 @@ bool UserInput::initialize()
// retVal = MapKey("admin", KeyCodeAdminMode) && retVal;
// retVal = MapKey("remove", KeyCodeHideItem) && retVal;
for(int i = 0; i < SDL_NumJoysticks(); ++i)
{
joystick_ = SDL_JoystickOpen(i);
break;
}
return retVal;
}
SDL_Scancode UserInput::scancode(KeyCode_E key)
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
std::map<KeyCode_E, SDL_Scancode>::iterator it = keyMap_.find(key);
if(it != keyMap_.end())
{
scancode = it->second;
}
return scancode;
}
UserInput::KeyCode_E UserInput::keycode(SDL_Scancode scancode)
{
KeyCode_E keycode = KeyCodeNull;
std::map<SDL_Scancode, KeyCode_E>::iterator it = reverseKeyMap_.find(scancode);
if(it != reverseKeyMap_.end())
{
keycode = it->second;
}
return keycode;
}
void UserInput::resetKeyStates()
{
for(std::map<KeyCode_E, bool>::iterator it = keyState_.begin(); it != keyState_.end(); it++)
{
it->second = false;
}
}
bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
{
SDL_Scancode scanCode;
@ -108,40 +86,90 @@ bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
if(!config_.getProperty(configKey, description))
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Missing property " + configKey);
Logger::write(Logger::ZONE_ERROR, "Input", "Missing property " + configKey);
return false;
}
scanCode = SDL_GetScancodeFromName(description.c_str());
if(scanCode == SDL_SCANCODE_UNKNOWN)
if(scanCode != SDL_SCANCODE_UNKNOWN)
{
Logger::write(Logger::ZONE_ERROR, "Configuration", "Unsupported property value for " + configKey + "(" + description + "). See Documentation/Keycodes.txt for valid inputs");
return false;
Logger::write(Logger::ZONE_INFO, "Input", "Binding key " + configKey);
keyHandlers_[key] = new KeyboardHandler(scanCode);
return true;
}
keyMap_[key] = scanCode;
reverseKeyMap_[scanCode] = key;
keyState_[key] = false;
return true;
/*
else if(description.find("joy") == 0)
{
std::string joydesc = Utils::replace(Utils::toLower(description), "joy", "");
if(joydesc.find("button"))
{
unsigned int button;
std::stringstream ss;
ss << Utils::replace(joydesc, "button", "");
ss >> button;
buttonMap_[key] = button;
keyState_[key] = 0;
Logger::write(Logger::ZONE_INFO, "Input", "Binding joypad button " + ss.str() );
}
else if(joydesc.find("axis"))
{
unsigned int axis;
std::stringstream ss;
ss << Utils::replace(joydesc, "axis", "");
ss >> axis;
buttonMap_[key] = axis;
keyState_[key] = 0;
Logger::write(Logger::ZONE_INFO, "Input", "Binding joypad axis " + ss.str() );
keyCallbacks_[key] = new JoyAxisHandler();
}
else if(joydesc.find("hat"))
{
joydesc = Utils::replace(joydesc, "hat", "");
if(joydesc == "leftup") hatMap_[key] = SDL_HAT_LEFTUP;
else if(joydesc == "left") hatMap_[key] = SDL_HAT_LEFT;
else if(joydesc == "leftdown") hatMap_[key] = SDL_HAT_LEFT_DOWN;
else if(joydesc == "up") hatMap_[key] = SDL_HAT_UP;
//else if(joydesc == "centered") hatMap_[key] = SDL_HAT_CENTERED;
else if(joydesc == "down") hatMap_[key] = SDL_HAT_DOWN;
else if(joydesc == "rightup") hatMap_[key] = SDL_HAT_RIGHTUP;
else if(joydesc == "right") hatMap_[key] = SDL_HAT_RIGHT;
else if(joydesc == "rightdown") hatMap_[key] = SDL_HAT_RIGHTDOWN;
keyState_[key] = 0;
Logger::write(Logger::ZONE_INFO, "Input", "Binding joypad hat " + joydesc );
}
}
*/
Logger::write(Logger::ZONE_ERROR, "Input", "Unsupported property value for " + configKey + "(" + description + "). See Documentation/Keycodes.txt for valid inputs");
return false;
}
bool UserInput::keystate(SDL_Scancode code, bool state)
void UserInput::resetStates()
{
KeyCode_E key = keycode(code);
if(key == KeyCodeNull) { return false; }
if(keyState_.find(key) == keyState_.end()) { return false; }
keyState_[key] = state;
return true;
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
keyHandlers_[i]->reset();
}
}
bool UserInput::keystate(KeyCode_E key)
bool UserInput::update(SDL_Event &e)
{
if(keyState_.find(key) == keyState_.end()) { return false; }
return keyState_[key];
bool updated = false;
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
InputHandler *h = keyHandlers_[i];
if(h)
{
if(h->update(e)) updated = true;
lastKeyState_[i] = h->pressed();
}
}
return updated;
}
bool UserInput::keystate(KeyCode_E code)
{
return lastKeyState_[code];
}

View File

@ -16,9 +16,11 @@
#pragma once
#include <map>
#include <SDL2/SDL.h>
#include <SDL2/SDL_joystick.h>
#include <string>
class Configuration;
class InputHandler;
class UserInput
{
@ -38,26 +40,22 @@ public:
KeyCodeLetterUp,
KeyCodeAdminMode,
KeyCodeHideItem,
KeyCodeQuit
KeyCodeQuit,
KeyCodeMax
};
UserInput(Configuration &c);
virtual ~UserInput();
bool initialize();
SDL_Scancode scancode(KeyCode_E key);
KeyCode_E keycode(SDL_Scancode scancode);
bool keystate(SDL_Scancode code, bool state);
bool keystate(KeyCode_E key);
bool keyStateChanged();
void resetKeyStates();
void resetStates();
bool update(SDL_Event &e);
bool keystate(KeyCode_E);
private:
bool MapKey(std::string keyDescription, KeyCode_E key);
std::map<KeyCode_E, SDL_Scancode> keyMap_;
std::map<SDL_Scancode, KeyCode_E> reverseKeyMap_;
std::map<KeyCode_E, bool> keyState_;
Configuration &config_;
const Uint8 *sdlkeys_;
SDL_Joystick *joystick_;
InputHandler *keyHandlers_[KeyCodeMax];
bool lastKeyState_[KeyCodeMax];
};

View File

@ -123,7 +123,7 @@ void RetroFE::launchExit()
SDL_RestoreWindow(SDL::getWindow());
SDL_RaiseWindow(SDL::getWindow());
SDL_SetWindowGrab(SDL::getWindow(), SDL_TRUE);
input_.resetKeyStates();
input_.resetStates();
attract_.reset();
currentTime_ = static_cast<float>(SDL_GetTicks()) / 1000;
@ -400,14 +400,11 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput(Page *page)
bool rememberMenu = false;
config_.getProperty("rememberMenu", rememberMenu);
if(e.type == SDL_KEYDOWN || e.type == SDL_KEYUP)
if(input_.update(e))
{
SDL_Scancode scancode = SDL_GetScancodeFromKey(e.key.keysym.sym);
input_.keystate(scancode, (e.type == SDL_KEYDOWN) ? true : false);
attract_.reset();
if(page->isHorizontalScroll())
if(page->isHorizontalScroll())
{
if (input_.keystate(UserInput::KeyCodeLeft))
{