Browse Source

Produce multiple controller button events for SDL_JOYHATMOTION events

pull/5551/head
staphen 3 years ago committed by Anders Jenbo
parent
commit
b66b6c611b
  1. 9
      Source/DiabloUI/credits.cpp
  2. 5
      Source/DiabloUI/diabloui.cpp
  3. 8
      Source/DiabloUI/dialogs.cpp
  4. 8
      Source/DiabloUI/progress.cpp
  5. 52
      Source/DiabloUI/settingsmenu.cpp
  6. 3
      Source/DiabloUI/title.cpp
  7. 14
      Source/controls/controller.cpp
  8. 9
      Source/controls/controller.h
  9. 128
      Source/controls/devices/joystick.cpp
  10. 16
      Source/controls/devices/joystick.h
  11. 11
      Source/controls/game_controls.cpp
  12. 2
      Source/controls/game_controls.h
  13. 110
      Source/controls/menu_controls.cpp
  14. 3
      Source/controls/menu_controls.h
  15. 9
      Source/diablo.cpp
  16. 11
      Source/movie.cpp

9
Source/DiabloUI/credits.cpp

@ -149,14 +149,13 @@ bool TextDialog(char const *const *text, std::size_t textLines)
endMenu = true;
break;
default:
switch (GetMenuAction(event)) {
case MenuAction_BACK:
case MenuAction_SELECT:
for (MenuAction menuAction : GetMenuActions(event)) {
if (IsNoneOf(menuAction, MenuAction_BACK, MenuAction_SELECT))
continue;
endMenu = true;
break;
default:
break;
}
break;
}
UiHandleEvents(&event);
}

5
Source/DiabloUI/diabloui.cpp

@ -368,7 +368,10 @@ void UiFocusNavigation(SDL_Event *event)
break;
}
if (HandleMenuAction(GetMenuAction(*event)))
bool menuActionHandled = false;
for (MenuAction menuAction : GetMenuActions(*event))
menuActionHandled |= HandleMenuAction(menuAction);
if (menuActionHandled)
return;
#if SDL_VERSION_ATLEAST(2, 0, 0)

8
Source/DiabloUI/dialogs.cpp

@ -116,13 +116,11 @@ void DialogLoop(const std::vector<std::unique_ptr<UiItemBase>> &items, const std
UiItemMouseEvents(&event, items);
break;
default:
switch (GetMenuAction(event)) {
case MenuAction_BACK:
case MenuAction_SELECT:
for (MenuAction menuAction : GetMenuActions(event)) {
if (IsNoneOf(menuAction, MenuAction_BACK, MenuAction_SELECT))
continue;
dialogEnd = true;
break;
default:
break;
}
break;
}

8
Source/DiabloUI/progress.cpp

@ -139,13 +139,11 @@ bool UiProgressDialog(int (*fnfunc)())
endMenu = true;
break;
default:
switch (GetMenuAction(event)) {
case MenuAction_BACK:
case MenuAction_SELECT:
for (MenuAction menuAction : GetMenuActions(event)) {
if (IsNoneOf(menuAction, MenuAction_BACK, MenuAction_SELECT))
continue;
endMenu = true;
break;
default:
break;
}
break;
}

52
Source/DiabloUI/settingsmenu.cpp

@ -429,32 +429,36 @@ void UiSettingsMenu()
if (padEntryStartTime == 0)
return false;
ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event);
bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent);
DetectInputMethod(event, ctrlEvent);
if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) {
StopPadEntryTimer();
return true;
}
if (isGamepadMotion || IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) {
return true;
}
bool modifierPressed = padEntryCombo.modifier != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.modifier);
bool buttonPressed = padEntryCombo.button != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.button);
if (ctrlEvent.up) {
// When the player has released all relevant inputs, assume the binding is finished and stop the timer
if (padEntryCombo.button != ControllerButton_NONE && !modifierPressed && !buttonPressed)
StaticVector<ControllerButtonEvent, 4> ctrlEvents = ToControllerButtonEvents(event);
for (ControllerButtonEvent ctrlEvent : ctrlEvents) {
bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent);
DetectInputMethod(event, ctrlEvent);
if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) {
StopPadEntryTimer();
return true;
}
return true;
}
if (isGamepadMotion || IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) {
continue;
}
auto *pOptionPad = static_cast<PadmapperOptions::Action *>(selectedOption);
if (!modifierPressed && buttonPressed)
padEntryCombo.modifier = padEntryCombo.button;
padEntryCombo.button = ctrlEvent.button;
if (pOptionPad->SetValue(padEntryCombo))
vecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription().data();
bool modifierPressed = padEntryCombo.modifier != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.modifier);
bool buttonPressed = padEntryCombo.button != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.button);
if (ctrlEvent.up) {
// When the player has released all relevant inputs, assume the binding is finished and stop the timer
if (padEntryCombo.button != ControllerButton_NONE && !modifierPressed && !buttonPressed) {
StopPadEntryTimer();
return true;
}
continue;
}
auto *pOptionPad = static_cast<PadmapperOptions::Action *>(selectedOption);
if (!modifierPressed && buttonPressed)
padEntryCombo.modifier = padEntryCombo.button;
padEntryCombo.button = ctrlEvent.button;
if (pOptionPad->SetValue(padEntryCombo))
vecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription().data();
}
return true;
};
UpdateDescription(*selectedOption);

3
Source/DiabloUI/title.cpp

@ -68,7 +68,8 @@ void UiTitleDialog()
discord_manager::UpdateMenu();
while (PollEvent(&event) != 0) {
if (GetMenuAction(event) != MenuAction_NONE) {
std::vector<MenuAction> menuActions = GetMenuActions(event);
if (std::any_of(menuActions.begin(), menuActions.end(), [](auto menuAction) { return menuAction != MenuAction_NONE; })) {
endMenu = true;
break;
}

14
Source/controls/controller.cpp

@ -18,9 +18,13 @@ void UnlockControllerState(const SDL_Event &event)
controller->UnlockTriggerState();
}
#endif
Joystick *const joystick = Joystick::Get(event);
if (joystick != nullptr) {
joystick->UnlockHatState();
}
}
ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event)
StaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event &event)
{
ControllerButtonEvent result { ControllerButton_NONE, false };
switch (event.type) {
@ -37,7 +41,7 @@ ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event)
#if HAS_KBCTRL == 1
result.button = KbCtrlToControllerButton(event);
if (result.button != ControllerButton_NONE)
return result;
return { result };
#endif
#ifndef USE_SDL1
GameController *const controller = GameController::Get(event);
@ -47,17 +51,17 @@ ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event)
if (result.button == ControllerButton_AXIS_TRIGGERLEFT || result.button == ControllerButton_AXIS_TRIGGERRIGHT) {
result.up = !controller->IsPressed(result.button);
}
return result;
return { result };
}
}
#endif
const Joystick *joystick = Joystick::Get(event);
if (joystick != nullptr) {
result.button = devilution::Joystick::ToControllerButton(event);
return devilution::Joystick::ToControllerButtonEvents(event);
}
return result;
return { result };
}
bool IsControllerButtonPressed(ControllerButton button)

9
Source/controls/controller.h

