Added support for SDL_GameController with fallback to default method.
This commit is contained in:
parent
02f19c03c9
commit
160bfc0702
9 changed files with 188 additions and 14 deletions
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <SDL_events.h>
|
||||
#include <SDL_joystick.h>
|
||||
#include <SDL_gamecontroller.h>
|
||||
#include <SDL_messagebox.h>
|
||||
#include <SDL_timer.h>
|
||||
#include <SDL_thread.h>
|
||||
|
@ -99,7 +100,9 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
bool terminate = false;
|
||||
|
||||
SDL_Joystick *js = 0;
|
||||
if (SDL_NumJoysticks() > 0)
|
||||
if (rtData.gamecontroller != NULL)
|
||||
js = SDL_GameControllerGetJoystick(rtData.gamecontroller);
|
||||
else if (SDL_NumJoysticks() > 0)
|
||||
js = SDL_JoystickOpen(0);
|
||||
|
||||
char buffer[128];
|
||||
|
@ -286,7 +289,19 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
if (event.jdevice.which > 0)
|
||||
break;
|
||||
|
||||
js = SDL_JoystickOpen(0);
|
||||
if (SDL_IsGameController(0))
|
||||
rtData.gamecontroller = SDL_GameControllerOpen(0);
|
||||
if (rtData.gamecontroller != NULL)
|
||||
{
|
||||
js = SDL_GameControllerGetJoystick(rtData.gamecontroller);
|
||||
/* generate new default bindings if a new controller is connected and
|
||||
* the user hasn't set a custom set of keybinds yet */
|
||||
rtData.bindingUpdateMsg.post(loadBindings(rtData.config, rtData.gamecontroller));
|
||||
}
|
||||
else
|
||||
{
|
||||
js = SDL_JoystickOpen(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_JOYDEVICEREMOVED :
|
||||
|
@ -358,7 +373,9 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
break;
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetAttached(js))
|
||||
if (rtData.gamecontroller != NULL && SDL_GameControllerGetAttached(rtData.gamecontroller))
|
||||
SDL_GameControllerClose(rtData.gamecontroller);
|
||||
else if (SDL_JoystickGetAttached(js))
|
||||
SDL_JoystickClose(js);
|
||||
|
||||
delete sMenu;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <SDL_scancode.h>
|
||||
#include <SDL_joystick.h>
|
||||
#include <SDL_gamecontroller.h>
|
||||
#include <SDL_mouse.h>
|
||||
#include <SDL_mutex.h>
|
||||
|
||||
|
@ -231,6 +232,8 @@ struct RGSSThreadData
|
|||
|
||||
Config config;
|
||||
|
||||
SDL_GameController *gamecontroller;
|
||||
|
||||
std::string rgssErrorMsg;
|
||||
|
||||
RGSSThreadData(EventThread *ethread,
|
||||
|
|
|
@ -45,6 +45,12 @@ struct KbBindingData
|
|||
}
|
||||
};
|
||||
|
||||
struct GcBindingData
|
||||
{
|
||||
SDL_GameControllerButton source;
|
||||
Input::ButtonCode target;
|
||||
};
|
||||
|
||||
struct JsBindingData
|
||||
{
|
||||
int source;
|
||||
|
@ -101,6 +107,24 @@ static elementsN(defaultKbBindings);
|
|||
static elementsN(defaultKbBindings1);
|
||||
static elementsN(defaultKbBindings2);
|
||||
|
||||
static const GcBindingData defaultGcBindings[] =
|
||||
{
|
||||
{ SDL_CONTROLLER_BUTTON_DPAD_LEFT, Input::Left },
|
||||
{ SDL_CONTROLLER_BUTTON_DPAD_RIGHT, Input::Right },
|
||||
{ SDL_CONTROLLER_BUTTON_DPAD_UP, Input::Up },
|
||||
{ SDL_CONTROLLER_BUTTON_DPAD_DOWN, Input::Down },
|
||||
{ SDL_CONTROLLER_BUTTON_A, Input::C },
|
||||
{ SDL_CONTROLLER_BUTTON_B, Input::B },
|
||||
{ SDL_CONTROLLER_BUTTON_START, Input::A },
|
||||
{ SDL_CONTROLLER_BUTTON_X, Input::X },
|
||||
{ SDL_CONTROLLER_BUTTON_Y, Input::Y },
|
||||
{ SDL_CONTROLLER_BUTTON_BACK, Input::Z },
|
||||
{ SDL_CONTROLLER_BUTTON_LEFTSHOULDER, Input::L },
|
||||
{ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, Input::R }
|
||||
};
|
||||
|
||||
static elementsN(defaultGcBindings);
|
||||
|
||||
static const JsBindingData defaultJsBindings[] =
|
||||
{
|
||||
{ 0, Input::A },
|
||||
|
@ -143,7 +167,38 @@ static void addHatBinding(BDescVec &d, uint8_t hat, uint8_t pos, Input::ButtonCo
|
|||
d.push_back(desc);
|
||||
}
|
||||
|
||||
BDescVec genDefaultBindings(const Config &conf)
|
||||
static void addGcBinding(BDescVec &d, SDL_GameController *gc, SDL_GameControllerButton but, Input::ButtonCode target)
|
||||
{
|
||||
SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForButton(gc, but);
|
||||
|
||||
switch(bind.bindType)
|
||||
{
|
||||
case SDL_CONTROLLER_BINDTYPE_BUTTON:
|
||||
SourceDesc src;
|
||||
src.type = JButton;
|
||||
src.d.jb = bind.value.button;
|
||||
|
||||
BindingDesc desc;
|
||||
desc.src = src;
|
||||
desc.target = target;
|
||||
|
||||
d.push_back(desc);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLER_BINDTYPE_HAT:
|
||||
addHatBinding(d, bind.value.hat.hat, bind.value.hat.hat_mask, target);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLER_BINDTYPE_AXIS:
|
||||
/* For now if a button turns out to be analog, let's assume positive is the correct direction */
|
||||
addAxisBinding(d, bind.value.axis, Positive, target);
|
||||
|
||||
case SDL_CONTROLLER_BINDTYPE_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BDescVec genDefaultBindings(const Config &conf, SDL_GameController *gc)
|
||||
{
|
||||
BDescVec d;
|
||||
|
||||
|
@ -157,13 +212,23 @@ BDescVec genDefaultBindings(const Config &conf)
|
|||
for (size_t i = 0; i < defaultKbBindings2N; ++i)
|
||||
defaultKbBindings2[i].add(d);
|
||||
|
||||
for (size_t i = 0; i < defaultJsBindingsN; ++i)
|
||||
defaultJsBindings[i].add(d);
|
||||
|
||||
addAxisBinding(d, 0, Negative, Input::Left );
|
||||
addAxisBinding(d, 0, Positive, Input::Right);
|
||||
addAxisBinding(d, 1, Negative, Input::Up );
|
||||
addAxisBinding(d, 1, Positive, Input::Down );
|
||||
|
||||
/* Try to get a sane binding through SDL_GameController
|
||||
* if that doesn't work fall back to the default JS bindings */
|
||||
if (gc != NULL)
|
||||
{
|
||||
for(size_t i = 0; i < defaultGcBindingsN; ++i)
|
||||
addGcBinding(d, gc, defaultGcBindings[i].source, defaultGcBindings[i].target);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < defaultJsBindingsN; ++i)
|
||||
defaultJsBindings[i].add(d);
|
||||
|
||||
addHatBinding(d, 0, SDL_HAT_LEFT, Input::Left );
|
||||
addHatBinding(d, 0, SDL_HAT_RIGHT, Input::Right);
|
||||
|
@ -320,7 +385,7 @@ static bool readBindings(BDescVec &out, const std::string &dir,
|
|||
return true;
|
||||
}
|
||||
|
||||
BDescVec loadBindings(const Config &conf)
|
||||
BDescVec loadBindings(const Config &conf, SDL_GameController *gc)
|
||||
{
|
||||
BDescVec d;
|
||||
|
||||
|
@ -330,5 +395,5 @@ BDescVec loadBindings(const Config &conf)
|
|||
if (readBindings(d, conf.commonDataPath, conf.rgssVersion))
|
||||
return d;
|
||||
|
||||
return genDefaultBindings(conf);
|
||||
return genDefaultBindings(conf, gc);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <SDL_scancode.h>
|
||||
#include <SDL_joystick.h>
|
||||
#include <SDL_gamecontroller.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
@ -111,9 +112,9 @@ struct BindingDesc
|
|||
typedef std::vector<BindingDesc> BDescVec;
|
||||
struct Config;
|
||||
|
||||
BDescVec genDefaultBindings(const Config &conf);
|
||||
BDescVec genDefaultBindings(const Config &conf, SDL_GameController *gc);
|
||||
|
||||
void storeBindings(const BDescVec &d, const Config &conf);
|
||||
BDescVec loadBindings(const Config &conf);
|
||||
BDescVec loadBindings(const Config &conf, SDL_GameController *gc);
|
||||
|
||||
#endif // KEYBINDINGS_H
|
||||
|
|
15
src/main.cpp
15
src/main.cpp
|
@ -25,6 +25,7 @@
|
|||
#include <SDL_image.h>
|
||||
#include <SDL_ttf.h>
|
||||
#include <SDL_sound.h>
|
||||
#include <SDL_gamecontroller.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include "binding.h"
|
||||
|
||||
#include "icon.png.xxd"
|
||||
#include "gamecontrollerdb.txt.xxd"
|
||||
|
||||
static void
|
||||
rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
|
||||
|
@ -175,7 +177,7 @@ static void printRgssVersion(int ver)
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* initialize SDL first */
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0)
|
||||
{
|
||||
Debug() << "Error initializing SDL:" << SDL_GetError();
|
||||
|
||||
|
@ -276,8 +278,17 @@ int main(int argc, char *argv[])
|
|||
EventThread eventThread;
|
||||
RGSSThreadData rtData(&eventThread, argv[0], win, conf);
|
||||
|
||||
/* Add controller bindings from embedded controller DB */
|
||||
SDL_RWops *controllerDB;
|
||||
controllerDB = SDL_RWFromConstMem(assets_gamecontrollerdb_txt, assets_gamecontrollerdb_txt_len);
|
||||
SDL_GameControllerAddMappingsFromRW(controllerDB, 1);
|
||||
|
||||
rtData.gamecontroller = NULL;
|
||||
if (SDL_NumJoysticks() > 0 && SDL_IsGameController(0))
|
||||
rtData.gamecontroller = SDL_GameControllerOpen(0);
|
||||
|
||||
/* Load and post key bindings */
|
||||
rtData.bindingUpdateMsg.post(loadBindings(conf));
|
||||
rtData.bindingUpdateMsg.post(loadBindings(conf, rtData.gamecontroller));
|
||||
|
||||
/* Start RGSS thread */
|
||||
SDL_Thread *rgssThread =
|
||||
|
|
|
@ -706,7 +706,7 @@ struct SettingsMenuPrivate
|
|||
|
||||
void onResetToDefault()
|
||||
{
|
||||
setupBindingData(genDefaultBindings(rtData.config));
|
||||
setupBindingData(genDefaultBindings(rtData.config, rtData.gamecontroller));
|
||||
updateDuplicateStatus();
|
||||
redraw();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue