Joystick Support

celladd
Digmaster 10 years ago
parent 6c8a662042
commit c37881ead1

@ -190,7 +190,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
std::srand ( std::time(NULL) ); std::srand ( std::time(NULL) );
MWClass::registerClasses(); MWClass::registerClasses();
Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE; Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE|SDL_INIT_GAMECONTROLLER|SDL_INIT_JOYSTICK;
if(SDL_WasInit(flags) == 0) if(SDL_WasInit(flags) == 0)
{ {
//kindly ask SDL not to trash our OGL context //kindly ask SDL not to trash our OGL context

@ -37,11 +37,19 @@ namespace MWBase
virtual bool getControlSwitch (const std::string& sw) = 0; virtual bool getControlSwitch (const std::string& sw) = 0;
virtual std::string getActionDescription (int action) = 0; virtual std::string getActionDescription (int action) = 0;
virtual std::string getActionBindingName (int action) = 0; virtual std::string getActionKeyBindingName (int action) = 0;
virtual std::vector<int> getActionSorting () = 0; virtual std::string getActionControllerBindingName (int action) = 0;
virtual std::string sdlControllerAxisToString(int axis) = 0;
virtual std::string sdlControllerButtonToString(int button) = 0;
///Actions available for binding to keyboard buttons
virtual std::vector<int> getActionKeySorting() = 0;
///Actions available for binding to controller buttons
virtual std::vector<int> getActionControllerSorting() = 0;
virtual int getNumActions() = 0; virtual int getNumActions() = 0;
virtual void enableDetectingBindingMode (int action) = 0; ///If keyboard is true, only pay attention to keyboard events. If false, only pay attention to cntroller events (excluding esc)
virtual void resetToDefaultBindings() = 0; virtual void enableDetectingBindingMode (int action, bool keyboard) = 0;
virtual void resetToDefaultKeyBindings() = 0;
virtual void resetToDefaultControllerBindings() = 0;
}; };
} }

@ -156,7 +156,8 @@ namespace MWGui
} }
SettingsWindow::SettingsWindow() : SettingsWindow::SettingsWindow() :
WindowBase("openmw_settings_window.layout") WindowBase("openmw_settings_window.layout"),
mKeyboardMode(true)
{ {
configureWidgets(mMainWidget); configureWidgets(mMainWidget);
@ -180,6 +181,8 @@ namespace MWGui
getWidget(mResetControlsButton, "ResetControlsButton"); getWidget(mResetControlsButton, "ResetControlsButton");
getWidget(mRefractionButton, "RefractionButton"); getWidget(mRefractionButton, "RefractionButton");
getWidget(mDifficultySlider, "DifficultySlider"); getWidget(mDifficultySlider, "DifficultySlider");
getWidget(mKeyboardSwitch, "KeyboardButton");
getWidget(mControllerSwitch, "ControllerButton");
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SettingsWindow::onWindowResize); mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SettingsWindow::onWindowResize);
@ -191,6 +194,9 @@ namespace MWGui
mShadowsTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSizeChanged); mShadowsTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSizeChanged);
mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked);
mControllerSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onControllerSwitchClicked);
center(); center();
mResetControlsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onResetDefaultBindings); mResetControlsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onResetDefaultBindings);
@ -436,14 +442,33 @@ namespace MWGui
MWBase::Environment::get().getInputManager()->processChangedSettings(changed); MWBase::Environment::get().getInputManager()->processChangedSettings(changed);
} }
void SettingsWindow::onKeyboardSwitchClicked(MyGUI::Widget* _sender)
{
if(mKeyboardMode)
return;
mKeyboardMode = true;
updateControlsBox();
}
void SettingsWindow::onControllerSwitchClicked(MyGUI::Widget* _sender)
{
if(!mKeyboardMode)
return;
mKeyboardMode = false;
updateControlsBox();
}
void SettingsWindow::updateControlsBox() void SettingsWindow::updateControlsBox()
{ {
while (mControlsBox->getChildCount()) while (mControlsBox->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mControlsBox->getChildAt(0)); MyGUI::Gui::getInstance().destroyWidget(mControlsBox->getChildAt(0));
MWBase::Environment::get().getWindowManager ()->removeStaticMessageBox(); MWBase::Environment::get().getWindowManager()->removeStaticMessageBox();
std::vector<int> actions;
std::vector<int> actions = MWBase::Environment::get().getInputManager()->getActionSorting (); if(mKeyboardMode)
actions = MWBase::Environment::get().getInputManager()->getActionKeySorting();
else
actions = MWBase::Environment::get().getInputManager()->getActionControllerSorting();
const int h = 18; const int h = 18;
const int w = mControlsBox->getWidth() - 28; const int w = mControlsBox->getWidth() - 28;
@ -454,7 +479,11 @@ namespace MWGui
if (desc == "") if (desc == "")
continue; continue;
std::string binding = MWBase::Environment::get().getInputManager()->getActionBindingName (*it); std::string binding;
if(mKeyboardMode)
binding = MWBase::Environment::get().getInputManager()->getActionKeyBindingName(*it);
else
binding = MWBase::Environment::get().getInputManager()->getActionControllerBindingName(*it);
Gui::SharedStateButton* leftText = mControlsBox->createWidget<Gui::SharedStateButton>("SandTextButton", MyGUI::IntCoord(0,curH,w,h), MyGUI::Align::Default); Gui::SharedStateButton* leftText = mControlsBox->createWidget<Gui::SharedStateButton>("SandTextButton", MyGUI::IntCoord(0,curH,w,h), MyGUI::Align::Default);
leftText->setCaptionWithReplacing(desc); leftText->setCaptionWithReplacing(desc);
@ -488,7 +517,7 @@ namespace MWGui
MWBase::Environment::get().getWindowManager ()->staticMessageBox ("#{sControlsMenu3}"); MWBase::Environment::get().getWindowManager ()->staticMessageBox ("#{sControlsMenu3}");
MWBase::Environment::get().getWindowManager ()->disallowMouse(); MWBase::Environment::get().getWindowManager ()->disallowMouse();
MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId); MWBase::Environment::get().getInputManager ()->enableDetectingBindingMode (actionId, mKeyboardMode);
} }
@ -511,7 +540,10 @@ namespace MWGui
void SettingsWindow::onResetDefaultBindingsAccept() void SettingsWindow::onResetDefaultBindingsAccept()
{ {
MWBase::Environment::get().getInputManager ()->resetToDefaultBindings (); if(mKeyboardMode)
MWBase::Environment::get().getInputManager ()->resetToDefaultKeyBindings ();
else
MWBase::Environment::get().getInputManager()->resetToDefaultControllerBindings();
updateControlsBox (); updateControlsBox ();
} }

@ -45,6 +45,9 @@ namespace MWGui
// controls // controls
MyGUI::ScrollView* mControlsBox; MyGUI::ScrollView* mControlsBox;
MyGUI::Button* mResetControlsButton; MyGUI::Button* mResetControlsButton;
MyGUI::Button* mKeyboardSwitch;
MyGUI::Button* mControllerSwitch;
bool mKeyboardMode; //if true, setting up the keyboard. Otherwise, it's controller
void onOkButtonClicked(MyGUI::Widget* _sender); void onOkButtonClicked(MyGUI::Widget* _sender);
void onFpsToggled(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender);
@ -62,6 +65,8 @@ namespace MWGui
void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel); void onInputTabMouseWheel(MyGUI::Widget* _sender, int _rel);
void onResetDefaultBindings(MyGUI::Widget* _sender); void onResetDefaultBindings(MyGUI::Widget* _sender);
void onResetDefaultBindingsAccept (); void onResetDefaultBindingsAccept ();
void onKeyboardSwitchClicked(MyGUI::Widget* _sender);
void onControllerSwitchClicked(MyGUI::Widget* _sender);
void onWindowResize(MyGUI::Window* _sender); void onWindowResize(MyGUI::Window* _sender);