@ -3,10 +3,17 @@
#include <SDL.h>
#include "controller_buttons.h"
#include "utils/static_vector.hpp"
namespace devilution {
struct ControllerButtonEvent {
ControllerButtonEvent(ControllerButton button, bool up)
: button(button)
, up(up)
{
}
ControllerButton button;
bool up;
};
@ -14,7 +21,7 @@ struct ControllerButtonEvent {
// Must be called exactly once at the start of each SDL input event.
void UnlockControllerState(const SDL_Event &event);
ControllerButtonEvent ToControllerButtonEvent(const SDL_Event &event);
StaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event &event);
bool IsControllerButtonPressed(ControllerButton button);
bool IsControllerButtonComboPressed(ControllerButtonCombo combo);

128
Source/controls/devices/joystick.cpp

@ -10,103 +10,159 @@ namespace devilution {
std::vector<Joystick> Joystick::joysticks_;
ControllerButton Joystick::ToControllerButton(const SDL_Event &event)
StaticVector<ControllerButtonEvent, 4> Joystick::ToControllerButtonEvents(const SDL_Event &event)
{
switch (event.type) {
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
case SDL_JOYBUTTONUP: {
bool up = (event.jbutton.state == SDL_RELEASED);
switch (event.jbutton.button) {
#ifdef JOY_BUTTON_A
case JOY_BUTTON_A:
return ControllerButton_BUTTON_A;
return { ControllerButtonEvent { ControllerButton_BUTTON_A, up } };
#endif
#ifdef JOY_BUTTON_B
case JOY_BUTTON_B:
return ControllerButton_BUTTON_B;
return { ControllerButtonEvent { ControllerButton_BUTTON_B, up } };
#endif
#ifdef JOY_BUTTON_X
case JOY_BUTTON_X:
return ControllerButton_BUTTON_X;
return { ControllerButtonEvent { ControllerButton_BUTTON_X, up } };
#endif
#ifdef JOY_BUTTON_Y
case JOY_BUTTON_Y:
return ControllerButton_BUTTON_Y;
return { ControllerButtonEvent { ControllerButton_BUTTON_Y, up } };
#endif
#ifdef JOY_BUTTON_LEFTSTICK
case JOY_BUTTON_LEFTSTICK:
return ControllerButton_BUTTON_LEFTSTICK;
return { ControllerButtonEvent { ControllerButton_BUTTON_LEFTSTICK, up } };
#endif
#ifdef JOY_BUTTON_RIGHTSTICK
case JOY_BUTTON_RIGHTSTICK:
return ControllerButton_BUTTON_RIGHTSTICK;
return { ControllerButtonEvent { ControllerButton_BUTTON_RIGHTSTICK, up } };
#endif
#ifdef JOY_BUTTON_LEFTSHOULDER
case JOY_BUTTON_LEFTSHOULDER:
return ControllerButton_BUTTON_LEFTSHOULDER;
return { ControllerButtonEvent { ControllerButton_BUTTON_LEFTSHOULDER, up } };
#endif
#ifdef JOY_BUTTON_RIGHTSHOULDER
case JOY_BUTTON_RIGHTSHOULDER:
return ControllerButton_BUTTON_RIGHTSHOULDER;
return { ControllerButtonEvent { ControllerButton_BUTTON_RIGHTSHOULDER, up } };
#endif
#ifdef JOY_BUTTON_TRIGGERLEFT
case JOY_BUTTON_TRIGGERLEFT:
return ControllerButton_AXIS_TRIGGERLEFT;
return { ControllerButtonEvent { ControllerButton_AXIS_TRIGGERLEFT, up } };
#endif
#ifdef JOY_BUTTON_TRIGGERRIGHT
case JOY_BUTTON_TRIGGERRIGHT:
return ControllerButton_AXIS_TRIGGERRIGHT;
return { ControllerButtonEvent { ControllerButton_AXIS_TRIGGERRIGHT, up } };
#endif
#ifdef JOY_BUTTON_START
case JOY_BUTTON_START:
return ControllerButton_BUTTON_START;
return { ControllerButtonEvent { ControllerButton_BUTTON_START, up } };
#endif
#ifdef JOY_BUTTON_BACK
case JOY_BUTTON_BACK:
return ControllerButton_BUTTON_BACK;
return { ControllerButtonEvent { ControllerButton_BUTTON_BACK, up } };
#endif
#ifdef JOY_BUTTON_DPAD_LEFT
case JOY_BUTTON_DPAD_LEFT:
return ControllerButton_BUTTON_DPAD_LEFT;
return { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_LEFT, up } };
#endif
#ifdef JOY_BUTTON_DPAD_UP
case JOY_BUTTON_DPAD_UP:
return ControllerButton_BUTTON_DPAD_UP;
return { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_UP, up } };
#endif
#ifdef JOY_BUTTON_DPAD_RIGHT
case JOY_BUTTON_DPAD_RIGHT:
return ControllerButton_BUTTON_DPAD_RIGHT;
return { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_RIGHT, up } };
#endif
#ifdef JOY_BUTTON_DPAD_DOWN
case JOY_BUTTON_DPAD_DOWN:
return ControllerButton_BUTTON_DPAD_DOWN;
return { ControllerButtonEvent { ControllerButton_BUTTON_DPAD_DOWN, up } };
#endif
default:
break;
return { ControllerButtonEvent { ControllerButton_IGNORE, up } };
}
break;
case SDL_JOYHATMOTION:
}
case SDL_JOYHATMOTION: {
Joystick *joystick = Get(event);
if (joystick == nullptr)
return { ControllerButtonEvent { ControllerButton_IGNORE, false } };
joystick->UpdateHatState(event.jhat);
return joystick->GetHatEvents();
}
case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION:
// ProcessAxisMotion() requires a ControllerButtonEvent parameter
// so provide one here using ControllerButton_NONE
return { ControllerButtonEvent { ControllerButton_NONE, false } };
default:
return {};
}
}
StaticVector<ControllerButtonEvent, 4> Joystick::GetHatEvents()
{
StaticVector<ControllerButtonEvent, 4> hatEvents;
if (hatState_[0].didStateChange)
hatEvents.emplace_back(ControllerButton_BUTTON_DPAD_UP, !hatState_[0].pressed);
if (hatState_[1].didStateChange)
hatEvents.emplace_back(ControllerButton_BUTTON_DPAD_DOWN, !hatState_[1].pressed);
if (hatState_[2].didStateChange)
hatEvents.emplace_back(ControllerButton_BUTTON_DPAD_LEFT, !hatState_[2].pressed);
if (hatState_[3].didStateChange)
hatEvents.emplace_back(ControllerButton_BUTTON_DPAD_RIGHT, !hatState_[3].pressed);
if (hatEvents.size() == 0)
hatEvents.emplace_back(ControllerButton_IGNORE, false);
return hatEvents;
}
void Joystick::UpdateHatState(const SDL_JoyHatEvent &event)
{
if (lockHatState_)
return;
#if defined(JOY_HAT_DPAD_UP_HAT) && defined(JOY_HAT_DPAD_UP)
if (event.jhat.hat == JOY_HAT_DPAD_UP_HAT && (event.jhat.value & JOY_HAT_DPAD_UP) != 0)
return ControllerButton_BUTTON_DPAD_UP;
if (event.hat == JOY_HAT_DPAD_UP_HAT) {
HatState &hatState = hatState_[0];
bool pressed = (event.value & JOY_HAT_DPAD_UP) != 0;
hatState.didStateChange = (pressed != hatState.pressed);
hatState.pressed = pressed;
}
#endif
#if defined(JOY_HAT_DPAD_DOWN_HAT) && defined(JOY_HAT_DPAD_DOWN)
if (event.jhat.hat == JOY_HAT_DPAD_DOWN_HAT && (event.jhat.value & JOY_HAT_DPAD_DOWN) != 0)
return ControllerButton_BUTTON_DPAD_DOWN;
if (event.hat == JOY_HAT_DPAD_DOWN_HAT) {
HatState &hatState = hatState_[1];
bool pressed = (event.value & JOY_HAT_DPAD_DOWN) != 0;
hatState.didStateChange = (pressed != hatState.pressed);
hatState.pressed = pressed;
}
#endif
#if defined(JOY_HAT_DPAD_LEFT_HAT) && defined(JOY_HAT_DPAD_LEFT)
if (event.jhat.hat == JOY_HAT_DPAD_LEFT_HAT && (event.jhat.value & JOY_HAT_DPAD_LEFT) != 0)
return ControllerButton_BUTTON_DPAD_LEFT;
if (event.hat == JOY_HAT_DPAD_LEFT_HAT) {
HatState &hatState = hatState_[2];
bool pressed = (event.value & JOY_HAT_DPAD_LEFT) != 0;
hatState.didStateChange = (pressed != hatState.pressed);
hatState.pressed = pressed;
}
#endif
#if defined(JOY_HAT_DPAD_RIGHT_HAT) && defined(JOY_HAT_DPAD_RIGHT)
if (event.jhat.hat == JOY_HAT_DPAD_RIGHT_HAT && (event.jhat.value & JOY_HAT_DPAD_RIGHT) != 0)
return ControllerButton_BUTTON_DPAD_RIGHT;
#endif
return ControllerButton_IGNORE;
break;
default:
break;
if (event.hat == JOY_HAT_DPAD_RIGHT_HAT) {
HatState &hatState = hatState_[3];
bool pressed = (event.value & JOY_HAT_DPAD_RIGHT) != 0;
hatState.didStateChange = (pressed != hatState.pressed);
hatState.pressed = pressed;
}
return ControllerButton_NONE;
#endif
lockHatState_ = true;
}
void Joystick::UnlockHatState()
{
lockHatState_ = false;
for (HatState &hatState : hatState_)
hatState.didStateChange = false;
}
int Joystick::ToSdlJoyButton(ControllerButton button)
@ -322,9 +378,9 @@ Joystick *Joystick::Get(const SDL_Event &event)
case SDL_JOYHATMOTION:
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
return joysticks_.empty() ? NULL : &joysticks_[0];
return joysticks_.empty() ? nullptr : &joysticks_[0];
default:
return NULL;
return nullptr;
#endif
}
}

