Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Options: More untangling #7652

Merged
merged 6 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -219,6 +220,21 @@ target_link_dependencies(libdevilutionx_controller_buttons
DevilutionX::SDL
)

add_devilutionx_object_library(libdevilutionx_control_mode
controls/control_mode.cpp
)
target_link_dependencies(libdevilutionx_control_mode PUBLIC
libdevilutionx_controller_buttons
)

add_devilutionx_object_library(libdevilutionx_padmapper
controls/padmapper.cpp
)
target_link_dependencies(libdevilutionx_padmapper PUBLIC
libdevilutionx_controller_buttons
libdevilutionx_options
)

add_devilutionx_object_library(libdevilutionx_crawl
crawl.cpp
)
Expand Down Expand Up @@ -419,6 +435,7 @@ target_link_dependencies(libdevilutionx_options PUBLIC
fmt::fmt
tl
libdevilutionx_controller_buttons
libdevilutionx_control_mode
libdevilutionx_logged_fstream
libdevilutionx_quick_messages
libdevilutionx_strings
Expand Down Expand Up @@ -645,6 +662,7 @@ target_link_dependencies(libdevilutionx PUBLIC
libdevilutionx_codec
libdevilutionx_config
libdevilutionx_controller_buttons
libdevilutionx_control_mode
libdevilutionx_crawl
libdevilutionx_direction
libdevilutionx_surface
Expand All @@ -662,6 +680,7 @@ target_link_dependencies(libdevilutionx PUBLIC
libdevilutionx_mpq
libdevilutionx_multiplayer
libdevilutionx_options
libdevilutionx_padmapper
libdevilutionx_parse_int
libdevilutionx_pathfinding
libdevilutionx_pkware_encrypt
Expand Down
1 change: 1 addition & 0 deletions Source/DiabloUI/diabloui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "DiabloUI/dialogs.h"
#include "DiabloUI/scrollbar.h"
#include "DiabloUI/text_input.hpp"
#include "controls/control_mode.hpp"
#include "controls/controller.h"
#include "controls/input.h"
#include "controls/menu_controls.h"
Expand Down
1 change: 1 addition & 0 deletions Source/DiabloUI/hero/selhero.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "DiabloUI/selok.h"
#include "DiabloUI/selyesno.h"
#include "control.h"
#include "controls/control_mode.hpp"
#include "controls/plrctrls.h"
#include "engine/assets.hpp"
#include "game_mode.hpp"
Expand Down
1 change: 1 addition & 0 deletions Source/control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "DiabloUI/text_input.hpp"
#include "automap.h"
#include "controls/control_mode.hpp"
#include "controls/modifier_hints.h"
#include "controls/plrctrls.h"
#include "cursor.h"
Expand Down
16 changes: 16 additions & 0 deletions Source/controls/control_mode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "controls/control_mode.hpp"

namespace devilution {

ControlTypes ControlMode = ControlTypes::None;
ControlTypes ControlDevice = ControlTypes::None;

GamepadLayout GamepadType =
#if defined(DEVILUTIONX_GAMEPAD_TYPE)
GamepadLayout::
DEVILUTIONX_GAMEPAD_TYPE;
#else
GamepadLayout::Generic;
#endif

} // namespace devilution
30 changes: 30 additions & 0 deletions Source/controls/control_mode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <cstdint>

#include "controls/controller_buttons.h"

namespace devilution {

enum class ControlTypes : uint8_t {
None,
KeyboardAndMouse,
Gamepad,
VirtualGamepad,
};

extern ControlTypes ControlMode;

/**
* @brief Controlling device type.
*
* While simulating a mouse, `ControlMode` is set to `KeyboardAndMouse`,
* even though a gamepad is used to control it.
*
* This value is always set to the actual active device type.
*/
extern ControlTypes ControlDevice;

extern GamepadLayout GamepadType;

} // namespace devilution
11 changes: 0 additions & 11 deletions Source/controls/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,6 @@

namespace devilution {

struct ControllerButtonEvent {
ControllerButtonEvent(ControllerButton button, bool up)
: button(button)
, up(up)
{
}

ControllerButton button;
bool up;
};

// Must be called exactly once at the start of each SDL input event.
void UnlockControllerState(const SDL_Event &event);

Expand Down
10 changes: 2 additions & 8 deletions Source/controls/controller_buttons.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "controller_buttons.h"

#include "controls/game_controls.h"

namespace devilution {
namespace {
namespace controller_button_icon {
Expand Down Expand Up @@ -280,13 +278,9 @@ std::string_view ToXboxIcon(ControllerButton button)

} // namespace

// Defined in `plrctrls.cpp`.
// Declared here to avoid having to depend on it in tests.
extern GamepadLayout GamepadType;

std::string_view ToString(ControllerButton button)
std::string_view ToString(GamepadLayout gamepadType, ControllerButton button)
{
switch (GamepadType) {
switch (gamepadType) {
case GamepadLayout::PlayStation:
return ToPlayStationIcon(button);
case GamepadLayout::Nintendo:
Expand Down
20 changes: 19 additions & 1 deletion Source/controls/controller_buttons.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ struct ControllerButtonCombo {
ControllerButton button;
};

struct ControllerButtonEvent {
ControllerButtonEvent(ControllerButton button, bool up)
: button(button)
, up(up)
{
}

ControllerButton button;
bool up;
};

inline bool IsDPadButton(ControllerButton button)
{
return button == ControllerButton_BUTTON_DPAD_UP
Expand All @@ -63,6 +74,13 @@ inline bool IsDPadButton(ControllerButton button)
|| button == ControllerButton_BUTTON_DPAD_RIGHT;
}

std::string_view ToString(ControllerButton button);
enum class GamepadLayout : uint8_t {
Generic,
Nintendo,
PlayStation,
Xbox,
};

[[nodiscard]] std::string_view ToString(GamepadLayout gamepadType, ControllerButton button);

} // namespace devilution
32 changes: 16 additions & 16 deletions Source/controls/controller_motion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
#include <cmath>

#include "control.h"
#include "controls/control_mode.hpp"
#include "controls/controller.h"
#ifndef USE_SDL1
#include "controls/devices/game_controller.h"
#endif
#include "controls/devices/joystick.h"
#include "controls/game_controls.h"
#include "controls/padmapper.hpp"
#include "controls/plrctrls.h"
#include "controls/touch/gamepad.h"
#include "engine/demomode.h"
Expand Down Expand Up @@ -71,16 +73,15 @@ void ScaleJoystickAxes(float *x, float *y, float deadzone)
bool IsMovementOverriddenByPadmapper(ControllerButton button)
{
ControllerButtonEvent releaseEvent { button, true };
const Options &options = GetOptions();
std::string_view actionName = options.Padmapper.ActionNameTriggeredByButtonEvent(releaseEvent);
ControllerButtonCombo buttonCombo = options.Padmapper.ButtonComboForAction(actionName);
std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(releaseEvent);
ControllerButtonCombo buttonCombo = GetOptions().Padmapper.ButtonComboForAction(actionName);
return buttonCombo.modifier != ControllerButton_NONE;
}

bool TriggersQuickSpellAction(ControllerButton button)
{
ControllerButtonEvent releaseEvent { button, true };
std::string_view actionName = GetOptions().Padmapper.ActionNameTriggeredByButtonEvent(releaseEvent);
std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(releaseEvent);

std::string_view prefix { "QuickSpell" };
if (actionName.size() < prefix.size())
Expand All @@ -91,7 +92,8 @@ bool TriggersQuickSpellAction(ControllerButton button)

bool IsPressedForMovement(ControllerButton button)
{
return !PadMenuNavigatorActive
return gbRunGame
&& !PadMenuNavigatorActive
&& IsControllerButtonPressed(button)
&& !IsMovementOverriddenByPadmapper(button)
&& !(SpellSelectFlag && TriggersQuickSpellAction(button));
Expand Down Expand Up @@ -210,12 +212,11 @@ AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper)
bool isLeftPressed = stickX <= -0.5;
bool isRightPressed = stickX >= 0.5;

const Options &options = GetOptions();
if (usePadmapper) {
isUpPressed |= options.Padmapper.IsActive("MoveUp");
isDownPressed |= options.Padmapper.IsActive("MoveDown");
isLeftPressed |= options.Padmapper.IsActive("MoveLeft");
isRightPressed |= options.Padmapper.IsActive("MoveRight");
isUpPressed |= PadmapperIsActionActive("MoveUp");
isDownPressed |= PadmapperIsActionActive("MoveDown");
isLeftPressed |= PadmapperIsActionActive("MoveLeft");
isRightPressed |= PadmapperIsActionActive("MoveRight");
} else if (!SimulatingMouseWithPadmapper) {
isUpPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_UP);
isDownPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_DOWN);
Expand Down Expand Up @@ -254,8 +255,7 @@ void SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent)
if (!ctrlEvent.up && ctrlEvent.button == SuppressedButton)
return;

const Options &options = GetOptions();
std::string_view actionName = options.Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent);
std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(ctrlEvent);
bool upTriggered = actionName == "MouseUp";
bool downTriggered = actionName == "MouseDown";
bool leftTriggered = actionName == "MouseLeft";
Expand All @@ -266,10 +266,10 @@ void SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent)
return;
}

bool upActive = (upTriggered && !ctrlEvent.up) || (!upTriggered && options.Padmapper.IsActive("MouseUp"));
bool downActive = (downTriggered && !ctrlEvent.up) || (!downTriggered && options.Padmapper.IsActive("MouseDown"));
bool leftActive = (leftTriggered && !ctrlEvent.up) || (!leftTriggered && options.Padmapper.IsActive("MouseLeft"));
bool rightActive = (rightTriggered && !ctrlEvent.up) || (!rightTriggered && options.Padmapper.IsActive("MouseRight"));
bool upActive = (upTriggered && !ctrlEvent.up) || (!upTriggered && PadmapperIsActionActive("MouseUp"));
bool downActive = (downTriggered && !ctrlEvent.up) || (!downTriggered && PadmapperIsActionActive("MouseDown"));
bool leftActive = (leftTriggered && !ctrlEvent.up) || (!leftTriggered && PadmapperIsActionActive("MouseLeft"));
bool rightActive = (rightTriggered && !ctrlEvent.up) || (!rightTriggered && PadmapperIsActionActive("MouseRight"));

rightStickX = 0;
rightStickY = 0;
Expand Down
38 changes: 32 additions & 6 deletions Source/controls/game_controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

#include <cstdint>

#include "controls/control_mode.hpp"
#include "controls/controller_motion.h"
#ifndef USE_SDL1
#include "controls/devices/game_controller.h"
#endif
#include "controls/devices/joystick.h"
#include "controls/padmapper.hpp"
#include "controls/plrctrls.h"
#include "controls/touch/gamepad.h"
#include "doom.h"
Expand Down Expand Up @@ -214,6 +216,28 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, Game
return false;
}

bool CanDeferToMovementHandler(const PadmapperOptions::Action &action)
{
if (action.boundInput.modifier != ControllerButton_NONE)
return false;

if (SpellSelectFlag) {
const std::string_view prefix { "QuickSpell" };
const std::string_view key { action.key };
if (key.size() >= prefix.size()) {
const std::string_view truncated { key.data(), prefix.size() };
if (truncated == prefix)
return false;
}
}

return IsAnyOf(action.boundInput.button,
ControllerButton_BUTTON_DPAD_UP,
ControllerButton_BUTTON_DPAD_DOWN,
ControllerButton_BUTTON_DPAD_LEFT,
ControllerButton_BUTTON_DPAD_RIGHT);
}

void PressControllerButton(ControllerButton button)
{
if (IsStashOpen) {
Expand Down Expand Up @@ -298,7 +322,10 @@ void PressControllerButton(ControllerButton button)
}
}

GetOptions().Padmapper.ButtonPressed(button);
const PadmapperOptions::Action *action = GetOptions().Padmapper.findAction(button, IsControllerButtonPressed);
if (action == nullptr) return;
if (IsMovementHandlerActive() && CanDeferToMovementHandler(*action)) return;
PadmapperPress(button, *action);
}

} // namespace
Expand Down Expand Up @@ -337,7 +364,7 @@ bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent)
return false;
if (!ctrlEvent.up && ctrlEvent.button == SuppressedButton)
return false;
std::string_view actionName = GetOptions().Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent);
const std::string_view actionName = PadmapperActionNameTriggeredByButtonEvent(ctrlEvent);
return IsAnyOf(actionName, "LeftMouseClick1", "LeftMouseClick2", "RightMouseClick1", "RightMouseClick2");
}