@ -2,6 +2,7 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreRenderWindow.h> #include <OgreRenderWindow.h>
#include <cmath>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
@ -32,6 +33,8 @@
#include "../mwgui/windowbase.hpp" #include "../mwgui/windowbase.hpp"
#include <iostream>
using namespace ICS; using namespace ICS;
namespace namespace
@ -120,6 +123,7 @@ namespace MWInput
, mAlwaysRunActive(Settings::Manager::getBool("always run", "Input")) , mAlwaysRunActive(Settings::Manager::getBool("always run", "Input"))
, mAttemptJump(false) , mAttemptJump(false)
, mControlsDisabled(false) , mControlsDisabled(false)
, mJoystickLastUsed(false)
{ {
Ogre::RenderWindow* window = ogre.getWindow (); Ogre::RenderWindow* window = ogre.getWindow ();
@ -128,6 +132,7 @@ namespace MWInput
mInputManager->setMouseEventCallback (this); mInputManager->setMouseEventCallback (this);
mInputManager->setKeyboardEventCallback (this); mInputManager->setKeyboardEventCallback (this);
mInputManager->setWindowEventCallback(this); mInputManager->setWindowEventCallback(this);
mInputManager->setControllerEventCallback(this);
std::string file = userFileExists ? userFile : ""; std::string file = userFileExists ? userFile : "";
mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last); mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last);
@ -135,6 +140,7 @@ namespace MWInput
adjustMouseRegion (window->getWidth(), window->getHeight()); adjustMouseRegion (window->getWidth(), window->getHeight());
loadKeyDefaults(); loadKeyDefaults();
loadControllerDefaults();
for (int i = 0; i < A_Last; ++i) for (int i = 0; i < A_Last; ++i)
{ {
@ -190,6 +196,15 @@ namespace MWInput
int action = channel->getNumber(); int action = channel->getNumber();
if(currentValue > .8) currentValue = 1.0;
else if(currentValue < .6) currentValue = 0.0;
else return;
if(previousValue > .8) previousValue = 1.0;
else if(previousValue < .6) previousValue = 0.0;
if(currentValue == previousValue) return;
if (mControlSwitch["playercontrols"]) if (mControlSwitch["playercontrols"])
{ {
if (action == A_Use) if (action == A_Use)
@ -326,6 +341,47 @@ namespace MWInput
mInputManager->warpMouse(mMouseX, mMouseY); mInputManager->warpMouse(mMouseX, mMouseY);
} }
if(mJoystickLastUsed)
{
if (mGuiCursorEnabled)
{
float xAxis = mInputBinder->getChannel(A_MoveLeftRight)->getValue()*2.0f-1.0f;
float yAxis = mInputBinder->getChannel(A_MoveForwardBackward)->getValue()*2.0f-1.0f;
float zAxis = mInputBinder->getChannel(A_LookUpDown)->getValue()*2.0f-1.0f;
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
// We keep track of our own mouse position, so that moving the mouse while in
// game mode does not move the position of the GUI cursor
mMouseX += xAxis * dt * 1500.0f;
mMouseY += yAxis * dt * 1500.0f;
mMouseWheel -= zAxis * dt * 1500.0f;
mMouseX = std::max(0.f, std::min(mMouseX, float(viewSize.width)));
mMouseY = std::max(0.f, std::min(mMouseY, float(viewSize.height)));
MyGUI::InputManager::getInstance().injectMouseMove( mMouseX, mMouseY, mMouseWheel);
mInputManager->warpMouse(mMouseX, mMouseY);
}
if (mMouseLookEnabled)
{
float xAxis = mInputBinder->getChannel(A_LookLeftRight)->getValue()*2.0f-1.0f;
float yAxis = mInputBinder->getChannel(A_LookUpDown)->getValue()*2.0f-1.0f;
resetIdleTime();
float rot[3];
rot[0] = yAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f) * (mInvertY ? -1 : 1) * mCameraYMultiplier;
rot[1] = 0.0f;
rot[2] = xAxis * (dt * 100.0f) * 10.0f * mCameraSensitivity * (1.0f/256.f);
// Only actually turn player when we're not in vanity mode
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
{
mPlayer->yaw(rot[2]);
mPlayer->pitch(rot[0]);
}
}
}
// Disable movement in Gui mode // Disable movement in Gui mode
if (!(MWBase::Environment::get().getWindowManager()->isGuiMode() if (!(MWBase::Environment::get().getWindowManager()->isGuiMode()
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)) || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running))
@ -335,34 +391,74 @@ namespace MWInput
if (mControlSwitch["playercontrols"]) if (mControlSwitch["playercontrols"])
{ {
bool triedToMove = false; bool triedToMove = false;
if (actionIsActive(A_MoveLeft)) bool isRunning = false;
{ if(mJoystickLastUsed)
triedToMove = true;
mPlayer->setLeftRight (-1);
}
else if (actionIsActive(A_MoveRight))
{ {
triedToMove = true; float xAxis = mInputBinder->getChannel(A_MoveLeftRight)->getValue();
mPlayer->setLeftRight (1); float yAxis = mInputBinder->getChannel(A_MoveForwardBackward)->getValue();
} if (xAxis < .5)
{
triedToMove = true;
mPlayer->setLeftRight (-1);
}
else if (xAxis > .5)
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
if (actionIsActive(A_MoveForward)) if (yAxis < .5)
{ {
triedToMove = true; triedToMove = true;
mPlayer->setAutoMove (false); mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1); mPlayer->setForwardBackward (1);
}
else if (yAxis > .5)
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;
mPlayer->setForwardBackward (1);
}
isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25;
if(triedToMove) resetIdleTime();
} }
else if (actionIsActive(A_MoveBackward)) else
{ {
triedToMove = true; if (actionIsActive(A_MoveLeft))
mPlayer->setAutoMove (false); {
mPlayer->setForwardBackward (-1); triedToMove = true;
} mPlayer->setLeftRight (-1);
}
else if (actionIsActive(A_MoveRight))
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
else if(mPlayer->getAutoMove()) if (actionIsActive(A_MoveForward))
{ {
triedToMove = true; triedToMove = true;
mPlayer->setForwardBackward (1); mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;
mPlayer->setForwardBackward (1);
}
} }
mPlayer->setSneak(actionIsActive(A_Sneak)); mPlayer->setSneak(actionIsActive(A_Sneak));
@ -374,7 +470,7 @@ namespace MWInput
mOverencumberedMessageDelay = 0.f; mOverencumberedMessageDelay = 0.f;
} }
if (mAlwaysRunActive) if (mAlwaysRunActive || isRunning)
mPlayer->setRunState(!actionIsActive(A_Run)); mPlayer->setRunState(!actionIsActive(A_Run));
else else
mPlayer->setRunState(actionIsActive(A_Run)); mPlayer->setRunState(actionIsActive(A_Run));
@ -519,6 +615,7 @@ namespace MWInput
} }
if (!mControlsDisabled && !consumed) if (!mControlsDisabled && !consumed)
mInputBinder->keyPressed (arg); mInputBinder->keyPressed (arg);
mJoystickLastUsed = false;
} }
void InputManager::textInput(const SDL_TextInputEvent &arg) void InputManager::textInput(const SDL_TextInputEvent &arg)
@ -531,6 +628,7 @@ namespace MWInput
void InputManager::keyReleased(const SDL_KeyboardEvent &arg ) void InputManager::keyReleased(const SDL_KeyboardEvent &arg )
{ {
mJoystickLastUsed = false;
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc))); setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)));
@ -539,6 +637,7 @@ namespace MWInput
void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id )
{ {
mJoystickLastUsed = false;
bool guiMode = false; bool guiMode = false;
if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI only uses these mouse events if (id == SDL_BUTTON_LEFT || id == SDL_BUTTON_RIGHT) // MyGUI only uses these mouse events
@ -563,7 +662,8 @@ namespace MWInput
} }
void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id )
{ {
mJoystickLastUsed = false;
if(mInputBinder->detectingBindingState()) if(mInputBinder->detectingBindingState())
{ {
@ -583,6 +683,7 @@ namespace MWInput
{ {
mInputBinder->mouseMoved (arg); mInputBinder->mouseMoved (arg);
mJoystickLastUsed = false;
resetIdleTime (); resetIdleTime ();
if (mGuiCursorEnabled) if (mGuiCursorEnabled)
@ -631,6 +732,75 @@ namespace MWInput
} }
} }
void InputManager::buttonPressed( const SDL_ControllerButtonEvent &arg )
{
mJoystickLastUsed = true;
bool guiMode = false;
if (arg.button == SDL_CONTROLLER_BUTTON_A || arg.button == SDL_CONTROLLER_BUTTON_B) // We'll pretend that A is left click and B is right click
{
guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
guiMode = MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI((arg.button == SDL_CONTROLLER_BUTTON_B) ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT)) && guiMode;
if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0)
{
MyGUI::Button* b = MyGUI::InputManager::getInstance ().getMouseFocusWidget ()->castType<MyGUI::Button>(false);
if (b && b->getEnabled())
{
MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f);
}
}
}
setPlayerControlsEnabled(!guiMode);
//esc, to leave inital movie screen
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(SDLK_ESCAPE);
bool guiFocus = MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0);
setPlayerControlsEnabled(!guiFocus);
if (!mControlsDisabled)
mInputBinder->buttonPressed(arg);
}
void InputManager::buttonReleased( const SDL_ControllerButtonEvent &arg )
{
mJoystickLastUsed = true;
if(mInputBinder->detectingBindingState())
mInputBinder->buttonReleased(arg);
else if(arg.button == SDL_CONTROLLER_BUTTON_A || arg.button == SDL_CONTROLLER_BUTTON_B)
{
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode();
guiMode = MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI((arg.button == SDL_CONTROLLER_BUTTON_B) ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT)) && guiMode;
if(mInputBinder->detectingBindingState()) return; // don't allow same mouseup to bind as initiated bind
setPlayerControlsEnabled(!guiMode);
mInputBinder->buttonReleased(arg);
}
else
mInputBinder->buttonReleased(arg);
//to escape inital movie
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(SDLK_ESCAPE);
setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)));
}
void InputManager::axisMoved( const SDL_ControllerAxisEvent &arg )
{
mJoystickLastUsed = true;
if (!mControlsDisabled)
mInputBinder->axisMoved(arg);
}
void InputManager::controllerAdded(const SDL_ControllerDeviceEvent &arg)
{
mInputBinder->controllerAdded(arg);
}
void InputManager::controllerRemoved(const SDL_ControllerDeviceEvent &arg)
{
mInputBinder->controllerRemoved(arg);
}
void InputManager::windowFocusChange(bool have_focus) void InputManager::windowFocusChange(bool have_focus)
{ {
} }
@ -877,7 +1047,7 @@ namespace MWInput
bool InputManager::actionIsActive (int id) bool InputManager::actionIsActive (int id)
{ {
return mInputBinder->getChannel (id)->getValue () == 1; return (mInputBinder->getChannel (id)->getValue ()!=0.0);
} }
void InputManager::loadKeyDefaults (bool force) void InputManager::loadKeyDefaults (bool force)
@ -945,14 +1115,80 @@ namespace MWInput
&& mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS && mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS
)) ))
{ {
clearAllBindings (control); clearAllKeyBindings(control);
if (defaultKeyBindings.find(i) != defaultKeyBindings.end() if (defaultKeyBindings.find(i) != defaultKeyBindings.end()
&& !mInputBinder->isKeyBound(defaultKeyBindings[i])) && !mInputBinder->isKeyBound(defaultKeyBindings[i]))
{
mInputBinder->addKeyBinding(control, defaultKeyBindings[i], ICS::Control::INCREASE); mInputBinder->addKeyBinding(control, defaultKeyBindings[i], ICS::Control::INCREASE);
}
else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end() else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end()
&& !mInputBinder->isMouseButtonBound(defaultMouseButtonBindings[i])) && !mInputBinder->isMouseButtonBound(defaultMouseButtonBindings[i]))
{
mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE);
}
}
}
}
void InputManager::loadControllerDefaults(bool force)
{
// using hardcoded key defaults is inevitable, if we want the configuration files to stay valid
// across different versions of OpenMW (in the case where another input action is added)
std::map<int, int> defaultButtonBindings;
defaultButtonBindings[A_Activate] = SDL_CONTROLLER_BUTTON_A;
defaultButtonBindings[A_ToggleWeapon] = SDL_CONTROLLER_BUTTON_X;
defaultButtonBindings[A_ToggleSpell] = SDL_CONTROLLER_BUTTON_LEFTSHOULDER;
//defaultButtonBindings[A_QuickButtonsMenu] = SDL_GetButtonFromScancode(SDL_SCANCODE_F1); // Need to implement, should be ToggleSpell(5) AND Wait(9)
defaultButtonBindings[A_Sneak] = SDL_CONTROLLER_BUTTON_RIGHTSTICK;
defaultButtonBindings[A_Jump] = SDL_CONTROLLER_BUTTON_Y;
defaultButtonBindings[A_Journal] = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
defaultButtonBindings[A_Rest] = SDL_CONTROLLER_BUTTON_BACK;
defaultButtonBindings[A_TogglePOV] = SDL_CONTROLLER_BUTTON_LEFTSTICK;
defaultButtonBindings[A_Inventory] = SDL_CONTROLLER_BUTTON_B;
defaultButtonBindings[A_GameMenu] = SDL_CONTROLLER_BUTTON_START;
defaultButtonBindings[A_QuickSave] = SDL_CONTROLLER_BUTTON_GUIDE;
defaultButtonBindings[A_QuickKey1] = SDL_CONTROLLER_BUTTON_DPAD_UP;
defaultButtonBindings[A_QuickKey2] = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
defaultButtonBindings[A_QuickKey3] = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
defaultButtonBindings[A_QuickKey4] = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
std::map<int, int> defaultAxisBindings;
defaultAxisBindings[A_MoveForwardBackward] = SDL_CONTROLLER_AXIS_LEFTY;
defaultAxisBindings[A_MoveLeftRight] = SDL_CONTROLLER_AXIS_LEFTX;
defaultAxisBindings[A_LookUpDown] = SDL_CONTROLLER_AXIS_RIGHTY;
defaultAxisBindings[A_LookLeftRight] = SDL_CONTROLLER_AXIS_RIGHTX;
defaultAxisBindings[A_Use] = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;
for (int i = 0; i < A_Last; i++)
{
ICS::Control* control;
bool controlExists = mInputBinder->getChannel(i)->getControlsCount () != 0;
if (!controlExists)
{
control = new ICS::Control(boost::lexical_cast<std::string>(i), false, true, 0, ICS::ICS_MAX, ICS::ICS_MAX);
mInputBinder->addControl(control);
control->attachChannel(mInputBinder->getChannel(i), ICS::Channel::DIRECT);
}
else
{
control = mInputBinder->getChannel(i)->getAttachedControls ().front().control;
}
if (!controlExists || force || ( mInputBinder->getJoystickAxisBinding (control, ICS::Control::INCREASE) == ICS::InputControlSystem::UNASSIGNED && mInputBinder->getJoystickButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS ))
{
clearAllControllerBindings(control);
if (defaultButtonBindings.find(i) != defaultButtonBindings.end())
{
control->setValue(0.5f);
mInputBinder->addJoystickButtonBinding(control, defaultButtonBindings[i], ICS::Control::INCREASE);
}
else if (defaultAxisBindings.find(i) != defaultAxisBindings.end())
{
mInputBinder->addJoystickAxisBinding(control, defaultAxisBindings[i], ICS::Control::INCREASE);
}
} }
} }
} }
@ -1002,7 +1238,7 @@ namespace MWInput
return "#{" + descriptions[action] + "}"; return "#{" + descriptions[action] + "}";
} }
std::string InputManager::getActionBindingName (int action) std::string InputManager::getActionKeyBindingName (int action)
{ {
if (mInputBinder->getChannel (action)->getControlsCount () == 0) if (mInputBinder->getChannel (action)->getControlsCount () == 0)
return "#{sNone}"; return "#{sNone}";
@ -1017,7 +1253,81 @@ namespace MWInput
return "#{sNone}"; return "#{sNone}";
} }
std::vector<int> InputManager::getActionSorting() std::string InputManager::getActionControllerBindingName (int action)
{
if (mInputBinder->getChannel (action)->getControlsCount () == 0)
return "#{sNone}";
ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control;
if (mInputBinder->getJoystickAxisBinding (c, ICS::Control::INCREASE) != ICS::InputControlSystem::UNASSIGNED)
return sdlControllerAxisToString(mInputBinder->getJoystickAxisBinding (c, ICS::Control::INCREASE));
else if (mInputBinder->getJoystickButtonBinding (c, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS )
return sdlControllerButtonToString(mInputBinder->getJoystickButtonBinding (c, ICS::Control::INCREASE));
else
return "#{sNone}";
}
std::string InputManager::sdlControllerButtonToString(int button)
{
switch(button)
{
case SDL_CONTROLLER_BUTTON_A:
return "A Button";
case SDL_CONTROLLER_BUTTON_B:
return "B Button";
case SDL_CONTROLLER_BUTTON_BACK:
return "Back Button";
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
return "DPad Down";
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
return "DPad Left";
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
return "DPad Right";
case SDL_CONTROLLER_BUTTON_DPAD_UP:
return "DPad Up";
case SDL_CONTROLLER_BUTTON_GUIDE:
return "Guide Button";
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
return "Left Shoulder";
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
return "Left Stick Button";
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
return "Right Shoulder";
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
return "Right Stick Button";
case SDL_CONTROLLER_BUTTON_START:
return "Start Button";
case SDL_CONTROLLER_BUTTON_X:
return "X Button";
case SDL_CONTROLLER_BUTTON_Y:
return "Y Button";
default:
return "Button " + boost::lexical_cast<std::string>(button);
}
}
std::string InputManager::sdlControllerAxisToString(int axis)
{
switch(axis)
{
case SDL_CONTROLLER_AXIS_LEFTX:
return "Left Stick X";
case SDL_CONTROLLER_AXIS_LEFTY:
return "Left Stick Y";
case SDL_CONTROLLER_AXIS_RIGHTX:
return "Right Stick X";
case SDL_CONTROLLER_AXIS_RIGHTY:
return "Right Stick Y";
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
return "Left Trigger";
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
return "Right Trigger";
default:
return "Axis " + boost::lexical_cast<std::string>(axis);
}
}
std::vector<int> InputManager::getActionKeySorting()
{ {
std::vector<int> ret; std::vector<int> ret;
ret.push_back(A_MoveForward); ret.push_back(A_MoveForward);
@ -1055,11 +1365,42 @@ namespace MWInput
return ret; return ret;
} }
std::vector<int> InputManager::getActionControllerSorting()
{
std::vector<int> ret;
ret.push_back(A_TogglePOV);
ret.push_back(A_Sneak);
ret.push_back(A_Activate);
ret.push_back(A_Use);
ret.push_back(A_ToggleWeapon);
ret.push_back(A_ToggleSpell);
ret.push_back(A_AutoMove);
ret.push_back(A_Jump);
ret.push_back(A_Inventory);
ret.push_back(A_Journal);
ret.push_back(A_Rest);
ret.push_back(A_QuickSave);
ret.push_back(A_QuickLoad);
ret.push_back(A_Screenshot);
ret.push_back(A_QuickKeysMenu);
ret.push_back(A_QuickKey1);
ret.push_back(A_QuickKey2);
ret.push_back(A_QuickKey3);
ret.push_back(A_QuickKey4);
ret.push_back(A_QuickKey5);
ret.push_back(A_QuickKey6);
ret.push_back(A_QuickKey7);
ret.push_back(A_QuickKey8);
ret.push_back(A_QuickKey9);
ret.push_back(A_QuickKey10);
return ret;
}
void InputManager::enableDetectingBindingMode (int action) void InputManager::enableDetectingBindingMode (int action, bool keyboard)
{ {
mDetectingKeyboard = keyboard;
ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control; ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control;
mInputBinder->enableDetectingBindingState (c, ICS::Control::INCREASE); mInputBinder->enableDetectingBindingState (c, ICS::Control::INCREASE);
} }
@ -1075,9 +1416,16 @@ namespace MWInput
{ {
//Disallow binding escape key //Disallow binding escape key
if(key==SDL_SCANCODE_ESCAPE) if(key==SDL_SCANCODE_ESCAPE)
{
//Stop binding if esc pressed
mInputBinder->cancelDetectingBindingState();
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound ();
return;
}
if(!mDetectingKeyboard)
return; return;
clearAllBindings(control); clearAllKeyBindings(control);
ICS::DetectingBindingListener::keyBindingDetected (ICS, control, key, direction); ICS::DetectingBindingListener::keyBindingDetected (ICS, control, key, direction);
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound ();
} }
@ -1085,59 +1433,66 @@ namespace MWInput
void InputManager::mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control void InputManager::mouseButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, unsigned int button, ICS::Control::ControlChangingDirection direction) , unsigned int button, ICS::Control::ControlChangingDirection direction)
{ {
clearAllBindings(control); if(!mDetectingKeyboard)
return;
clearAllKeyBindings(control);
ICS::DetectingBindingListener::mouseButtonBindingDetected (ICS, control, button, direction); ICS::DetectingBindingListener::mouseButtonBindingDetected (ICS, control, button, direction);
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound ();
} }
void InputManager::joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control void InputManager::joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, int axis, ICS::Control::ControlChangingDirection direction) , int axis, ICS::Control::ControlChangingDirection direction)
{ {
clearAllBindings(control); //only allow binding to the trigers
ICS::DetectingBindingListener::joystickAxisBindingDetected (ICS, control, deviceId, axis, direction); if(axis != SDL_CONTROLLER_AXIS_TRIGGERLEFT && axis != SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); return;
} if(mDetectingKeyboard)
return;
void InputManager::joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, unsigned int button, ICS::Control::ControlChangingDirection direction)
{
clearAllBindings(control);
ICS::DetectingBindingListener::joystickButtonBindingDetected (ICS, control, deviceId, button, direction);
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound ();
}
void InputManager::joystickPOVBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control clearAllControllerBindings(control);
, int deviceId, int pov,ICS:: InputControlSystem::POVAxis axis, ICS::Control::ControlChangingDirection direction) control->setValue(0.5f); //axis bindings must start at 0.5
{ ICS::DetectingBindingListener::joystickAxisBindingDetected (ICS, control, axis, direction);
clearAllBindings(control);
ICS::DetectingBindingListener::joystickPOVBindingDetected (ICS, control, deviceId, pov, axis, direction);
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound ();
} }
void InputManager::joystickSliderBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control void InputManager::joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, int slider, ICS::Control::ControlChangingDirection direction) , unsigned int button, ICS::Control::ControlChangingDirection direction)
{ {
clearAllBindings(control); if(mDetectingKeyboard)
ICS::DetectingBindingListener::joystickSliderBindingDetected (ICS, control, deviceId, slider, direction); return;
clearAllControllerBindings(control);
ICS::DetectingBindingListener::joystickButtonBindingDetected (ICS, control, button, direction);
MWBase::Environment::get().getWindowManager ()->notifyInputActionBound (); MWBase::Environment::get().getWindowManager ()->notifyInputActionBound ();
} }
void InputManager::clearAllBindings (ICS::Control* control) void InputManager::clearAllKeyBindings (ICS::Control* control)
{ {
// right now we don't really need multiple bindings for the same action, so remove all others first // right now we don't really need multiple bindings for the same action, so remove all others first
if (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN) if (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN)
mInputBinder->removeKeyBinding (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE)); mInputBinder->removeKeyBinding (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE));
if (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) if (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS)
mInputBinder->removeMouseButtonBinding (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE)); mInputBinder->removeMouseButtonBinding (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE));
}
/// \todo add joysticks here once they are added void InputManager::clearAllControllerBindings (ICS::Control* control)
{
// right now we don't really need multiple bindings for the same action, so remove all others first
if (mInputBinder->getJoystickAxisBinding (control, ICS::Control::INCREASE) != SDL_SCANCODE_UNKNOWN)
mInputBinder->removeJoystickAxisBinding (mInputBinder->getJoystickAxisBinding (control, ICS::Control::INCREASE));
if (mInputBinder->getJoystickButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS)
mInputBinder->removeJoystickButtonBinding (mInputBinder->getJoystickButtonBinding (control, ICS::Control::INCREASE));
} }
void InputManager::resetToDefaultBindings() void InputManager::resetToDefaultKeyBindings()
{ {
loadKeyDefaults(true); loadKeyDefaults(true);
} }
void InputManager::resetToDefaultControllerBindings()
{
loadControllerDefaults(true);
}
MyGUI::MouseButton InputManager::sdlButtonToMyGUI(Uint8 button) MyGUI::MouseButton InputManager::sdlButtonToMyGUI(Uint8 button)
{ {
//The right button is the second button, according to MyGUI //The right button is the second button, according to MyGUI

@ -55,6 +55,7 @@ namespace MWInput
public SFO::KeyListener, public SFO::KeyListener,
public SFO::MouseListener, public SFO::MouseListener,
public SFO::WindowListener, public SFO::WindowListener,
public SFO::ControllerListener,
public ICS::ChannelListener, public ICS::ChannelListener,
public ICS::DetectingBindingListener public ICS::DetectingBindingListener
{ {
@ -82,11 +83,16 @@ namespace MWInput
virtual bool getControlSwitch (const std::string& sw); virtual bool getControlSwitch (const std::string& sw);
virtual std::string getActionDescription (int action); virtual std::string getActionDescription (int action);
virtual std::string getActionBindingName (int action); virtual std::string getActionKeyBindingName (int action);
virtual std::string getActionControllerBindingName (int action);
virtual std::string sdlControllerAxisToString(int axis);
virtual std::string sdlControllerButtonToString(int button);
virtual int getNumActions() { return A_Last; } virtual int getNumActions() { return A_Last; }
virtual std::vector<int> getActionSorting (); virtual std::vector<int> getActionKeySorting();
virtual void enableDetectingBindingMode (int action); virtual std::vector<int> getActionControllerSorting();
virtual void resetToDefaultBindings(); virtual void enableDetectingBindingMode (int action, bool keyboard);
virtual void resetToDefaultKeyBindings();
virtual void resetToDefaultControllerBindings();
public: public:
virtual void keyPressed(const SDL_KeyboardEvent &arg ); virtual void keyPressed(const SDL_KeyboardEvent &arg );
@ -97,6 +103,12 @@ namespace MWInput
virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ); virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id );
virtual void mouseMoved( const SFO::MouseMotionEvent &arg ); virtual void mouseMoved( const SFO::MouseMotionEvent &arg );
virtual void buttonPressed( const SDL_ControllerButtonEvent &arg);
virtual void buttonReleased( const SDL_ControllerButtonEvent &arg);
virtual void axisMoved( const SDL_ControllerAxisEvent &arg);
virtual void controllerAdded( const SDL_ControllerDeviceEvent &arg);
virtual void controllerRemoved( const SDL_ControllerDeviceEvent &arg);
virtual void windowVisibilityChange( bool visible ); virtual void windowVisibilityChange( bool visible );
virtual void windowFocusChange( bool have_focus ); virtual void windowFocusChange( bool have_focus );
virtual void windowResized (int x, int y); virtual void windowResized (int x, int y);
@ -114,20 +126,16 @@ namespace MWInput
, unsigned int button, ICS::Control::ControlChangingDirection direction); , unsigned int button, ICS::Control::ControlChangingDirection direction);
virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control virtual void joystickAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, int axis, ICS::Control::ControlChangingDirection direction); , int axis, ICS::Control::ControlChangingDirection direction);
virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control virtual void joystickButtonBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, unsigned int button, ICS::Control::ControlChangingDirection direction); , unsigned int button, ICS::Control::ControlChangingDirection direction);
virtual void joystickPOVBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, int pov,ICS:: InputControlSystem::POVAxis axis, ICS::Control::ControlChangingDirection direction);
virtual void joystickSliderBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control
, int deviceId, int slider, ICS::Control::ControlChangingDirection direction);
void clearAllBindings (ICS::Control* control); void clearAllKeyBindings (ICS::Control* control);
void clearAllControllerBindings (ICS::Control* control);
private: private:
bool mJoystickLastUsed;
OEngine::Render::OgreRenderer &mOgre; OEngine::Render::OgreRenderer &mOgre;
MWWorld::Player* mPlayer; MWWorld::Player* mPlayer;
OMW::Engine& mEngine; OMW::Engine& mEngine;
@ -156,6 +164,8 @@ namespace MWInput
bool mMouseLookEnabled; bool mMouseLookEnabled;
bool mGuiCursorEnabled; bool mGuiCursorEnabled;
bool mDetectingKeyboard;
float mOverencumberedMessageDelay; float mOverencumberedMessageDelay;
float mMouseX; float mMouseX;
@ -191,12 +201,15 @@ namespace MWInput
void quickLoad(); void quickLoad();
void quickSave(); void quickSave();
bool isAReverse(int action);
void quickKey (int index); void quickKey (int index);
void showQuickKeysMenu(); void showQuickKeysMenu();
bool actionIsActive (int id); bool actionIsActive (int id);
void loadKeyDefaults(bool force = false); void loadKeyDefaults(bool force = false);
void loadControllerDefaults(bool force = false);
private: private:
enum Actions enum Actions
@ -261,6 +274,11 @@ namespace MWInput
A_ToggleDebug, A_ToggleDebug,
A_LookUpDown, //Joystick look
A_LookLeftRight,
A_MoveForwardBackward,
A_MoveLeftRight,
A_Last // Marker for the last item A_Last // Marker for the last item
}; };
}; };