16
Source/controls/devices/joystick.h

@ -1,6 +1,7 @@
#pragma once
// Joystick mappings for SDL1 and additional buttons on SDL2.
#include <array>
#include <vector>
#include <SDL.h>
@ -11,6 +12,7 @@
#include "controls/controller.h"
#include "controls/controller_buttons.h"
#include "utils/static_vector.hpp"
namespace devilution {
@ -25,7 +27,10 @@ public:
static const std::vector<Joystick> &All();
static bool IsPressedOnAnyJoystick(ControllerButton button);
static ControllerButton ToControllerButton(const SDL_Event &event);
// Must be called exactly once at the start of each SDL input event.
void UnlockHatState();
static StaticVector<ControllerButtonEvent, 4> ToControllerButtonEvents(const SDL_Event &event);
bool IsPressed(ControllerButton button) const;
static bool ProcessAxisMotion(const SDL_Event &event);
@ -35,12 +40,21 @@ public:
}
private:
struct HatState {
bool pressed;
bool didStateChange;
};
static int ToSdlJoyButton(ControllerButton button);
bool IsHatButtonPressed(ControllerButton button) const;
StaticVector<ControllerButtonEvent, 4> GetHatEvents();
void UpdateHatState(const SDL_JoyHatEvent &event);
SDL_Joystick *sdl_joystick_ = NULL;
SDL_JoystickID instance_id_ = -1;
std::array<HatState, 4> hatState_;
bool lockHatState_ = false;
};
} // namespace devilution

