Skip to content

Commit

Permalink
Added support for SDL_GameController with fallback to default method.
Browse files Browse the repository at this point in the history
  • Loading branch information
Daverball committed Jan 1, 2015
1 parent 02f19c0 commit 225b97a
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 13 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ set(EMBEDDED_INPUT
shader/blurH.vert
shader/blurV.vert
shader/simpleMatrix.vert
assets/gamecontrollerdb.txt
assets/liberation.ttf
assets/icon.png
)
Expand Down
75 changes: 75 additions & 0 deletions assets/gamecontrollerdb.txt

Large diffs are not rendered by default.

22 changes: 20 additions & 2 deletions src/eventthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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 :
Expand Down Expand Up @@ -358,6 +373,9 @@ void EventThread::process(RGSSThreadData &rtData)
break;
}

if (SDL_GameControllerGetAttached(rtData.gamecontroller))
SDL_GameControllerClose(rtData.gamecontroller);

if (SDL_JoystickGetAttached(js))
SDL_JoystickClose(js);

Expand Down
3 changes: 3 additions & 0 deletions src/eventthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include <SDL_scancode.h>
#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>
#include <SDL_mouse.h>
#include <SDL_mutex.h>

Expand Down Expand Up @@ -231,6 +232,8 @@ struct RGSSThreadData

Config config;

SDL_GameController *gamecontroller;

std::string rgssErrorMsg;

RGSSThreadData(EventThread *ethread,
Expand Down
74 changes: 68 additions & 6 deletions src/keybindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ struct KbBindingData
}
};

struct GcBindingData
{
SDL_GameControllerButton source;
Input::ButtonCode target;
};

struct JsBindingData
{
int source;
Expand Down Expand Up @@ -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::A },
{ SDL_CONTROLLER_BUTTON_B, Input::B },
{ SDL_CONTROLLER_BUTTON_START, Input::C },
{ 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 },
Expand Down Expand Up @@ -143,7 +167,35 @@ 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);
}
}

BDescVec genDefaultBindings(const Config &conf, SDL_GameController *gc)
{
BDescVec d;

Expand All @@ -157,13 +209,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);
Expand Down Expand Up @@ -320,7 +382,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;

Expand All @@ -330,5 +392,5 @@ BDescVec loadBindings(const Config &conf)
if (readBindings(d, conf.commonDataPath, conf.rgssVersion))
return d;

return genDefaultBindings(conf);
return genDefaultBindings(conf, gc);
}
5 changes: 3 additions & 2 deletions src/keybindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <SDL_scancode.h>
#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>
#include <stdint.h>
#include <assert.h>
#include <vector>
Expand Down Expand Up @@ -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 changes: 13 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -41,6 +42,7 @@
#include "binding.h"

#include "icon.png.xxd"
#include "gamecontrollerdb.txt.xxd"

static void
rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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 =
Expand Down
2 changes: 1 addition & 1 deletion src/settingsmenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ struct SettingsMenuPrivate

void onResetToDefault()
{
setupBindingData(genDefaultBindings(rtData.config));
setupBindingData(genDefaultBindings(rtData.config, rtData.gamecontroller));
updateDuplicateStatus();
redraw();
}
Expand Down

0 comments on commit 225b97a

Please sign in to comment.