@ -268,7 +268,7 @@ namespace MWScript
std::string InterpreterContext::getActionBinding(const std::string& action) const std::string InterpreterContext::getActionBinding(const std::string& action) const
{ {
std::vector<int> actions = MWBase::Environment::get().getInputManager()->getActionSorting (); std::vector<int> actions = MWBase::Environment::get().getInputManager()->getActionKeySorting ();
for (std::vector<int>::const_iterator it = actions.begin(); it != actions.end(); ++it) for (std::vector<int>::const_iterator it = actions.begin(); it != actions.end(); ++it)
{ {
std::string desc = MWBase::Environment::get().getInputManager()->getActionDescription (*it); std::string desc = MWBase::Environment::get().getInputManager()->getActionDescription (*it);
@ -276,7 +276,7 @@ namespace MWScript
continue; continue;
if(desc == action) if(desc == action)
return MWBase::Environment::get().getInputManager()->getActionBindingName (*it); return MWBase::Environment::get().getInputManager()->getActionKeyBindingName (*it);
} }
return "None"; return "None";

@ -43,10 +43,10 @@ namespace ICS
, mAxisBindable(axisBindable) , mAxisBindable(axisBindable)
, currentChangingDirection(STOP) , currentChangingDirection(STOP)
{ {
} }
Control::~Control() Control::~Control()
{ {
mAttachedChannels.clear(); mAttachedChannels.clear();
} }
@ -92,7 +92,7 @@ namespace ICS
} }
void Control::setChangingDirection(ControlChangingDirection direction) void Control::setChangingDirection(ControlChangingDirection direction)
{ {
currentChangingDirection = direction; currentChangingDirection = direction;
mPendingActions.push_back(direction); mPendingActions.push_back(direction);
} }
@ -102,9 +102,9 @@ namespace ICS
if(!mPendingActions.empty()) if(!mPendingActions.empty())
{ {
size_t timedActionsCount = 0; size_t timedActionsCount = 0;
std::list<Control::ControlChangingDirection>::iterator cached_end = mPendingActions.end(); std::list<Control::ControlChangingDirection>::iterator cached_end = mPendingActions.end();
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ; for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
it != cached_end ; ++it) it != cached_end ; ++it)
{ {
if( (*it) != Control::STOP ) if( (*it) != Control::STOP )
@ -112,14 +112,14 @@ namespace ICS
timedActionsCount++; timedActionsCount++;
} }
} }
float timeSinceLastFramePart = timeSinceLastFrame / std::max<size_t>(1, timedActionsCount); float timeSinceLastFramePart = timeSinceLastFrame / std::max<size_t>(1, timedActionsCount);
for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ; for(std::list<Control::ControlChangingDirection>::iterator it = mPendingActions.begin() ;
it != cached_end ; ++it) it != cached_end ; ++it)
{ {
if( (*it) != Control::STOP ) if( (*it) != Control::STOP )
{ {
this->setValue(mValue + this->setValue(mValue +
(((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart))); (((int)(*it)) * mStepSize * mStepsPerSeconds * (timeSinceLastFramePart)));
} }
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue ) else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )
@ -141,7 +141,7 @@ namespace ICS
} }
else if( currentChangingDirection != Control::STOP ) else if( currentChangingDirection != Control::STOP )
{ {
this->setValue(mValue + this->setValue(mValue +
(((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame))); (((int)currentChangingDirection) * mStepSize * mStepsPerSeconds * (timeSinceLastFrame)));
} }
else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue ) else if(mAutoReverseToInitialValue && !mIgnoreAutoReverse && mValue != mInitialValue )