11
Source/controls/game_controls.cpp

@ -345,8 +345,12 @@ AxisDirection GetMoveDirection()
return GetLeftStickOrDpadDirection(true);
}
bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action)
bool HandleControllerButtonEvent(const SDL_Event &event, const ControllerButtonEvent ctrlEvent, GameAction &action)
{
if (ctrlEvent.button == ControllerButton_IGNORE) {
return false;
}
struct ButtonReleaser {
~ButtonReleaser()
{
@ -356,11 +360,6 @@ bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action)
ControllerButtonEvent ctrlEvent;
};
const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event);
if (ctrlEvent.button == ControllerButton_IGNORE) {
return false;
}
const ButtonReleaser buttonReleaser { ctrlEvent };
bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent);
DetectInputMethod(event, ctrlEvent);

2
Source/controls/game_controls.h

@ -67,7 +67,7 @@ bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent);
AxisDirection GetMoveDirection();
bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action);
bool HandleControllerButtonEvent(const SDL_Event &event, const ControllerButtonEvent ctrlEvent, GameAction &action);
extern bool PadMenuNavigatorActive;
extern bool PadHotspellMenuActive;

110
Source/controls/menu_controls.cpp

@ -24,44 +24,58 @@ MenuAction GetMenuHeldUpDownAction()
}
}
MenuAction GetMenuAction(const SDL_Event &event)
std::vector<MenuAction> GetMenuActions(const SDL_Event &event)
{
const ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event);
if (ctrlEvent.button == ControllerButton_IGNORE) {
return MenuAction_NONE;
}
std::vector<MenuAction> menuActions;
for (const ControllerButtonEvent ctrlEvent : ToControllerButtonEvents(event)) {
if (ctrlEvent.button == ControllerButton_IGNORE) {
continue;
}
bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent);
DetectInputMethod(event, ctrlEvent);
if (isGamepadMotion) {
return GetMenuHeldUpDownAction();
}
bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent);
DetectInputMethod(event, ctrlEvent);
if (isGamepadMotion) {
menuActions.push_back(GetMenuHeldUpDownAction());
continue;
}
if (!ctrlEvent.up) {
switch (TranslateTo(GamepadType, ctrlEvent.button)) {
case ControllerButton_BUTTON_A:
case ControllerButton_BUTTON_START:
return MenuAction_SELECT;
case ControllerButton_BUTTON_BACK:
case ControllerButton_BUTTON_B:
return MenuAction_BACK;
case ControllerButton_BUTTON_X:
return MenuAction_DELETE;
case ControllerButton_BUTTON_DPAD_UP:
case ControllerButton_BUTTON_DPAD_DOWN:
return GetMenuHeldUpDownAction();
case ControllerButton_BUTTON_DPAD_LEFT:
return MenuAction_LEFT;
case ControllerButton_BUTTON_DPAD_RIGHT:
return MenuAction_RIGHT;
case ControllerButton_BUTTON_LEFTSHOULDER:
return MenuAction_PAGE_UP;
case ControllerButton_BUTTON_RIGHTSHOULDER:
return MenuAction_PAGE_DOWN;
default:
break;
if (!ctrlEvent.up) {
switch (TranslateTo(GamepadType, ctrlEvent.button)) {
case ControllerButton_BUTTON_A:
case ControllerButton_BUTTON_START:
menuActions.push_back(MenuAction_SELECT);
break;
case ControllerButton_BUTTON_BACK:
case ControllerButton_BUTTON_B:
menuActions.push_back(MenuAction_BACK);
break;
case ControllerButton_BUTTON_X:
menuActions.push_back(MenuAction_DELETE);
break;
case ControllerButton_BUTTON_DPAD_UP:
case ControllerButton_BUTTON_DPAD_DOWN:
menuActions.push_back(GetMenuHeldUpDownAction());
break;
case ControllerButton_BUTTON_DPAD_LEFT:
menuActions.push_back(MenuAction_LEFT);
break;
case ControllerButton_BUTTON_DPAD_RIGHT:
menuActions.push_back(MenuAction_RIGHT);
break;
case ControllerButton_BUTTON_LEFTSHOULDER:
menuActions.push_back(MenuAction_PAGE_UP);
break;
case ControllerButton_BUTTON_RIGHTSHOULDER:
menuActions.push_back(MenuAction_PAGE_DOWN);
break;
default:
break;
}
}
}
if (!menuActions.empty()) {
return menuActions;
}
if (event.type == SDL_MOUSEBUTTONDOWN) {
switch (event.button.button) {
@ -69,7 +83,7 @@ MenuAction GetMenuAction(const SDL_Event &event)
#if !SDL_VERSION_ATLEAST(2, 0, 0)
case 8:
#endif
return MenuAction_BACK;
return { MenuAction_BACK };
}
}
@ -79,45 +93,45 @@ MenuAction GetMenuAction(const SDL_Event &event)
remap_keyboard_key(&sym);
switch (sym) {
case SDLK_UP:
return MenuAction_UP;
return { MenuAction_UP };
case SDLK_DOWN:
return MenuAction_DOWN;
return { MenuAction_DOWN };
case SDLK_TAB:
if ((SDL_GetModState() & KMOD_SHIFT) != 0)
return MenuAction_UP;
return { MenuAction_UP };
else
return MenuAction_DOWN;
return { MenuAction_DOWN };
case SDLK_PAGEUP:
return MenuAction_PAGE_UP;
return { MenuAction_PAGE_UP };
case SDLK_PAGEDOWN:
return MenuAction_PAGE_DOWN;
return { MenuAction_PAGE_DOWN };
case SDLK_RETURN:
if ((SDL_GetModState() & KMOD_ALT) == 0) {
return MenuAction_SELECT;
return { MenuAction_SELECT };
}
break;
case SDLK_KP_ENTER:
return MenuAction_SELECT;
return { MenuAction_SELECT };
case SDLK_SPACE:
if (!textInputActive) {
return MenuAction_SELECT;
return { MenuAction_SELECT };
}
break;
case SDLK_DELETE:
return MenuAction_DELETE;
return { MenuAction_DELETE };
case SDLK_LEFT:
return MenuAction_LEFT;
return { MenuAction_LEFT };
case SDLK_RIGHT:
return MenuAction_RIGHT;
return { MenuAction_RIGHT };
case SDLK_ESCAPE:
return MenuAction_BACK;
return { MenuAction_BACK };
default:
break;
}
}
#endif
return MenuAction_NONE;
return {};
} // namespace devilution
} // namespace devilution

