Browse Source

Options: Extract keymapper handling from options

pull/7670/head
Gleb Mazovetskiy 1 year ago
parent
commit
acc335be17
  1. 3
      Source/CMakeLists.txt
  2. 60
      Source/controls/keymapper.cpp
  3. 16
      Source/controls/keymapper.hpp
  4. 19
      Source/diablo.cpp
  5. 50
      Source/options.cpp
  6. 14
      Source/options.h

3
Source/CMakeLists.txt

@ -38,11 +38,12 @@ set(libdevilutionx_SRCS
track.cpp
controls/axis_direction.cpp
controls/controller.cpp
controls/controller_motion.cpp
controls/controller.cpp
controls/devices/joystick.cpp
controls/devices/kbcontroller.cpp
controls/game_controls.cpp
controls/keymapper.cpp
controls/menu_controls.cpp
controls/modifier_hints.cpp
controls/plrctrls.cpp

60
Source/controls/keymapper.cpp

@ -0,0 +1,60 @@
#include "controls/keymapper.hpp"
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#include "control.h"
#include "options.h"
#include "utils/is_of.hpp"
namespace devilution {
namespace {
bool IsTextEntryKey(SDL_Keycode vkey)
{
return IsAnyOf(vkey, SDLK_ESCAPE, SDLK_RETURN, SDLK_KP_ENTER, SDLK_BACKSPACE, SDLK_DOWN, SDLK_UP) || (vkey >= SDLK_SPACE && vkey <= SDLK_z);
}
bool IsNumberEntryKey(SDL_Keycode vkey)
{
return ((vkey >= SDLK_0 && vkey <= SDLK_9) || vkey == SDLK_BACKSPACE);
}
SDL_Keycode ToAsciiUpper(SDL_Keycode key)
{
if (key >= SDLK_a && key <= SDLK_z) {
return static_cast<SDL_Keycode>(static_cast<Sint32>(key) - ('a' - 'A'));
}
return key;
}
} // namespace
void KeymapperPress(SDL_Keycode key)
{
key = ToAsciiUpper(key);
const KeymapperOptions::Action *action = GetOptions().Keymapper.findAction(static_cast<uint32_t>(key));
if (action == nullptr || !action->actionPressed || !action->isEnabled()) return;
// TODO: This should be handled outside of the keymapper.
if (ChatFlag) return;
action->actionPressed();
}
void KeymapperRelease(SDL_Keycode key)
{
key = ToAsciiUpper(key);
const KeymapperOptions::Action *action = GetOptions().Keymapper.findAction(static_cast<uint32_t>(key));
if (action == nullptr || !action->actionReleased || !action->isEnabled()) return;
// TODO: This should be handled outside of the keymapper.
if ((ChatFlag && IsTextEntryKey(key)) || (DropGoldFlag && IsNumberEntryKey(key))) return;
action->actionReleased();
}
} // namespace devilution

16
Source/controls/keymapper.hpp

@ -0,0 +1,16 @@
#pragma once
#include <cstdint>
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
namespace devilution {
void KeymapperPress(SDL_Keycode key);
void KeymapperRelease(SDL_Keycode key);
} // namespace devilution

19
Source/diablo.cpp

@ -22,6 +22,7 @@
#include "debug.h"
#endif
#include "DiabloUI/diabloui.h"
#include "controls/keymapper.hpp"
#include "controls/plrctrls.h"
#include "controls/remap_keyboard.h"
#include "diablo.h"
@ -457,7 +458,7 @@ void ReleaseKey(SDL_Keycode vkey)
remap_keyboard_key(&vkey);
if (sgnTimeoutCurs != CURSOR_NONE)
return;
GetOptions().Keymapper.KeyReleased(vkey);
KeymapperRelease(vkey);
}
void ClosePanels()
@ -491,7 +492,7 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
if (sgnTimeoutCurs != CURSOR_NONE) {
return;
}
options.Keymapper.KeyPressed(vkey);
KeymapperPress(vkey);
if (vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) {
if ((modState & KMOD_ALT) != 0) {
options.Graphics.fullscreen.SetValue(!IsFullScreen());
@ -525,7 +526,7 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
return;
}
options.Keymapper.KeyPressed(vkey);
KeymapperPress(vkey);
if (PauseMode == 2) {
if ((vkey == SDLK_RETURN || vkey == SDLK_KP_ENTER) && (modState & KMOD_ALT) != 0) {
@ -656,7 +657,7 @@ void HandleMouseButtonDown(Uint8 button, uint16_t modState)
RightMouseDown((modState & KMOD_SHIFT) != 0);
break;
default:
GetOptions().Keymapper.KeyPressed(button | KeymapperMouseButtonMask);
KeymapperPress(static_cast<SDL_Keycode>(button | KeymapperMouseButtonMask));
break;
}
}
@ -672,7 +673,7 @@ void HandleMouseButtonUp(Uint8 button, uint16_t modState)
LastMouseButtonAction = MouseActionType::None;
sgbMouseDown = CLICK_NONE;
} else {
GetOptions().Keymapper.KeyReleased(static_cast<SDL_Keycode>(button | KeymapperMouseButtonMask));
KeymapperRelease(static_cast<SDL_Keycode>(button | KeymapperMouseButtonMask));
}
}
@ -757,7 +758,7 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
} else if (IsStashOpen) {
Stash.PreviousPage();
} else {
options.Keymapper.KeyPressed(MouseScrollUpButton);
KeymapperPress(MouseScrollUpButton);
}
} else if (event.wheel.y < 0) { // down
if (ActiveStore != TalkID::None) {
@ -771,12 +772,12 @@ void GameEventHandler(const SDL_Event &event, uint16_t modState)
} else if (IsStashOpen) {
Stash.NextPage();
} else {
options.Keymapper.KeyPressed(MouseScrollDownButton);
KeymapperPress(MouseScrollDownButton);
}
} else if (event.wheel.x > 0) { // left
options.Keymapper.KeyPressed(MouseScrollLeftButton);
KeymapperPress(MouseScrollLeftButton);
} else if (event.wheel.x < 0) { // right
options.Keymapper.KeyPressed(MouseScrollRightButton);
KeymapperPress(MouseScrollRightButton);
}
break;
#endif