@ -57,10 +57,10 @@ namespace ICS
xmlDoc = new TiXmlDocument(file.c_str()); xmlDoc = new TiXmlDocument(file.c_str());
xmlDoc->LoadFile(); xmlDoc->LoadFile();
if(xmlDoc->Error()) if(xmlDoc->Error())
{ {
std::ostringstream message; std::ostringstream message;
message << "TinyXml reported an error reading \""+ file + "\". Row " << message << "TinyXml reported an error reading \""+ file + "\". Row " <<
(int)xmlDoc->ErrorRow() << ", Col " << (int)xmlDoc->ErrorCol() << ": " << (int)xmlDoc->ErrorRow() << ", Col " << (int)xmlDoc->ErrorCol() << ": " <<
xmlDoc->ErrorDesc() ; xmlDoc->ErrorDesc() ;
ICS_LOG(message.str()); ICS_LOG(message.str());
@ -78,10 +78,10 @@ namespace ICS
TiXmlElement* xmlControl = xmlRoot->FirstChildElement("Control"); TiXmlElement* xmlControl = xmlRoot->FirstChildElement("Control");
size_t controlChannelCount = 0; size_t controlChannelCount = 0;
while(xmlControl) while(xmlControl)
{ {
TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel");
while(xmlChannel) while(xmlChannel)
{ {
controlChannelCount = std::max(channelCount, FromString<size_t>(xmlChannel->Attribute("number"))+1); controlChannelCount = std::max(channelCount, FromString<size_t>(xmlChannel->Attribute("number"))+1);
@ -108,7 +108,7 @@ namespace ICS
// <interval type="bezier" startX="0.5" startY="0.5" midX="0.75" midY="0.5" endX="1.0" endY="1.0" step="0.1" /> // <interval type="bezier" startX="0.5" startY="0.5" midX="0.75" midY="0.5" endX="1.0" endY="1.0" step="0.1" />
//</ChannelFilter> //</ChannelFilter>
TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter"); TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter");
while(xmlChannelFilter) while(xmlChannelFilter)
{ {
int ch = FromString<int>(xmlChannelFilter->Attribute("number")); int ch = FromString<int>(xmlChannelFilter->Attribute("number"));
@ -130,12 +130,12 @@ namespace ICS
float step = FromString<float>(xmlInterval->Attribute("step")); float step = FromString<float>(xmlInterval->Attribute("step"));
ICS_LOG("Applying Bezier filter to channel [number=" ICS_LOG("Applying Bezier filter to channel [number="
+ ToString<int>(ch) + ", startX=" + ToString<int>(ch) + ", startX="
+ ToString<float>(startX) + ", startY=" + ToString<float>(startX) + ", startY="
+ ToString<float>(startY) + ", midX=" + ToString<float>(startY) + ", midX="
+ ToString<float>(midX) + ", midY=" + ToString<float>(midX) + ", midY="
+ ToString<float>(midY) + ", endX=" + ToString<float>(midY) + ", endX="
+ ToString<float>(endX) + ", endY=" + ToString<float>(endX) + ", endY="
+ ToString<float>(endY) + ", step=" + ToString<float>(endY) + ", step="
+ ToString<float>(step) + "]"); + ToString<float>(step) + "]");
@ -149,8 +149,8 @@ namespace ICS
xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter"); xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter");
} }
xmlControl = xmlRoot->FirstChildElement("Control"); xmlControl = xmlRoot->FirstChildElement("Control");
while(xmlControl) while(xmlControl)
{ {
bool axisBindable = true; bool axisBindable = true;
if(xmlControl->Attribute("axisBindable")) if(xmlControl->Attribute("axisBindable"))
@ -173,11 +173,11 @@ namespace ICS
std::string value(xmlControl->Attribute("stepSize")); std::string value(xmlControl->Attribute("stepSize"));
if(value == "MAX") if(value == "MAX")
{ {
_stepSize = ICS_MAX; _stepSize = ICS_MAX;
} }
else else
{ {
_stepSize = FromString<float>(value.c_str()); _stepSize = FromString<float>(value.c_str());
} }
} }
else else
@ -191,7 +191,7 @@ namespace ICS
std::string value(xmlControl->Attribute("stepsPerSeconds")); std::string value(xmlControl->Attribute("stepsPerSeconds"));
if(value == "MAX") if(value == "MAX")
{ {
_stepsPerSeconds = ICS_MAX; _stepsPerSeconds = ICS_MAX;
} }
else else
{ {
@ -221,12 +221,8 @@ namespace ICS
loadJoystickButtonBinders(xmlControl); loadJoystickButtonBinders(xmlControl);
loadJoystickPOVBinders(xmlControl);
loadJoystickSliderBinders(xmlControl);
// Attach controls to channels // Attach controls to channels
TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel"); TiXmlElement* xmlChannel = xmlControl->FirstChildElement("Channel");
while(xmlChannel) while(xmlChannel)
{ {
ICS_LOG("\tAttaching control to channel [number=" ICS_LOG("\tAttaching control to channel [number="
@ -247,7 +243,7 @@ namespace ICS
{ {
percentage = val; percentage = val;
} }
} }
else else
{ {
ICS_LOG("ERROR: attaching percentage value range is [0,1]"); ICS_LOG("ERROR: attaching percentage value range is [0,1]");
@ -277,6 +273,35 @@ namespace ICS
} }
delete xmlDoc; delete xmlDoc;
}
/* Joystick Init */
//Load controller mappings
int res = SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt");
if(res == -1)
{
ICS_LOG(std::string("Error loading controller bindings: ")+SDL_GetError());
}
else
{
ICS_LOG(std::string("Loaded ")+boost::lexical_cast<std::string>(res)+" Game controller bindings");
}
//Open all presently connected sticks
int numSticks = SDL_NumJoysticks();
for(int i = 0; i < numSticks; i++)
{
if(SDL_IsGameController(i))
{
SDL_ControllerDeviceEvent evt;
evt.which = i;
controllerAdded(evt);
}
else
{
ICS_LOG(std::string("Unusable controller plugged in: ")+SDL_JoystickNameForIndex(i));
}
} }
ICS_LOG(" - InputControlSystem Created - "); ICS_LOG(" - InputControlSystem Created - ");
@ -335,7 +360,7 @@ namespace ICS
for(std::vector<Channel*>::const_iterator o = mChannels.begin() ; o != mChannels.end(); ++o) for(std::vector<Channel*>::const_iterator o = mChannels.begin() ; o != mChannels.end(); ++o)
{ {
ICS::IntervalList intervals = (*o)->getIntervals(); ICS::IntervalList intervals = (*o)->getIntervals();
if(intervals.size() > 1) // all channels have a default linear filter if(intervals.size() > 1) // all channels have a default linear filter
{ {
TiXmlElement ChannelFilter( "ChannelFilter" ); TiXmlElement ChannelFilter( "ChannelFilter" );
@ -368,7 +393,7 @@ namespace ICS
ChannelFilter.InsertEndChild(XMLInterval); ChannelFilter.InsertEndChild(XMLInterval);
} }
++interval; ++interval;
} }
@ -398,7 +423,7 @@ namespace ICS
control.SetAttribute( "autoReverseToInitialValue", "false" ); control.SetAttribute( "autoReverseToInitialValue", "false" );
} }
control.SetAttribute( "initialValue", ToString<float>((*o)->getInitialValue()).c_str() ); control.SetAttribute( "initialValue", ToString<float>((*o)->getInitialValue()).c_str() );
if((*o)->getStepSize() == ICS_MAX) if((*o)->getStepSize() == ICS_MAX)
{ {
control.SetAttribute( "stepSize", "MAX" ); control.SetAttribute( "stepSize", "MAX" );
@ -442,12 +467,12 @@ namespace ICS
control.InsertEndChild(keyBinder); control.InsertEndChild(keyBinder);
} }
if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)
!= InputControlSystem/*::NamedAxis*/::UNASSIGNED) != InputControlSystem/*::NamedAxis*/::UNASSIGNED)
{ {
TiXmlElement binder( "MouseBinder" ); TiXmlElement binder( "MouseBinder" );
InputControlSystem::NamedAxis axis = InputControlSystem::NamedAxis axis =
getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE); getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE);
if(axis == InputControlSystem/*::NamedAxis*/::X) if(axis == InputControlSystem/*::NamedAxis*/::X)
{ {
@ -466,12 +491,12 @@ namespace ICS
control.InsertEndChild(binder); control.InsertEndChild(binder);
} }
if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) if(getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)
!= InputControlSystem/*::NamedAxis*/::UNASSIGNED) != InputControlSystem/*::NamedAxis*/::UNASSIGNED)
{ {
TiXmlElement binder( "MouseBinder" ); TiXmlElement binder( "MouseBinder" );
InputControlSystem::NamedAxis axis = InputControlSystem::NamedAxis axis =
getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE); getMouseAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE);
if(axis == InputControlSystem/*::NamedAxis*/::X) if(axis == InputControlSystem/*::NamedAxis*/::X)
{ {
@ -490,7 +515,7 @@ namespace ICS
control.InsertEndChild(binder); control.InsertEndChild(binder);
} }
if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE) if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)
!= ICS_MAX_DEVICE_BUTTONS) != ICS_MAX_DEVICE_BUTTONS)
{ {
TiXmlElement binder( "MouseButtonBinder" ); TiXmlElement binder( "MouseButtonBinder" );
@ -516,7 +541,7 @@ namespace ICS
control.InsertEndChild(binder); control.InsertEndChild(binder);
} }
if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE) if(getMouseButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)
!= ICS_MAX_DEVICE_BUTTONS) != ICS_MAX_DEVICE_BUTTONS)
{ {
TiXmlElement binder( "MouseButtonBinder" ); TiXmlElement binder( "MouseButtonBinder" );
@ -541,152 +566,57 @@ namespace ICS
binder.SetAttribute( "direction", "DECREASE" ); binder.SetAttribute( "direction", "DECREASE" );
control.InsertEndChild(binder); control.InsertEndChild(binder);
} }
if(getJoystickAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)
!= /*NamedAxis::*/UNASSIGNED)
{
TiXmlElement binder( "JoystickAxisBinder" );
JoystickIDList::const_iterator it = mJoystickIDList.begin(); binder.SetAttribute( "axis", ToString<int>(
while(it != mJoystickIDList.end()) getJoystickAxisBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
{
int deviceId = *it;
if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)
!= /*NamedAxis::*/UNASSIGNED)
{
TiXmlElement binder( "JoystickAxisBinder" );
binder.SetAttribute( "axis", ToString<int>(
getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
binder.SetAttribute( "direction", "INCREASE" );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
control.InsertEndChild(binder);
}
if(getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)
!= /*NamedAxis::*/UNASSIGNED)
{
TiXmlElement binder( "JoystickAxisBinder" );
binder.SetAttribute( "axis", ToString<int>(
getJoystickAxisBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
binder.SetAttribute( "direction", "DECREASE" );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() ); binder.SetAttribute( "direction", "INCREASE" );
control.InsertEndChild(binder);
}
if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE) control.InsertEndChild(binder);
!= ICS_MAX_DEVICE_BUTTONS) }
{
TiXmlElement binder( "JoystickButtonBinder" );
binder.SetAttribute( "button", ToString<unsigned int>( if(getJoystickAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)
getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); != /*NamedAxis::*/UNASSIGNED)
{
TiXmlElement binder( "JoystickAxisBinder" );
binder.SetAttribute( "direction", "INCREASE" ); binder.SetAttribute( "axis", ToString<int>(
getJoystickAxisBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() ); binder.SetAttribute( "direction", "DECREASE" );
control.InsertEndChild(binder);
}
if(getJoystickButtonBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE) control.InsertEndChild(binder);
!= ICS_MAX_DEVICE_BUTTONS) }
{
TiXmlElement binder( "JoystickButtonBinder" );
binder.SetAttribute( "button", ToString<unsigned int>( if(getJoystickButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)
getJoystickButtonBinding(*o, *it, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); != ICS_MAX_DEVICE_BUTTONS)
{
TiXmlElement binder( "JoystickButtonBinder" );
binder.SetAttribute( "direction", "DECREASE" ); binder.SetAttribute( "button", ToString<unsigned int>(
getJoystickButtonBinding(*o, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() ); binder.SetAttribute( "direction", "INCREASE" );
control.InsertEndChild(binder);
}
if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE).index >= 0) control.InsertEndChild(binder);
{ }
TiXmlElement binder( "JoystickPOVBinder" );
POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE); if(getJoystickButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)
!= ICS_MAX_DEVICE_BUTTONS)
binder.SetAttribute( "pov", ToString<int>(POVPair.index).c_str() ); {
TiXmlElement binder( "JoystickButtonBinder" );
binder.SetAttribute( "direction", "INCREASE" ); binder.SetAttribute( "button", ToString<unsigned int>(
getJoystickButtonBinding(*o, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() ); binder.SetAttribute( "direction", "DECREASE" );
if(POVPair.axis == ICS::InputControlSystem::EastWest) control.InsertEndChild(binder);
{ }
binder.SetAttribute( "axis", "EastWest" );
}
else
{
binder.SetAttribute( "axis", "NorthSouth" );
}
control.InsertEndChild(binder);
}
if(getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE).index >= 0)
{
TiXmlElement binder( "JoystickPOVBinder" );
POVBindingPair POVPair = getJoystickPOVBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE);
binder.SetAttribute( "pov", ToString<int>(POVPair.index).c_str() );
binder.SetAttribute( "direction", "DECREASE" );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
if(POVPair.axis == ICS::InputControlSystem::EastWest)
{
binder.SetAttribute( "axis", "EastWest" );
}
else
{
binder.SetAttribute( "axis", "NorthSouth" );
}
control.InsertEndChild(binder);
}
if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)
!= /*NamedAxis::*/UNASSIGNED)
{
TiXmlElement binder( "JoystickSliderBinder" );
binder.SetAttribute( "slider", ToString<int>(
getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::INCREASE)).c_str() );
binder.SetAttribute( "direction", "INCREASE" );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
control.InsertEndChild(binder);
}
if(getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)
!= /*NamedAxis::*/UNASSIGNED)
{
TiXmlElement binder( "JoystickSliderBinder" );
binder.SetAttribute( "slider", ToString<int>(
getJoystickSliderBinding(*o, deviceId, Control/*::ControlChangingDirection*/::DECREASE)).c_str() );
binder.SetAttribute( "direction", "DECREASE" );
binder.SetAttribute( "deviceId", ToString<int>(deviceId).c_str() );
control.InsertEndChild(binder);
}
++it;
}
std::list<Channel*> channels = (*o)->getAttachedChannels(); std::list<Channel*> channels = (*o)->getAttachedChannels();
@ -697,19 +627,19 @@ namespace ICS
binder.SetAttribute( "number", ToString<int>((*it)->getNumber()).c_str() ); binder.SetAttribute( "number", ToString<int>((*it)->getNumber()).c_str() );
Channel::ChannelDirection direction = (*it)->getAttachedControlBinding(*o).direction; Channel::ChannelDirection direction = (*it)->getAttachedControlBinding(*o).direction;
if(direction == Channel/*::ChannelDirection*/::DIRECT) if(direction == Channel/*::ChannelDirection*/::DIRECT)
{ {
binder.SetAttribute( "direction", "DIRECT" ); binder.SetAttribute( "direction", "DIRECT" );
} }
else else
{ {
binder.SetAttribute( "direction", "INVERSE" ); binder.SetAttribute( "direction", "INVERSE" );
} }
float percentage = (*it)->getAttachedControlBinding(*o).percentage; float percentage = (*it)->getAttachedControlBinding(*o).percentage;
binder.SetAttribute( "percentage", ToString<float>(percentage).c_str() ); binder.SetAttribute( "percentage", ToString<float>(percentage).c_str() );
control.InsertEndChild(binder); control.InsertEndChild(binder);
} }
@ -731,7 +661,7 @@ namespace ICS
} }
} }
//! @todo Future versions should consider channel exponentials and mixtures, so //! @todo Future versions should consider channel exponentials and mixtures, so
// after updating Controls, Channels should be updated according to their values // after updating Controls, Channels should be updated according to their values
} }
@ -745,24 +675,6 @@ namespace ICS
return mControls[i]->getValue(); return mControls[i]->getValue();
} }
void InputControlSystem::addJoystick(int deviceId)
{
ICS_LOG("Adding joystick (device id: " + ToString<int>(deviceId) + ")");
for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++)
{
if(mControlsJoystickAxisBinderMap[deviceId].find(j) == mControlsJoystickAxisBinderMap[deviceId].end())
{
ControlAxisBinderItem controlJoystickBinderItem;
controlJoystickBinderItem.direction = Control::STOP;
controlJoystickBinderItem.control = NULL;
mControlsJoystickAxisBinderMap[deviceId][j] = controlJoystickBinderItem;
}
}
mJoystickIDList.push_back(deviceId);
}
Control* InputControlSystem::findControl(std::string name) Control* InputControlSystem::findControl(std::string name)
{ {
if(mActive) if(mActive)

@ -32,7 +32,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "ICSControl.h" #include "ICSControl.h"
#include "ICSChannel.h" #include "ICSChannel.h"
#include "../sdl4ogre/events.h" #include "../sdl4ogre/events.h"
#include "boost/lexical_cast.hpp"
#define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() ); #define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() );
#define ICS_MAX_JOYSTICK_AXIS 16 #define ICS_MAX_JOYSTICK_AXIS 16
@ -43,16 +45,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace ICS namespace ICS
{ {
class DllExport InputControlSystemLog class DllExport InputControlSystemLog
{ {
public: public:
virtual void logMessage(const char* text) = 0; virtual void logMessage(const char* text) = 0;
}; };
class DllExport InputControlSystem : class DllExport InputControlSystem :
public SFO::MouseListener, public SFO::MouseListener,
public SFO::KeyListener, public SFO::KeyListener,
public SFO::JoyListener public SFO::ControllerListener
{ {
public: public:
@ -62,7 +64,7 @@ namespace ICS
typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions typedef NamedAxis MouseAxis; // MouseAxis is deprecated. It will be removed in future versions
typedef std::list<int> JoystickIDList; typedef std::map<int, SDL_GameController*> JoystickIDList;
typedef struct typedef struct
{ {
@ -72,7 +74,7 @@ namespace ICS
InputControlSystem(std::string file = "", bool active = true InputControlSystem(std::string file = "", bool active = true
, DetectingBindingListener* detectingBindingListener = NULL , DetectingBindingListener* detectingBindingListener = NULL
, InputControlSystemLog* log = NULL, size_t channelCount = 16); , InputControlSystemLog* log = NULL, size_t channelCount = 16);
~InputControlSystem(); ~InputControlSystem();
std::string getFileName(){ return mFileName; }; std::string getFileName(){ return mFileName; };
@ -98,50 +100,42 @@ namespace ICS
inline void activate(){ this->mActive = true; }; inline void activate(){ this->mActive = true; };
inline void deactivate(){ this->mActive = false; }; inline void deactivate(){ this->mActive = false; };
void addJoystick(int deviceId); void controllerAdded (const SDL_ControllerDeviceEvent &args);
void controllerRemoved(const SDL_ControllerDeviceEvent &args);
JoystickIDList& getJoystickIdList(){ return mJoystickIDList; }; JoystickIDList& getJoystickIdList(){ return mJoystickIDList; };
// MouseListener // MouseListener
void mouseMoved(const SFO::MouseMotionEvent &evt); void mouseMoved(const SFO::MouseMotionEvent &evt);
void mousePressed(const SDL_MouseButtonEvent &evt, Uint8); void mousePressed(const SDL_MouseButtonEvent &evt, Uint8);
void mouseReleased(const SDL_MouseButtonEvent &evt, Uint8); void mouseReleased(const SDL_MouseButtonEvent &evt, Uint8);
// KeyListener // KeyListener
void keyPressed(const SDL_KeyboardEvent &evt); void keyPressed(const SDL_KeyboardEvent &evt);
void keyReleased(const SDL_KeyboardEvent &evt); void keyReleased(const SDL_KeyboardEvent &evt);
// JoyStickListener // ControllerListener
void buttonPressed(const SDL_JoyButtonEvent &evt, int button); void buttonPressed(const SDL_ControllerButtonEvent &evt);
void buttonReleased(const SDL_JoyButtonEvent &evt, int button); void buttonReleased(const SDL_ControllerButtonEvent &evt);
void axisMoved(const SDL_JoyAxisEvent &evt, int axis); void axisMoved(const SDL_ControllerAxisEvent &evt);
void povMoved(const SDL_JoyHatEvent &evt, int index);
//TODO: does this have an SDL equivalent?
//bool sliderMoved(const OIS::JoyStickEvent &evt, int index);
void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction); void addKeyBinding(Control* control, SDL_Scancode key, Control::ControlChangingDirection direction);
bool isKeyBound(SDL_Scancode key) const; bool isKeyBound(SDL_Scancode key) const;
void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction); void addMouseAxisBinding(Control* control, NamedAxis axis, Control::ControlChangingDirection direction);
void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction); void addMouseButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction);
bool isMouseButtonBound(unsigned int button) const; bool isMouseButtonBound(unsigned int button) const;
void addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction); void addJoystickAxisBinding(Control* control, int axis, Control::ControlChangingDirection direction);
void addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction); void addJoystickButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction);
void addJoystickPOVBinding(Control* control, int deviceId, int index, POVAxis axis, Control::ControlChangingDirection direction);
void addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction);
void removeKeyBinding(SDL_Scancode key); void removeKeyBinding(SDL_Scancode key);
void removeMouseAxisBinding(NamedAxis axis); void removeMouseAxisBinding(NamedAxis axis);
void removeMouseButtonBinding(unsigned int button); void removeMouseButtonBinding(unsigned int button);
void removeJoystickAxisBinding(int deviceId, int axis); void removeJoystickAxisBinding(int axis);
void removeJoystickButtonBinding(int deviceId, unsigned int button); void removeJoystickButtonBinding(unsigned int button);
void removeJoystickPOVBinding(int deviceId, int index, POVAxis axis);
void removeJoystickSliderBinding(int deviceId, int index);
SDL_Scancode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction); SDL_Scancode getKeyBinding(Control* control, ICS::Control::ControlChangingDirection direction);
NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction); NamedAxis getMouseAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction);
unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction); unsigned int getMouseButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction);
int getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); int getJoystickAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction);
unsigned int getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction); unsigned int getJoystickButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction);
POVBindingPair getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction);
int getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction);
std::string scancodeToString(SDL_Scancode key); std::string scancodeToString(SDL_Scancode key);
@ -193,17 +187,10 @@ namespace ICS
typedef std::map<int, ControlPOVBinderItem> ControlsPOVBinderMapType; // <index, [direction, control]> typedef std::map<int, ControlPOVBinderItem> ControlsPOVBinderMapType; // <index, [direction, control]>
typedef std::map<int, ControlSliderBinderItem> ControlsSliderBinderMapType; // <index, [direction, control]> typedef std::map<int, ControlSliderBinderItem> ControlsSliderBinderMapType; // <index, [direction, control]>
typedef std::map<int, ControlsAxisBinderMapType> JoystickAxisBinderMapType; // <joystick_id, <axis, [direction, control]> >
typedef std::map<int, ControlsButtonBinderMapType> JoystickButtonBinderMapType; // <joystick_id, <button, [direction, control]> >
typedef std::map<int, std::map<int, ControlsPOVBinderMapType> > JoystickPOVBinderMapType; // <joystick_id, <index, <axis, [direction, control]> > >
typedef std::map<int, ControlsSliderBinderMapType> JoystickSliderBinderMapType; // <joystick_id, <index, [direction, control]> >
ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // <axis, [direction, control]> ControlsAxisBinderMapType mControlsMouseAxisBinderMap; // <axis, [direction, control]>
ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // <int, [direction, control]> ControlsButtonBinderMapType mControlsMouseButtonBinderMap; // <int, [direction, control]>
JoystickAxisBinderMapType mControlsJoystickAxisBinderMap; // <joystick_id, <axis, [direction, control]> > ControlsAxisBinderMapType mControlsJoystickAxisBinderMap; // <axis, [direction, control]>
JoystickButtonBinderMapType mControlsJoystickButtonBinderMap; // <joystick_id, <button, [direction, control]> > ControlsButtonBinderMapType mControlsJoystickButtonBinderMap; // <button, [direction, control]>
JoystickPOVBinderMapType mControlsJoystickPOVBinderMap; // <joystick_id, <index, <axis, [direction, control]> > >
JoystickSliderBinderMapType mControlsJoystickSliderBinderMap; // <joystick_id, <index, [direction, control]> >
std::vector<Control *> mControls; std::vector<Control *> mControls;
std::vector<Channel *> mChannels; std::vector<Channel *> mChannels;
@ -212,7 +199,7 @@ namespace ICS
bool mActive; bool mActive;
InputControlSystemLog* mLog; InputControlSystemLog* mLog;
DetectingBindingListener* mDetectingBindingListener; DetectingBindingListener* mDetectingBindingListener;
Control* mDetectingBindingControl; Control* mDetectingBindingControl;
Control::ControlChangingDirection mDetectingBindingDirection; Control::ControlChangingDirection mDetectingBindingDirection;
@ -243,16 +230,11 @@ namespace ICS
, unsigned int button, Control::ControlChangingDirection direction); , unsigned int button, Control::ControlChangingDirection direction);
virtual void joystickAxisBindingDetected(InputControlSystem* ICS, Control* control virtual void joystickAxisBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, int axis, Control::ControlChangingDirection direction); , int axis, Control::ControlChangingDirection direction);
virtual void joystickButtonBindingDetected(InputControlSystem* ICS, Control* control virtual void joystickButtonBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, unsigned int button, Control::ControlChangingDirection direction); , unsigned int button, Control::ControlChangingDirection direction);
virtual void joystickPOVBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction);
virtual void joystickSliderBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, int slider, Control::ControlChangingDirection direction);
}; };
static const float ICS_MAX = std::numeric_limits<float>::max(); static const float ICS_MAX = std::numeric_limits<float>::max();

