Merge with develop

This commit is contained in:
emb 2015-07-27 12:52:59 -05:00
commit 0c1c371df9
20 changed files with 485 additions and 85 deletions

View File

@ -11,8 +11,56 @@ back = Escape
quit = Q
# See below for a list of key codes that can be used for configuring the controls:
##############################################################################
MOUSE CODES
###################### ######################################################
# Code # Description
###################### ######################################################
# mouseButtonLeft Left mouse click
# mouseButtonMiddle Middle mouse click
# mouseButtonRight Right mouse click
# mouseButtonX1 ?
# mouseButtonX2 ?
##############################################################################
JOYSTICK/GAMEPAD CODES
###################### ######################################################
# Code # Description
###################### ######################################################
# X is joypad number (0 is first joystick/gamepad)
# joyXHatYLeftUp Y=hat number (0 is the first dpad) (example joy0Hat0Up)
# joyXHatYLeft
# joyXHatYLeftDown
# joyXHatYUp
# joyXHatYDown
# joyXHatYRightUp
# joyXHatYRight
# joyXHatYRightDown
# joyXButtonY Y is button number (0 is first button)
# Example: joy1button7 -> second joystick, 8th button
# Open up the gamepad control panel in windows or use
# "jstest" in linux
#
# joyXAxis0+ First POV stick, first axis positive direction
# (axis 0 is usually x)
# joyXAxis0- First POV stick, first axis positive direction
# (axis 0 is usually x)
# joyXAxis1+ First POV stick, second axis positive direction
# (axis 0 is usually y)
#joyXAxis1- First POV stick, second axis positive direction
# (axis 0 is usually y)
#
# joyXAxis2+ Second POV stick, first axis positive direction
# (axis 2 is usually x)
# joyXAxis2- Second POV stick, first axis positive direction
# (axis 2 is usually x)
# joyXAxis3+ Second POV stick, second axis positive direction
# (axis 3 is usually y)
# joyXAxis3- Second POV stick, second axis positive direction
# (axis 3 is usually y)
##############################################################################
KEYBOARD CODES
###################### ######################################################
# Code # Description
###################### ######################################################

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,12 @@ 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/JoyAxisHandler.h"
"${RETROFE_DIR}/Source/Control/JoyButtonHandler.h"
"${RETROFE_DIR}/Source/Control/JoyHatHandler.h"
"${RETROFE_DIR}/Source/Control/KeyboardHandler.h"
"${RETROFE_DIR}/Source/Control/MouseButtonHandler.h"
"${RETROFE_DIR}/Source/Database/Configuration.h"
"${RETROFE_DIR}/Source/Database/DB.h"
"${RETROFE_DIR}/Source/Database/MetadataDatabase.h"
@ -137,6 +143,11 @@ 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/JoyAxisHandler.cpp"
"${RETROFE_DIR}/Source/Control/JoyButtonHandler.cpp"
"${RETROFE_DIR}/Source/Control/JoyHatHandler.cpp"
"${RETROFE_DIR}/Source/Control/KeyboardHandler.cpp"
"${RETROFE_DIR}/Source/Control/MouseButtonHandler.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,29 @@
#include "JoyAxisHandler.h"
JoyAxisHandler::JoyAxisHandler(SDL_JoystickID joyid, Uint8 axis, Sint16 min, Sint16 max)
: joyid_(joyid)
, axis_(axis)
, min_(min)
, max_(max)
, pressed_(false)
{
}
void JoyAxisHandler::reset()
{
pressed_= false;
}
bool JoyAxisHandler::update(SDL_Event &e)
{
if(e.type != SDL_JOYAXISMOTION || e.jaxis.which != joyid_ || e.jaxis.axis != axis_) return false;
pressed_ = (min_ <= e.jaxis.value && e.jaxis.value <= max_);
return true;
}
bool JoyAxisHandler::pressed()
{
return pressed_;
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "InputHandler.h"
class JoyAxisHandler : public InputHandler
{
public:
JoyAxisHandler(SDL_JoystickID joyid, Uint8 axis, Sint16 min, Sint16 max);
bool update(SDL_Event &e);
bool pressed();
void reset();
private:
SDL_JoystickID joyid_;
Uint8 axis_;
Sint16 min_;
Sint16 max_;
bool pressed_;
};

View File

@ -0,0 +1,32 @@
#include "JoyButtonHandler.h"
JoyButtonHandler::JoyButtonHandler(SDL_JoystickID joynum, Uint8 button)
: joynum_(joynum)
, button_(button)
, pressed_(false)
{
}
void JoyButtonHandler::reset()
{
pressed_= false;
}
bool JoyButtonHandler::update(SDL_Event &e)
{
if(e.type != SDL_JOYBUTTONUP && e.type != SDL_JOYBUTTONDOWN) return false;
if(e.jbutton.which == joynum_ && e.jbutton.button == button_)
{
pressed_ = (e.type == SDL_JOYBUTTONDOWN) ? true : false;
return true;
}
return false;
}
bool JoyButtonHandler::pressed()
{
return pressed_;
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "InputHandler.h"
class JoyButtonHandler : public InputHandler
{
public:
JoyButtonHandler(SDL_JoystickID joynum, Uint8 button);
bool update(SDL_Event &e);
bool pressed();
void reset();
private:
SDL_JoystickID joynum_;
Uint8 button_;
bool pressed_;
};

View File

@ -0,0 +1,28 @@
#include "JoyHatHandler.h"
JoyHatHandler::JoyHatHandler(SDL_JoystickID joynum, Uint8 hatnum, Uint8 direction)
: joynum_(joynum)
, hatnum_(hatnum)
, direction_(direction)
, pressed_(false)
{
}
void JoyHatHandler::reset()
{
pressed_= false;
}
bool JoyHatHandler::update(SDL_Event &e)
{
if(e.type != SDL_JOYHATMOTION || e.jhat.which != joynum_ || e.jhat.hat != hatnum_) return false;
pressed_ = (e.jhat.value == direction_);
return true;
}
bool JoyHatHandler::pressed()
{
return pressed_;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "InputHandler.h"
class JoyHatHandler : public InputHandler
{
public:
JoyHatHandler(SDL_JoystickID joynum, Uint8 hatnum, Uint8 direction);
bool update(SDL_Event &e);
bool pressed();
void reset();
private:
SDL_JoystickID joynum_;
Uint8 hatnum_;
Uint8 direction_;
bool pressed_;
};

View File

@ -0,0 +1,31 @@
#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.type != SDL_KEYUP && e.type != SDL_KEYDOWN) return false;
if(e.key.keysym.scancode == scancode_)
{
pressed_ = (e.type == SDL_KEYDOWN);
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

@ -0,0 +1,31 @@
#include "MouseButtonHandler.h"
MouseButtonHandler::MouseButtonHandler(Uint8 button)
: button_(button)
, pressed_(false)
{
}
void MouseButtonHandler::reset()
{
pressed_= false;
}
bool MouseButtonHandler::update(SDL_Event &e)
{
if(e.type != SDL_MOUSEBUTTONUP && e.type != SDL_MOUSEBUTTONDOWN) return false;
if(e.button.button == button_)
{
pressed_ = (e.type == SDL_MOUSEBUTTONDOWN) ? true : false;
return true;
}
return false;
}
bool MouseButtonHandler::pressed()
{
return pressed_;
}

View File

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

View File

@ -17,10 +17,22 @@
#include "UserInput.h"
#include "../Database/Configuration.h"
#include "../Utility/Log.h"
#include "../Utility/Utils.h"
#include "JoyAxisHandler.h"
#include "JoyButtonHandler.h"
#include "JoyHatHandler.h"
#include "KeyboardHandler.h"
#include "MouseButtonHandler.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 +71,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 +90,146 @@ 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;
}
description = Utils::toLower(description);
keyMap_[key] = scanCode;
reverseKeyMap_[scanCode] = key;
keyState_[key] = false;
return true;
if(description.find("mouse") == 0)
{
std::string mousedesc = Utils::replace(Utils::toLower(description), "mouse", "");
if(mousedesc.find("button") == 0)
{
int button = 0;
std::stringstream ss;
mousedesc = Utils::replace(mousedesc, "button", "");
if(mousedesc == "left") button = SDL_BUTTON_LEFT;
else if(mousedesc == "middle") button = SDL_BUTTON_MIDDLE;
else if(mousedesc == "right") button = SDL_BUTTON_RIGHT;
else if(mousedesc == "x1") button = SDL_BUTTON_X1;
else if(mousedesc == "x2") button = SDL_BUTTON_X2;
keyHandlers_[key] = new MouseButtonHandler(button);
Logger::write(Logger::ZONE_INFO, "Input", "Binding mouse button " + ss.str() );
return true;
}
}
else if(description.find("joy") == 0)
{
std::string joydesc = Utils::replace(Utils::toLower(description), "joy", "");
std::stringstream ssjoy;
ssjoy << joydesc.at(0);
int joynum;
ssjoy >> joynum;
joydesc = joydesc.erase(0, 1);
if(joydesc.find("button") == 0)
{
unsigned int button;
std::stringstream ss;
ss << Utils::replace(joydesc, "button", "");
ss >> button;
keyHandlers_[key] = new JoyButtonHandler(joynum, button);
Logger::write(Logger::ZONE_INFO, "Input", "Binding joypad button " + ss.str() );
return true;
}
else if(joydesc.find("hat") == 0)
{
Uint8 hat;
joydesc = Utils::replace(joydesc, "hat", "");
std::stringstream sshat;
sshat << joydesc.at(0);
int hatnum;
ssjoy >> hatnum;
joydesc = joydesc.erase(0, 1);
if(joydesc == "leftup") hat = SDL_HAT_LEFTUP;
else if(joydesc == "left") hat = SDL_HAT_LEFT;
else if(joydesc == "leftdown") hat = SDL_HAT_LEFTDOWN;
else if(joydesc == "up") hat = SDL_HAT_UP;
//else if(joydesc == "centered") hat = SDL_HAT_CENTERED;
else if(joydesc == "down") hat = SDL_HAT_DOWN;
else if(joydesc == "rightup") hat = SDL_HAT_RIGHTUP;
else if(joydesc == "right") hat = SDL_HAT_RIGHT;
else if(joydesc == "rightdown") hat = SDL_HAT_RIGHTDOWN;
keyHandlers_[key] = new JoyHatHandler(joynum, hatnum, hat);
Logger::write(Logger::ZONE_INFO, "Input", "Binding joypad hat " + joydesc );
return true;
}
else if(joydesc.find("axis") == 0)
{
// string is now axis0+
unsigned int axis;
Sint16 min;
Sint16 max;
joydesc = Utils::replace(joydesc, "axis", "");
// string is now 0+
if(joydesc.find("-") != std::string::npos)
{
min = -32768;
max = -1000;
joydesc = Utils::replace(joydesc, "-", "");
}
else if(joydesc.find("+") != std::string::npos)
{
min = 1000;
max = 32767;
joydesc = Utils::replace(joydesc, "+", "");
}
// string is now just the axis number
std::stringstream ss;
ss << joydesc;
ss >> axis;
Logger::write(Logger::ZONE_INFO, "Input", "Binding joypad axis " + ss.str() );
keyHandlers_[key] = new JoyAxisHandler(joynum, axis, min, max);
return true;
}
}
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

@ -40,6 +40,9 @@ Configuration::~Configuration()
void Configuration::initialize()
{
absolutePath = "D:/RetroFE";
return;
const char *environment = std::getenv("RETROFE_PATH");
std::string environmentStr;
if (environment != NULL)

View File

@ -374,7 +374,7 @@ bool Component::animate(bool loop)
for(unsigned int i = 0; i < tweens->size(); i++)
{
Tween *tween = tweens->tweens()->at(i);
float elapsedTime = elapsedTweenTime_;
double elapsedTime = elapsedTweenTime_;
//todo: too many levels of nesting
if(elapsedTime < tween->duration)

View File

@ -179,7 +179,7 @@ void ScrollingList::deallocateSpritePoints()
unsigned int spriteIndex = firstSpriteIndex_;
for(unsigned int i = 0; i < scrollPoints_->size(); ++i)
for(unsigned int i = 0; i < scrollPoints_->size() && spriteList_->size() > spriteIndex; ++i)
{
deallocateTexture(spriteList_->at(spriteIndex));
circularIncrement(spriteIndex, spriteList_);
@ -393,7 +393,7 @@ void ScrollingList::letterUp()
notifyAllRequested_ = true;
deallocateSpritePoints();
if(spriteList_ && scrollPoints_)
if(spriteList_ && scrollPoints_ && getSelectedCollectionItemSprite())
{
unsigned int i = 0;
@ -438,7 +438,7 @@ void ScrollingList::letterDown()
notifyAllRequested_ = true;
deallocateSpritePoints();
if(spriteList_ && scrollPoints_)
if(spriteList_ && scrollPoints_ && getSelectedCollectionItemSprite())
{
std::string startname = getSelectedCollectionItemSprite()->item->lowercaseFullTitle();

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;
@ -403,14 +403,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))
{