50
Source/options.cpp

@ -1167,9 +1167,9 @@ std::vector<OptionEntryBase *> KeymapperOptions::GetEntries()
KeymapperOptions::Action::Action(std::string_view key, const char *name, const char *description, uint32_t defaultKey, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index)
: OptionEntryBase(key, OptionEntryFlags::None, name, description)
, defaultKey(defaultKey)
, actionPressed(std::move(actionPressed))
, actionReleased(std::move(actionReleased))
, defaultKey(defaultKey)
, enable(std::move(enable))
, dynamicIndex(index)
{
@ -1278,53 +1278,11 @@ void KeymapperOptions::CommitActions()
actions.reverse();
}
void KeymapperOptions::KeyPressed(uint32_t key) const
const KeymapperOptions::Action *KeymapperOptions::findAction(uint32_t key) const
{
if (key >= SDLK_a && key <= SDLK_z) {
key -= 'a' - 'A';
}
auto it = keyIDToAction.find(key);
if (it == keyIDToAction.end())
return; // Ignore unmapped keys.
const Action &action = it->second.get();
// Check that the action can be triggered and that the chat textbox is not
// open.
if (!action.actionPressed || (action.enable && !action.enable()) || ChatFlag)
return;
action.actionPressed();
}
void KeymapperOptions::KeyReleased(SDL_Keycode key) const
{
if (key >= SDLK_a && key <= SDLK_z) {
key = static_cast<SDL_Keycode>(static_cast<Sint32>(key) - ('a' - 'A'));
}
auto it = keyIDToAction.find(key);
if (it == keyIDToAction.end())
return; // Ignore unmapped keys.
const Action &action = it->second.get();
// Check that the action can be triggered and that the chat or gold textbox is not
// open. If either of those textboxes are open, only return if the key can be used for entry into the box
if (!action.actionReleased || (action.enable && !action.enable()) || ((ChatFlag && IsTextEntryKey(key)) || (DropGoldFlag && IsNumberEntryKey(key))))
return;
action.actionReleased();
}
bool KeymapperOptions::IsTextEntryKey(SDL_Keycode vkey) const
{
return IsAnyOf(vkey, SDLK_ESCAPE, SDLK_RETURN, SDLK_KP_ENTER, SDLK_BACKSPACE, SDLK_DOWN, SDLK_UP) || (vkey >= SDLK_SPACE && vkey <= SDLK_z);
}
bool KeymapperOptions::IsNumberEntryKey(SDL_Keycode vkey) const
{
return ((vkey >= SDLK_0 && vkey <= SDLK_9) || vkey == SDLK_BACKSPACE);
if (it == keyIDToAction.end()) return nullptr;
return &it->second.get();
}
std::string_view KeymapperOptions::KeyNameForAction(std::string_view actionName) const

14
Source/options.h

@ -700,10 +700,13 @@ struct KeymapperOptions : OptionCategoryBase {
bool SetValue(int value);
private:
uint32_t defaultKey;
[[nodiscard]] bool isEnabled() const { return !enable || enable(); }
std::function<void()> actionPressed;
std::function<void()> actionReleased;
private:
uint32_t defaultKey;
std::function<bool()> enable;
uint32_t boundKey = SDLK_UNKNOWN;
unsigned dynamicIndex;
@ -723,10 +726,9 @@ struct KeymapperOptions : OptionCategoryBase {
std::function<bool()> enable = nullptr,
unsigned index = 0);
void CommitActions();
void KeyPressed(uint32_t key) const;
void KeyReleased(SDL_Keycode key) const;
bool IsTextEntryKey(SDL_Keycode vkey) const;
bool IsNumberEntryKey(SDL_Keycode vkey) const;
[[nodiscard]] const Action *findAction(uint32_t key) const;
std::string_view KeyNameForAction(std::string_view actionName) const;
uint32_t KeyForAction(std::string_view actionName) const;

Loading…
Cancel
Save