@ -27,14 +27,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "ICSInputControlSystem.h" #include "ICSInputControlSystem.h"
#define SDL_JOY_AXIS_MIN -32768 #define SDL_JOY_AXIS_MIN -32768
#define SDL_JOY_AXIS_MAX 32767 #define SDL_JOY_AXIS_MAX 32767
#define DEADZONE 0.1f
namespace ICS namespace ICS
{ {
// load xml // load xml
void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode) void InputControlSystem::loadJoystickAxisBinders(TiXmlElement* xmlControlNode)
{ {
TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder"); TiXmlElement* xmlJoystickBinder = xmlControlNode->FirstChildElement("JoystickAxisBinder");
while(xmlJoystickBinder) while(xmlJoystickBinder)
{ {
Control::ControlChangingDirection dir = Control::STOP; Control::ControlChangingDirection dir = Control::STOP;
@ -47,8 +48,7 @@ namespace ICS
dir = Control::DECREASE; dir = Control::DECREASE;
} }
addJoystickAxisBinding(mControls.back(), FromString<int>(xmlJoystickBinder->Attribute("deviceId")) addJoystickAxisBinding(mControls.back(), FromString<int>(xmlJoystickBinder->Attribute("axis")), dir);
, FromString<int>(xmlJoystickBinder->Attribute("axis")), dir);
xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder"); xmlJoystickBinder = xmlJoystickBinder->NextSiblingElement("JoystickAxisBinder");
} }
@ -56,7 +56,7 @@ namespace ICS
void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode) void InputControlSystem::loadJoystickButtonBinders(TiXmlElement* xmlControlNode)
{ {
TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder"); TiXmlElement* xmlJoystickButtonBinder = xmlControlNode->FirstChildElement("JoystickButtonBinder");
while(xmlJoystickButtonBinder) while(xmlJoystickButtonBinder)
{ {
Control::ControlChangingDirection dir = Control::STOP; Control::ControlChangingDirection dir = Control::STOP;
@ -69,335 +69,168 @@ namespace ICS
dir = Control::DECREASE; dir = Control::DECREASE;
} }
addJoystickButtonBinding(mControls.back(), FromString<int>(xmlJoystickButtonBinder->Attribute("deviceId")) addJoystickButtonBinding(mControls.back(), FromString<int>(xmlJoystickButtonBinder->Attribute("button")), dir);
, FromString<int>(xmlJoystickButtonBinder->Attribute("button")), dir);
xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder"); xmlJoystickButtonBinder = xmlJoystickButtonBinder->NextSiblingElement("JoystickButtonBinder");
} }
} }
void InputControlSystem::loadJoystickPOVBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlJoystickPOVBinder = xmlControlNode->FirstChildElement("JoystickPOVBinder");
while(xmlJoystickPOVBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlJoystickPOVBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
InputControlSystem::POVAxis axis = /*POVAxis::*/NorthSouth;
if(std::string(xmlJoystickPOVBinder->Attribute("axis")) == "EastWest")
{
axis = /*POVAxis::*/EastWest;
}
addJoystickPOVBinding(mControls.back(), FromString<int>(xmlJoystickPOVBinder->Attribute("deviceId"))
, FromString<int>(xmlJoystickPOVBinder->Attribute("pov")), axis, dir);
xmlJoystickPOVBinder = xmlJoystickPOVBinder->NextSiblingElement("JoystickPOVBinder");
}
}
void InputControlSystem::loadJoystickSliderBinders(TiXmlElement* xmlControlNode)
{
TiXmlElement* xmlJoystickSliderBinder = xmlControlNode->FirstChildElement("JoystickSliderBinder");
while(xmlJoystickSliderBinder)
{
Control::ControlChangingDirection dir = Control::STOP;
if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "INCREASE")
{
dir = Control::INCREASE;
}
else if(std::string(xmlJoystickSliderBinder->Attribute("direction")) == "DECREASE")
{
dir = Control::DECREASE;
}
addJoystickSliderBinding(mControls.back(), FromString<int>(xmlJoystickSliderBinder->Attribute("deviceId"))
, FromString<int>(xmlJoystickSliderBinder->Attribute("slider")), dir);
xmlJoystickSliderBinder = xmlJoystickSliderBinder->NextSiblingElement("JoystickSliderBinder");
}
}
// add bindings // add bindings
void InputControlSystem::addJoystickAxisBinding(Control* control, int deviceId, int axis, Control::ControlChangingDirection direction) void InputControlSystem::addJoystickAxisBinding(Control* control, int axis, Control::ControlChangingDirection direction)
{ {
ICS_LOG("\tAdding AxisBinder [deviceid=" ICS_LOG("\tAdding AxisBinder [axis="
+ ToString<int>(deviceId) + ", axis="
+ ToString<int>(axis) + ", direction=" + ToString<int>(axis) + ", direction="
+ ToString<int>(direction) + "]"); + ToString<int>(direction) + "]");
control->setValue(0.5f); //all joystick axis start at .5, so do that
ControlAxisBinderItem controlAxisBinderItem; ControlAxisBinderItem controlAxisBinderItem;
controlAxisBinderItem.control = control; controlAxisBinderItem.control = control;
controlAxisBinderItem.direction = direction; controlAxisBinderItem.direction = direction;
mControlsJoystickAxisBinderMap[ deviceId ][ axis ] = controlAxisBinderItem; mControlsJoystickAxisBinderMap[ axis ] = controlAxisBinderItem;
} }
void InputControlSystem::addJoystickButtonBinding(Control* control, int deviceId, unsigned int button, Control::ControlChangingDirection direction) void InputControlSystem::addJoystickButtonBinding(Control* control, unsigned int button, Control::ControlChangingDirection direction)
{ {
ICS_LOG("\tAdding JoystickButtonBinder [deviceId=" ICS_LOG("\tAdding JoystickButtonBinder [button="
+ ToString<int>(deviceId) + ", button="
+ ToString<int>(button) + ", direction=" + ToString<int>(button) + ", direction="
+ ToString<int>(direction) + "]"); + ToString<int>(direction) + "]");
ControlButtonBinderItem controlJoystickButtonBinderItem; ControlButtonBinderItem controlJoystickButtonBinderItem;
controlJoystickButtonBinderItem.direction = direction; controlJoystickButtonBinderItem.direction = direction;
controlJoystickButtonBinderItem.control = control; controlJoystickButtonBinderItem.control = control;
mControlsJoystickButtonBinderMap[ deviceId ][ button ] = controlJoystickButtonBinderItem; mControlsJoystickButtonBinderMap[ button ] = controlJoystickButtonBinderItem;
}
void InputControlSystem::addJoystickPOVBinding(Control* control, int deviceId, int index, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction)
{
ICS_LOG("\tAdding JoystickPOVBinder [deviceId="
+ ToString<int>(deviceId) + ", pov="
+ ToString<int>(index) + ", axis="
+ ToString<int>(axis) + ", direction="
+ ToString<int>(direction) + "]");
ControlPOVBinderItem ControlPOVBinderItem;
ControlPOVBinderItem.direction = direction;
ControlPOVBinderItem.control = control;
mControlsJoystickPOVBinderMap[ deviceId ][ index ][ axis ] = ControlPOVBinderItem;
}
void InputControlSystem::addJoystickSliderBinding(Control* control, int deviceId, int index, Control::ControlChangingDirection direction)
{
ICS_LOG("\tAdding JoystickSliderBinder [deviceId="
+ ToString<int>(deviceId) + ", direction="
+ ToString<int>(index) + ", direction="
+ ToString<int>(direction) + "]");
ControlSliderBinderItem ControlSliderBinderItem;
ControlSliderBinderItem.direction = direction;
ControlSliderBinderItem.control = control;
mControlsJoystickSliderBinderMap[ deviceId ][ index ] = ControlSliderBinderItem;
} }
// get bindings // get bindings
int InputControlSystem::getJoystickAxisBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) int InputControlSystem::getJoystickAxisBinding(Control* control, ICS::Control::ControlChangingDirection direction)
{ {
if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end()) ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap.begin();
{ while(it != mControlsJoystickAxisBinderMap.end())
ControlsAxisBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].begin(); {
while(it != mControlsJoystickAxisBinderMap[deviceId].end()) if(it->first >= 0 && it->second.control == control && it->second.direction == direction)
{ {
if(it->first >= 0 && it->second.control == control && it->second.direction == direction) return it->first;
{ }
return it->first; ++it;
} }
++it;
}
}
return /*NamedAxis::*/UNASSIGNED; return /*NamedAxis::*/UNASSIGNED;
} }
unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction) unsigned int InputControlSystem::getJoystickButtonBinding(Control* control, ICS::Control::ControlChangingDirection direction)
{ {
if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end()) ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap.begin();
{ while(it != mControlsJoystickButtonBinderMap.end())
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].begin(); {
while(it != mControlsJoystickButtonBinderMap[deviceId].end()) if(it->second.control == control && it->second.direction == direction)
{ {
if(it->second.control == control && it->second.direction == direction) return it->first;
{ }
return it->first; ++it;
} }
++it;
}
}
return ICS_MAX_DEVICE_BUTTONS; return ICS_MAX_DEVICE_BUTTONS;
} }
InputControlSystem::POVBindingPair InputControlSystem::getJoystickPOVBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction)
{
POVBindingPair result;
result.index = -1;
if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end())
{
//ControlsAxisBinderMapType::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin();
std::map<int, ControlsPOVBinderMapType>::iterator it = mControlsJoystickPOVBinderMap[deviceId].begin();
while(it != mControlsJoystickPOVBinderMap[deviceId].end())
{
ControlsPOVBinderMapType::const_iterator it2 = it->second.begin();
while(it2 != it->second.end())
{
if(it2->second.control == control && it2->second.direction == direction)
{
result.index = it->first;
result.axis = (POVAxis)it2->first;
return result;
}
it2++;
}
it++;
}
}
return result;
}
int InputControlSystem::getJoystickSliderBinding(Control* control, int deviceId, ICS::Control::ControlChangingDirection direction)
{
if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end())
{
ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].begin();
while(it != mControlsJoystickSliderBinderMap[deviceId].end())
{
if(it->second.control == control && it->second.direction == direction)
{
return it->first;
}
it++;
}
}
return /*NamedAxis::*/UNASSIGNED;
}
// remove bindings // remove bindings
void InputControlSystem::removeJoystickAxisBinding(int deviceId, int axis) void InputControlSystem::removeJoystickAxisBinding(int axis)
{ {
if(mControlsJoystickAxisBinderMap.find(deviceId) != mControlsJoystickAxisBinderMap.end()) ControlsButtonBinderMapType::iterator it = mControlsJoystickAxisBinderMap.find(axis);
{ if(it != mControlsJoystickAxisBinderMap.end())
ControlsButtonBinderMapType::iterator it = mControlsJoystickAxisBinderMap[deviceId].find(axis); {
if(it != mControlsJoystickAxisBinderMap[deviceId].end()) mControlsJoystickAxisBinderMap.erase(it);
{ }
mControlsJoystickAxisBinderMap[deviceId].erase(it);
}
}
} }
void InputControlSystem::removeJoystickButtonBinding(int deviceId, unsigned int button) void InputControlSystem::removeJoystickButtonBinding(unsigned int button)
{ {
if(mControlsJoystickButtonBinderMap.find(deviceId) != mControlsJoystickButtonBinderMap.end()) ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap.find(button);
{ if(it != mControlsJoystickButtonBinderMap.end())
ControlsButtonBinderMapType::iterator it = mControlsJoystickButtonBinderMap[deviceId].find(button); {
if(it != mControlsJoystickButtonBinderMap[deviceId].end()) mControlsJoystickButtonBinderMap.erase(it);
{ }
mControlsJoystickButtonBinderMap[deviceId].erase(it);
}
}
}
void InputControlSystem::removeJoystickPOVBinding(int deviceId, int index, POVAxis axis)
{
if(mControlsJoystickPOVBinderMap.find(deviceId) != mControlsJoystickPOVBinderMap.end())
{
std::map<int, ControlsPOVBinderMapType>::iterator it = mControlsJoystickPOVBinderMap[deviceId].find(index);
if(it != mControlsJoystickPOVBinderMap[deviceId].end())
{
if(it->second.find(axis) != it->second.end())
{
mControlsJoystickPOVBinderMap[deviceId].find(index)->second.erase( it->second.find(axis) );
}
}
}
}
void InputControlSystem::removeJoystickSliderBinding(int deviceId, int index)
{
if(mControlsJoystickSliderBinderMap.find(deviceId) != mControlsJoystickSliderBinderMap.end())
{
ControlsButtonBinderMapType::iterator it = mControlsJoystickSliderBinderMap[deviceId].find(index);
if(it != mControlsJoystickSliderBinderMap[deviceId].end())
{
mControlsJoystickSliderBinderMap[deviceId].erase(it);
}
}
} }
// joyStick listeners // joyStick listeners
void InputControlSystem::buttonPressed(const SDL_JoyButtonEvent &evt, int button) void InputControlSystem::buttonPressed(const SDL_ControllerButtonEvent &evt)
{ {
if(mActive) if(mActive)
{ {
if(!mDetectingBindingControl) if(!mDetectingBindingControl)
{ {
if(mControlsJoystickButtonBinderMap.find(evt.which) != mControlsJoystickButtonBinderMap.end()) ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap.find(evt.button);
{ if(it != mControlsJoystickButtonBinderMap.end())
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.which].find(button); {
if(it != mControlsJoystickButtonBinderMap[evt.which].end()) it->second.control->setIgnoreAutoReverse(false);
{ if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
it->second.control->setIgnoreAutoReverse(false); {
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) it->second.control->setChangingDirection(it->second.direction);
{ }
it->second.control->setChangingDirection(it->second.direction); else
} {
else if(it->second.control->getValue() == 1)
{ {
if(it->second.control->getValue() == 1) it->second.control->setChangingDirection(Control::DECREASE);
{ }
it->second.control->setChangingDirection(Control::DECREASE); else if(it->second.control->getValue() == 0)
} {
else if(it->second.control->getValue() == 0) it->second.control->setChangingDirection(Control::INCREASE);
{ }
it->second.control->setChangingDirection(Control::INCREASE); }
} }
}
}
}
} }
else if(mDetectingBindingListener) else if(mDetectingBindingListener)
{ {
mDetectingBindingListener->joystickButtonBindingDetected(this, mDetectingBindingListener->joystickButtonBindingDetected(this,
mDetectingBindingControl, evt.which, button, mDetectingBindingDirection); mDetectingBindingControl, evt.button, mDetectingBindingDirection);
} }
} }
} }
void InputControlSystem::buttonReleased(const SDL_JoyButtonEvent &evt, int button) void InputControlSystem::buttonReleased(const SDL_ControllerButtonEvent &evt)
{ {
if(mActive) if(mActive)
{ {
if(mControlsJoystickButtonBinderMap.find(evt.which) != mControlsJoystickButtonBinderMap.end()) ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap.find(evt.button);
{ if(it != mControlsJoystickButtonBinderMap.end())
ControlsButtonBinderMapType::const_iterator it = mControlsJoystickButtonBinderMap[evt.which].find(button); {
if(it != mControlsJoystickButtonBinderMap[evt.which].end()) it->second.control->setChangingDirection(Control::STOP);
{ }
it->second.control->setChangingDirection(Control::STOP);
}
}
} }
} }
void InputControlSystem::axisMoved(const SDL_JoyAxisEvent &evt, int axis) void InputControlSystem::axisMoved(const SDL_ControllerAxisEvent &evt)
{ {
if(mActive) if(mActive)
{ {
if(!mDetectingBindingControl) if(!mDetectingBindingControl)
{ {
if(mControlsJoystickAxisBinderMap.find(evt.which) != mControlsJoystickAxisBinderMap.end()) ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[evt.axis]; // joystic axis start at 0 index
{ Control* ctrl = joystickBinderItem.control;
ControlAxisBinderItem joystickBinderItem = mControlsJoystickAxisBinderMap[ evt.which ][ axis ]; // joystic axis start at 0 index if(ctrl)
Control* ctrl = joystickBinderItem.control; {
if(ctrl) ctrl->setIgnoreAutoReverse(true);
{
ctrl->setIgnoreAutoReverse(true); float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN;
float valDisplaced = (float)(evt.value - SDL_JOY_AXIS_MIN);
float axisRange = SDL_JOY_AXIS_MAX - SDL_JOY_AXIS_MIN; float percent = valDisplaced / axisRange * (1+DEADZONE*2) - DEADZONE; //Assures all values, 0 through 1, are seen
float valDisplaced = (float)(evt.value - SDL_JOY_AXIS_MIN); if(percent > .5-DEADZONE && percent < .5+DEADZONE) //close enough to center
percent = .5;
if(joystickBinderItem.direction == Control::INCREASE) else if(percent > .5)
{ percent -= DEADZONE;
ctrl->setValue( valDisplaced / axisRange ); else
} percent += DEADZONE;
else if(joystickBinderItem.direction == Control::DECREASE)
{ if(joystickBinderItem.direction == Control::INCREASE)
ctrl->setValue( 1 - ( valDisplaced / axisRange ) ); {
} ctrl->setValue( percent );
} }
} else if(joystickBinderItem.direction == Control::DECREASE)
{
ctrl->setValue( 1 - ( percent ) );
}
}
} }
else if(mDetectingBindingListener) else if(mDetectingBindingListener)
{ {
@ -409,249 +242,74 @@ namespace ICS
if( abs( evt.value ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN) if( abs( evt.value ) > ICS_JOYSTICK_AXIS_BINDING_MARGIN)
{ {
mDetectingBindingListener->joystickAxisBindingDetected(this, mDetectingBindingListener->joystickAxisBindingDetected(this,
mDetectingBindingControl, evt.which, axis, mDetectingBindingDirection); mDetectingBindingControl, evt.axis, mDetectingBindingDirection);
} }
} }
} }
} }
} }
//Here be dragons, apparently void InputControlSystem::controllerAdded(const SDL_ControllerDeviceEvent &args)
void InputControlSystem::povMoved(const SDL_JoyHatEvent &evt, int index)
{ {
if(mActive) ICS_LOG("Adding joystick (index: " + ToString<int>(args.which) + ")");
{ SDL_GameController* cntrl = SDL_GameControllerOpen(args.which);
if(!mDetectingBindingControl) int instanceID = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(cntrl));
{ if(mJoystickIDList.empty()) //
if(mControlsJoystickPOVBinderMap.find(evt.which) != mControlsJoystickPOVBinderMap.end()) {
{ for(int j = 0 ; j < ICS_MAX_JOYSTICK_AXIS ; j++)
std::map<int, ControlsPOVBinderMapType>::const_iterator i = mControlsJoystickPOVBinderMap[ evt.which ].find(index); {
if(i != mControlsJoystickPOVBinderMap[ evt.which ].end()) if(mControlsJoystickAxisBinderMap.find(j) == mControlsJoystickAxisBinderMap.end())
{ {
if(evt.value != SDL_HAT_LEFT ControlAxisBinderItem controlJoystickBinderItem;
&& evt.value != SDL_HAT_RIGHT controlJoystickBinderItem.direction = Control::STOP;
&& evt.value != SDL_HAT_CENTERED) controlJoystickBinderItem.control = NULL;
{ mControlsJoystickAxisBinderMap[j] = controlJoystickBinderItem;
ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth ); }
if(it != i->second.end()) }
{ }
it->second.control->setIgnoreAutoReverse(false);
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop()) mJoystickIDList[instanceID] = cntrl;
{ }
if(evt.value == SDL_HAT_UP void InputControlSystem::controllerRemoved(const SDL_ControllerDeviceEvent &args)
|| evt.value == SDL_HAT_LEFTUP {
|| evt.value == SDL_HAT_RIGHTUP) ICS_LOG("Removing joystick (instance id: " + ToString<int>(args.which) + ")");
{ if(mJoystickIDList.count(args.which)!=0)
it->second.control->setChangingDirection(it->second.direction); {
} SDL_GameControllerClose(mJoystickIDList.at(args.which));
else mJoystickIDList.erase(args.which);
{ }
it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction));
}
}
else
{
if(it->second.control->getValue() == 1)
{
it->second.control->setChangingDirection(Control::DECREASE);
}
else if(it->second.control->getValue() == 0)
{
it->second.control->setChangingDirection(Control::INCREASE);
}
}
}
}
if(evt.value != SDL_HAT_UP
&& evt.value != SDL_HAT_DOWN
&& evt.value != SDL_HAT_CENTERED)
{
ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/EastWest );
if(it != i->second.end())
{
it->second.control->setIgnoreAutoReverse(false);
if(!it->second.control->getAutoChangeDirectionOnLimitsAfterStop())
{
if(evt.value == SDL_HAT_RIGHT
|| evt.value == SDL_HAT_RIGHTUP
|| evt.value == SDL_HAT_RIGHTDOWN)
{
it->second.control->setChangingDirection(it->second.direction);
}
else
{
it->second.control->setChangingDirection((Control::ControlChangingDirection)(-1 * it->second.direction));
}
}
else
{
if(it->second.control->getValue() == 1)
{
it->second.control->setChangingDirection(Control::DECREASE);
}
else if(it->second.control->getValue() == 0)
{
it->second.control->setChangingDirection(Control::INCREASE);
}
}
}
}
if(evt.value == SDL_HAT_CENTERED)
{
ControlsPOVBinderMapType::const_iterator it = i->second.find( /*POVAxis::*/NorthSouth );
if(it != i->second.end())
{
it->second.control->setChangingDirection(Control::STOP);
}
it = i->second.find( /*POVAxis::*/EastWest );
if(it != i->second.end())
{
it->second.control->setChangingDirection(Control::STOP);
}
}
}
}
}
else if(mDetectingBindingListener)
{
if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable())
{
if(evt.value == SDL_HAT_LEFT
|| evt.value == SDL_HAT_RIGHT
|| evt.value == SDL_HAT_UP
|| evt.value == SDL_HAT_DOWN)
{
POVAxis povAxis = NorthSouth;
if(evt.value == SDL_HAT_LEFT
|| evt.value == SDL_HAT_RIGHT)
{
povAxis = EastWest;
}
mDetectingBindingListener->joystickPOVBindingDetected(this,
mDetectingBindingControl, evt.which, index, povAxis, mDetectingBindingDirection);
}
}
}
}
} }
//TODO: does this have an SDL equivalent?
/*
void InputControlSystem::sliderMoved(const OIS::JoyStickEvent &evt, int index)
{
if(mActive)
{
if(!mDetectingBindingControl)
{
if(mControlsJoystickSliderBinderMap.find(evt.device->getID()) != mControlsJoystickSliderBinderMap.end())
{
ControlSliderBinderItem joystickBinderItem = mControlsJoystickSliderBinderMap[ evt.device->getID() ][ index ];
Control* ctrl = joystickBinderItem.control;
if(ctrl)
{
ctrl->setIgnoreAutoReverse(true);
if(joystickBinderItem.direction == Control::INCREASE)
{
float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS;
float valDisplaced = (float)( evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS);
ctrl->setValue( valDisplaced / axisRange );
}
else if(joystickBinderItem.direction == Control::DECREASE)
{
float axisRange = OIS::JoyStick::MAX_AXIS - OIS::JoyStick::MIN_AXIS;
float valDisplaced = (float)(evt.state.mSliders[index].abX - OIS::JoyStick::MIN_AXIS);
ctrl->setValue( 1 - ( valDisplaced / axisRange ) );
}
}
}
}
else if(mDetectingBindingListener)
{
if(mDetectingBindingControl && mDetectingBindingControl->isAxisBindable())
{
if( abs( evt.state.mSliders[index].abX ) > ICS_JOYSTICK_SLIDER_BINDING_MARGIN)
{
mDetectingBindingListener->joystickSliderBindingDetected(this,
mDetectingBindingControl, evt.device->getID(), index, mDetectingBindingDirection);
}
}
}
}
}
*/
// joystick auto bindings // joystick auto bindings
void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, Control* control void DetectingBindingListener::joystickAxisBindingDetected(InputControlSystem* ICS, Control* control, int axis, Control::ControlChangingDirection direction)
, int deviceId, int axis, Control::ControlChangingDirection direction)
{ {
// if the joystick axis is used by another control, remove it // if the joystick axis is used by another control, remove it
ICS->removeJoystickAxisBinding(deviceId, axis); ICS->removeJoystickAxisBinding(axis);
// if the control has an axis assigned, remove it // if the control has an axis assigned, remove it
int oldAxis = ICS->getJoystickAxisBinding(control, deviceId, direction); int oldAxis = ICS->getJoystickAxisBinding(control, direction);
if(oldAxis != InputControlSystem::UNASSIGNED) if(oldAxis != InputControlSystem::UNASSIGNED)
{ {
ICS->removeJoystickAxisBinding(deviceId, oldAxis); ICS->removeJoystickAxisBinding(oldAxis);
} }
ICS->addJoystickAxisBinding(control, deviceId, axis, direction); ICS->addJoystickAxisBinding(control, axis, direction);
ICS->cancelDetectingBindingState(); ICS->cancelDetectingBindingState();
} }
void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, Control* control void DetectingBindingListener::joystickButtonBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, unsigned int button, Control::ControlChangingDirection direction) , unsigned int button, Control::ControlChangingDirection direction)
{ {
// if the joystick button is used by another control, remove it // if the joystick button is used by another control, remove it
ICS->removeJoystickButtonBinding(deviceId, button); ICS->removeJoystickButtonBinding(button);
// if the control has a joystick button assigned, remove it // if the control has a joystick button assigned, remove it
unsigned int oldButton = ICS->getJoystickButtonBinding(control, deviceId, direction); unsigned int oldButton = ICS->getJoystickButtonBinding(control, direction);
if(oldButton != ICS_MAX_DEVICE_BUTTONS) if(oldButton != ICS_MAX_DEVICE_BUTTONS)
{ {
ICS->removeJoystickButtonBinding(deviceId, oldButton); ICS->removeJoystickButtonBinding(oldButton);
}
ICS->addJoystickButtonBinding(control, deviceId, button, direction);
ICS->cancelDetectingBindingState();
}
void DetectingBindingListener::joystickPOVBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, int pov, InputControlSystem::POVAxis axis, Control::ControlChangingDirection direction)
{
// if the joystick slider is used by another control, remove it
ICS->removeJoystickPOVBinding(deviceId, pov, axis);
// if the control has a joystick button assigned, remove it
ICS::InputControlSystem::POVBindingPair oldPOV = ICS->getJoystickPOVBinding(control, deviceId, direction);
if(oldPOV.index >= 0 && oldPOV.axis == axis)
{
ICS->removeJoystickPOVBinding(deviceId, oldPOV.index, oldPOV.axis);
}
ICS->addJoystickPOVBinding(control, deviceId, pov, axis, direction);
ICS->cancelDetectingBindingState();
}
void DetectingBindingListener::joystickSliderBindingDetected(InputControlSystem* ICS, Control* control
, int deviceId, int slider, Control::ControlChangingDirection direction)
{
// if the joystick slider is used by another control, remove it
ICS->removeJoystickSliderBinding(deviceId, slider);
// if the control has a joystick slider assigned, remove it
int oldSlider = ICS->getJoystickSliderBinding(control, deviceId, direction);
if(oldSlider != InputControlSystem::/*NamedAxis::*/UNASSIGNED)
{
ICS->removeJoystickSliderBinding(deviceId, oldSlider);
} }
ICS->addJoystickSliderBinding(control, deviceId, slider, direction); ICS->addJoystickButtonBinding(control, button, direction);
ICS->cancelDetectingBindingState(); ICS->cancelDetectingBindingState();
} }
} }

