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 # Display
####################################### #######################################
fullscreen = no fullscreen = no
horizontal = stretch # or enter in the screen pixel width (i.e 1024) horizontal = 400 # or enter in the screen pixel width (i.e 1024)
vertical = stretch # or enter in the screen pixel width (i.e 768) vertical = 300 # or enter in the screen pixel width (i.e 768)
layout = Default 16x9 layout = Default 16x9
hideMouse = yes hideMouse = yes
showParenthesis = yes showParenthesis = yes

View File

@ -92,6 +92,8 @@ set(RETROFE_HEADERS
"${RETROFE_DIR}/Source/Collection/Item.h" "${RETROFE_DIR}/Source/Collection/Item.h"
"${RETROFE_DIR}/Source/Collection/MenuParser.h" "${RETROFE_DIR}/Source/Collection/MenuParser.h"
"${RETROFE_DIR}/Source/Control/UserInput.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/Configuration.h"
"${RETROFE_DIR}/Source/Database/DB.h" "${RETROFE_DIR}/Source/Database/DB.h"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.h" "${RETROFE_DIR}/Source/Database/MetadataDatabase.h"
@ -137,6 +139,7 @@ set(RETROFE_SOURCES
"${RETROFE_DIR}/Source/Collection/Item.cpp" "${RETROFE_DIR}/Source/Collection/Item.cpp"
"${RETROFE_DIR}/Source/Collection/MenuParser.cpp" "${RETROFE_DIR}/Source/Collection/MenuParser.cpp"
"${RETROFE_DIR}/Source/Control/UserInput.cpp" "${RETROFE_DIR}/Source/Control/UserInput.cpp"
"${RETROFE_DIR}/Source/Control/KeyboardHandler.cpp"
"${RETROFE_DIR}/Source/Database/Configuration.cpp" "${RETROFE_DIR}/Source/Database/Configuration.cpp"
"${RETROFE_DIR}/Source/Database/DB.cpp" "${RETROFE_DIR}/Source/Database/DB.cpp"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.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 "UserInput.h"
#include "../Database/Configuration.h" #include "../Database/Configuration.h"
#include "../Utility/Log.h" #include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include "KeyboardHandler.h"
UserInput::UserInput(Configuration &c) UserInput::UserInput(Configuration &c)
: config_(c) : config_(c)
, joystick_(NULL)
{ {
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
keyHandlers_[i] = NULL;
lastKeyState_[i] = false;
}
} }
UserInput::~UserInput() UserInput::~UserInput()
@ -59,46 +67,16 @@ bool UserInput::initialize()
// retVal = MapKey("admin", KeyCodeAdminMode) && retVal; // retVal = MapKey("admin", KeyCodeAdminMode) && retVal;
// retVal = MapKey("remove", KeyCodeHideItem) && retVal; // retVal = MapKey("remove", KeyCodeHideItem) && retVal;
for(int i = 0; i < SDL_NumJoysticks(); ++i)
{
joystick_ = SDL_JoystickOpen(i);
break;
}
return retVal; 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) bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
{ {
SDL_Scancode scanCode; SDL_Scancode scanCode;
@ -108,40 +86,90 @@ bool UserInput::MapKey(std::string keyDescription, KeyCode_E key)
if(!config_.getProperty(configKey, description)) 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; return false;
} }
scanCode = SDL_GetScancodeFromName(description.c_str()); 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"); Logger::write(Logger::ZONE_INFO, "Input", "Binding key " + configKey);
return false; keyHandlers_[key] = new KeyboardHandler(scanCode);
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;
}
void UserInput::resetStates()
{
for(unsigned int i = 0; i < KeyCodeMax; ++i)
{
keyHandlers_[i]->reset();
}
}
bool UserInput::update(SDL_Event &e)
{
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();
}
} }
keyMap_[key] = scanCode; return updated;
reverseKeyMap_[scanCode] = key;
keyState_[key] = false;
return true;
} }
bool UserInput::keystate(SDL_Scancode code, bool state) bool UserInput::keystate(KeyCode_E code)
{ {
KeyCode_E key = keycode(code); return lastKeyState_[code];
if(key == KeyCodeNull) { return false; }
if(keyState_.find(key) == keyState_.end()) { return false; }
keyState_[key] = state;
return true;
} }
bool UserInput::keystate(KeyCode_E key)
{
if(keyState_.find(key) == keyState_.end()) { return false; }
return keyState_[key];
}

View File

@ -16,9 +16,11 @@
#pragma once #pragma once
#include <map> #include <map>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_joystick.h>
#include <string> #include <string>
class Configuration; class Configuration;
class InputHandler;
class UserInput class UserInput
{ {
@ -38,26 +40,22 @@ public:
KeyCodeLetterUp, KeyCodeLetterUp,
KeyCodeAdminMode, KeyCodeAdminMode,
KeyCodeHideItem, KeyCodeHideItem,
KeyCodeQuit KeyCodeQuit,
KeyCodeMax
}; };
UserInput(Configuration &c); UserInput(Configuration &c);
virtual ~UserInput(); virtual ~UserInput();
bool initialize(); bool initialize();
SDL_Scancode scancode(KeyCode_E key); void resetStates();
KeyCode_E keycode(SDL_Scancode scancode); bool update(SDL_Event &e);
bool keystate(SDL_Scancode code, bool state); bool keystate(KeyCode_E);
bool keystate(KeyCode_E key);
bool keyStateChanged();
void resetKeyStates();
private: private:
bool MapKey(std::string keyDescription, KeyCode_E key); 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_; 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_RestoreWindow(SDL::getWindow());
SDL_RaiseWindow(SDL::getWindow()); SDL_RaiseWindow(SDL::getWindow());
SDL_SetWindowGrab(SDL::getWindow(), SDL_TRUE); SDL_SetWindowGrab(SDL::getWindow(), SDL_TRUE);
input_.resetKeyStates(); input_.resetStates();
attract_.reset(); attract_.reset();
currentTime_ = static_cast<float>(SDL_GetTicks()) / 1000; currentTime_ = static_cast<float>(SDL_GetTicks()) / 1000;
@ -400,14 +400,11 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput(Page *page)
bool rememberMenu = false; bool rememberMenu = false;
config_.getProperty("rememberMenu", rememberMenu); 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(); attract_.reset();
if(page->isHorizontalScroll()) if(page->isHorizontalScroll())
{ {
if (input_.keystate(UserInput::KeyCodeLeft)) if (input_.keystate(UserInput::KeyCodeLeft))
{ {