Skip to content

Commit

Permalink
sdl: handle gamepad events
Browse files Browse the repository at this point in the history
Add new GamepadButton enum with bits corresponding to AppleJack button bits.
Both the AppleJack controller and the SDL GameController coincidentally define
one d-pad, two shoulder buttons, four face buttons, and three system buttons.
This makes mapping modern game controllers to the AppleJack straightforward.
  • Loading branch information
kkaisershot committed Oct 7, 2024
1 parent 6696248 commit d23f21b
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
38 changes: 38 additions & 0 deletions core/hostevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ enum : uint32_t {
MOUSE_EVENT_BUTTON = 1 << 1,
KEYBOARD_EVENT_DOWN = 1 << 0,
KEYBOARD_EVENT_UP = 1 << 1,
GAMEPAD_EVENT_DOWN = 1 << 0,
GAMEPAD_EVENT_UP = 1 << 1,
};

class MouseEvent {
Expand All @@ -65,6 +67,36 @@ class KeyboardEvent {
uint16_t keys_state;
};

/* AppleJack bits 3-7 are supported but unused */
enum GamepadButton : uint8_t {
Red = 14,
Green = 15,
Yellow = 9,
Blue = 8,

FrontLeft = 0,
FrontMiddle = 1,
FrontRight = 2,

LeftTrigger = 17,
RightTrigger = 16,

Up = 10,
Down = 13,
Left = 11,
Right = 12,
};

class GamepadEvent {
public:
GamepadEvent() = default;
~GamepadEvent() = default;

uint32_t gamepad_id;
uint32_t flags;
uint8_t button;
};

class EventManager {
public:
static EventManager* get_instance() {
Expand All @@ -91,6 +123,11 @@ class EventManager {
_keyboard_signal.connect_method(inst, func);
}

template <typename T>
void add_gamepad_handler(T* inst, void (T::*func)(const GamepadEvent&)) {
_gamepad_signal.connect_method(inst, func);
}

template <typename T>
void add_post_handler(T *inst, void (T::*func)()) {
_post_signal.connect_method(inst, func);
Expand All @@ -110,6 +147,7 @@ class EventManager {
CoreSignal<const WindowEvent&> _window_signal;
CoreSignal<const MouseEvent&> _mouse_signal;
CoreSignal<const KeyboardEvent&> _keyboard_signal;
CoreSignal<const GamepadEvent&> _gamepad_signal;
CoreSignal<> _post_signal;

uint64_t events_captured = 0;
Expand Down
46 changes: 46 additions & 0 deletions core/hostevents_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,52 @@ void EventManager::poll_events()
}
break;

case SDL_CONTROLLERBUTTONDOWN: {
GamepadEvent ge;
switch (event.cbutton.button) {
case SDL_CONTROLLER_BUTTON_BACK: ge.button = GamepadButton::FrontLeft; break;
case SDL_CONTROLLER_BUTTON_GUIDE: ge.button = GamepadButton::FrontMiddle; break;
case SDL_CONTROLLER_BUTTON_START: ge.button = GamepadButton::FrontRight; break;
case SDL_CONTROLLER_BUTTON_Y: ge.button = GamepadButton::Blue; break;
case SDL_CONTROLLER_BUTTON_X: ge.button = GamepadButton::Yellow; break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: ge.button = GamepadButton::Up; break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: ge.button = GamepadButton::Left; break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: ge.button = GamepadButton::Right; break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: ge.button = GamepadButton::Down; break;
case SDL_CONTROLLER_BUTTON_A: ge.button = GamepadButton::Red; break;
case SDL_CONTROLLER_BUTTON_B: ge.button = GamepadButton::Green; break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: ge.button = GamepadButton::RightTrigger; break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: ge.button = GamepadButton::LeftTrigger; break;
}
ge.gamepad_id = event.cbutton.which;
ge.flags = GAMEPAD_EVENT_DOWN;
this->_gamepad_signal.emit(ge);
}
break;

case SDL_CONTROLLERBUTTONUP: {
GamepadEvent ge;
switch (event.cbutton.button) {
case SDL_CONTROLLER_BUTTON_BACK: ge.button = GamepadButton::FrontLeft; break;
case SDL_CONTROLLER_BUTTON_GUIDE: ge.button = GamepadButton::FrontMiddle; break;
case SDL_CONTROLLER_BUTTON_START: ge.button = GamepadButton::FrontRight; break;
case SDL_CONTROLLER_BUTTON_Y: ge.button = GamepadButton::Blue; break;
case SDL_CONTROLLER_BUTTON_X: ge.button = GamepadButton::Yellow; break;
case SDL_CONTROLLER_BUTTON_DPAD_UP: ge.button = GamepadButton::Up; break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT: ge.button = GamepadButton::Left; break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: ge.button = GamepadButton::Right; break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN: ge.button = GamepadButton::Down; break;
case SDL_CONTROLLER_BUTTON_A: ge.button = GamepadButton::Red; break;
case SDL_CONTROLLER_BUTTON_B: ge.button = GamepadButton::Green; break;
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: ge.button = GamepadButton::RightTrigger; break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: ge.button = GamepadButton::LeftTrigger; break;
}
ge.gamepad_id = event.cbutton.which;
ge.flags = GAMEPAD_EVENT_UP;
this->_gamepad_signal.emit(ge);
}
break;

default:
unhandled_events++;
}
Expand Down
10 changes: 9 additions & 1 deletion main_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ extern "C" void remap_appkit_menu_shortcuts();
#endif

bool init() {
if (SDL_Init(SDL_INIT_VIDEO)) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER)) {
LOG_F(ERROR, "SDL_Init error: %s", SDL_GetError());
return false;
}

int num_joysticks = SDL_NumJoysticks();
for (int i = 0; i < num_joysticks; ++i) {
if (SDL_IsGameController(i)) {
SDL_GameControllerOpen(i); /* only support one controller for now */
break;
}
}

#ifdef __APPLE__
remap_appkit_menu_shortcuts();
#endif
Expand Down

0 comments on commit d23f21b

Please sign in to comment.