Expand All @@ -355,8 +382,7 @@ bool HandleControllerButtonEvent(const SDL_Event &event, const ControllerButtonE
struct ButtonReleaser {
~ButtonReleaser()
{
if (ctrlEvent.up)
GetOptions().Padmapper.ButtonReleased(ctrlEvent.button, false);
if (ctrlEvent.up) PadmapperRelease(ctrlEvent.button, /*invokeAction=*/false);
}
ControllerButtonEvent ctrlEvent;
};
Expand All @@ -377,10 +403,10 @@ bool HandleControllerButtonEvent(const SDL_Event &event, const ControllerButtonE
SuppressedButton = ControllerButton_NONE;
}

if (ctrlEvent.up && GetOptions().Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent) != "") {
if (ctrlEvent.up && !PadmapperActionNameTriggeredByButtonEvent(ctrlEvent).empty()) {
// Button press may have brought up a menu;
// don't confuse release of that button with intent to interact with the menu
GetOptions().Padmapper.ButtonReleased(ctrlEvent.button);
PadmapperRelease(ctrlEvent.button, /*invokeAction=*/true);
return true;
} else if (GetGameAction(event, ctrlEvent, &action)) {
ProcessGameAction(action);
Expand Down
7 changes: 0 additions & 7 deletions Source/controls/game_controls.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@

namespace devilution {

enum class GamepadLayout : uint8_t {
Generic,
Nintendo,
PlayStation,
Xbox,
};

enum GameActionType : uint8_t {
GameActionType_NONE,
GameActionType_USE_HEALTH_POTION,
Expand Down
Loading
Loading