@ -40,23 +40,25 @@ public:
virtual void keyReleased(const SDL_KeyboardEvent &arg) = 0; virtual void keyReleased(const SDL_KeyboardEvent &arg) = 0;
}; };
class JoyListener class ControllerListener
{ {
public: public:
virtual ~JoyListener() {} virtual ~ControllerListener() {}
/** @remarks Joystick button down event */ /** @remarks Joystick button down event */
virtual void buttonPressed( const SDL_JoyButtonEvent &evt, int button ) = 0; virtual void buttonPressed( const SDL_ControllerButtonEvent &evt) = 0;
/** @remarks Joystick button up event */ /** @remarks Joystick button up event */
virtual void buttonReleased( const SDL_JoyButtonEvent &evt, int button ) = 0; virtual void buttonReleased( const SDL_ControllerButtonEvent &evt) = 0;
/** @remarks Joystick axis moved event */ /** @remarks Joystick axis moved event */
virtual void axisMoved( const SDL_JoyAxisEvent &arg, int axis ) = 0; virtual void axisMoved( const SDL_ControllerAxisEvent &arg) = 0;
//-- Not so common control events, so are not required --// /** @remarks Joystick Added **/
virtual void controllerAdded( const SDL_ControllerDeviceEvent &arg) = 0;
/** @remarks Joystick Removed **/
virtual void controllerRemoved( const SDL_ControllerDeviceEvent &arg) = 0;
//! Joystick Event, and povID
virtual void povMoved( const SDL_JoyHatEvent &arg, int index) {}
}; };
class WindowListener class WindowListener