3
Source/controls/menu_controls.h

@ -2,6 +2,7 @@
#include <SDL.h>
#include <cstdint>
#include <vector>
namespace devilution {
@ -20,7 +21,7 @@ enum MenuAction : uint8_t {
MenuAction_PAGE_DOWN,
};
MenuAction GetMenuAction(const SDL_Event &event);
std::vector<MenuAction> GetMenuActions(const SDL_Event &event);
/** Menu action from holding the left stick or DPad. */
MenuAction GetMenuHeldUpDownAction();

9
Source/diablo.cpp

@ -677,9 +677,10 @@ bool HandleTextInput(string_view text)
void GameEventHandler(const SDL_Event &event, uint16_t modState)
{
GameAction action;
if (HandleControllerButtonEvent(event, action)) {
if (action.type == GameActionType_SEND_KEY) {
StaticVector<ControllerButtonEvent, 4> ctrlEvents = ToControllerButtonEvents(event);
for (ControllerButtonEvent ctrlEvent : ctrlEvents) {
GameAction action;
if (HandleControllerButtonEvent(event, ctrlEvent, action) && action.type == GameActionType_SEND_KEY) {
if ((action.send_key.vk_code & KeymapperMouseButtonMask) != 0) {
const unsigned button = action.send_key.vk_code & ~KeymapperMouseButtonMask;
if (!action.send_key.up)
@ -693,6 +694,8 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
ReleaseKey(static_cast<SDL_Keycode>(action.send_key.vk_code));
}
}
}
if (ctrlEvents.size() > 0 && ctrlEvents[0].button != ControllerButton_NONE) {
return;
}

11
Source/movie.cpp

@ -42,9 +42,14 @@ void play_movie(const char *pszMovie, bool userCanClose)
uint16_t modState;
while (movie_playing) {
while (movie_playing && FetchMessage(&event, &modState)) {
ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event);
if (userCanClose && SkipsMovie(ctrlEvent))
movie_playing = false;
if (userCanClose) {
for (ControllerButtonEvent ctrlEvent : ToControllerButtonEvents(event)) {
if (!SkipsMovie(ctrlEvent))
continue;
movie_playing = false;
break;
}
}
switch (event.type) {
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONUP:

Loading…
Cancel
Save