@ -20,7 +20,7 @@ namespace SFO
mMouseY(0), mMouseY(0),
mMouseX(0), mMouseX(0),
mMouseInWindow(true), mMouseInWindow(true),
mJoyListener(NULL), mConListener(NULL),
mKeyboardListener(NULL), mKeyboardListener(NULL),
mMouseListener(NULL), mMouseListener(NULL),
mWindowListener(NULL), mWindowListener(NULL),
@ -88,24 +88,32 @@ namespace SFO
case SDL_TEXTINPUT: case SDL_TEXTINPUT:
mKeyboardListener->textInput(evt.text); mKeyboardListener->textInput(evt.text);
break; break;
case SDL_JOYHATMOTION: //As we manage everything with GameController, don't even bother with these.
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
if (mJoyListener)
mJoyListener->axisMoved(evt.jaxis, evt.jaxis.axis);
break;
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
if (mJoyListener)
mJoyListener->buttonPressed(evt.jbutton, evt.jbutton.button);
break;
case SDL_JOYBUTTONUP: case SDL_JOYBUTTONUP:
if (mJoyListener)
mJoyListener->buttonReleased(evt.jbutton, evt.jbutton.button);
break;
case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEADDED:
//SDL_JoystickOpen(evt.jdevice.which);
//std::cout << "Detected a new joystick: " << SDL_JoystickNameForIndex(evt.jdevice.which) << std::endl;
break;
case SDL_JOYDEVICEREMOVED: case SDL_JOYDEVICEREMOVED:
//std::cout << "A joystick has been removed" << std::endl; break;
case SDL_CONTROLLERDEVICEADDED:
if(mConListener)
mConListener->controllerAdded(evt.cdevice);
break;
case SDL_CONTROLLERDEVICEREMOVED:
if(mConListener)
mConListener->controllerRemoved(evt.cdevice);
break;
case SDL_CONTROLLERBUTTONDOWN:
if(mConListener)
mConListener->buttonPressed(evt.cbutton);
break;
case SDL_CONTROLLERBUTTONUP:
if(mConListener)
mConListener->buttonReleased(evt.cbutton);
break;
case SDL_CONTROLLERAXISMOTION:
if(mConListener)
mConListener->axisMoved(evt.caxis);
break; break;
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
handleWindowEvent(evt); handleWindowEvent(evt);

@ -24,7 +24,7 @@ namespace SFO
void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; } void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; }
void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; } void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; }
void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; } void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; }
void setJoyEventCallback(JoyListener* listen) { mJoyListener = listen; } void setControllerEventCallback(ControllerListener* listen) { mConListener = listen; }
void capture(bool windowEventsOnly); void capture(bool windowEventsOnly);
bool isModifierHeld(SDL_Keymod mod); bool isModifierHeld(SDL_Keymod mod);
@ -54,7 +54,7 @@ namespace SFO
SFO::MouseListener* mMouseListener; SFO::MouseListener* mMouseListener;
SFO::KeyListener* mKeyboardListener; SFO::KeyListener* mKeyboardListener;
SFO::WindowListener* mWindowListener; SFO::WindowListener* mWindowListener;
SFO::JoyListener* mJoyListener; SFO::ControllerListener* mConListener;
typedef boost::unordered_map<SDL_Keycode, OIS::KeyCode> KeyMap; typedef boost::unordered_map<SDL_Keycode, OIS::KeyCode> KeyMap;
KeyMap mKeyMap; KeyMap mKeyMap;

@ -52,3 +52,5 @@ set(MATERIAL_FILES
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}") copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}")
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/materials "${OpenMW_BINARY_DIR}/resources/materials/" "${MATERIAL_FILES}") copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/materials "${OpenMW_BINARY_DIR}/resources/materials/" "${MATERIAL_FILES}")
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/gamecontrollerdb.txt ${OpenMW_BINARY_DIR}/resources/)

@ -0,0 +1,75 @@
# Windows - DINPUT
8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
xinput,X360 Controller,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,platform:Windows,
6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,
4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,
00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,
ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,
# OS X
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,Platform:Mac OS X,
5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,
4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,
# Linux
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Linux,
03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,
03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,
030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,
030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,
030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,
030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,
0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,
030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,
030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
050000004c050000c405000000010000,PS4 Controller (Bluetooth),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,
03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,
05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
Loading…
Cancel
Save