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
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
@@ -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
@@ -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
)
@@ -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
@@ -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
@@ -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
1 change: 1 addition & 0 deletions Source/DiabloUI/diabloui.cpp
Original file line number Diff line number Diff line change
@@ -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"
1 change: 1 addition & 0 deletions Source/DiabloUI/hero/selhero.cpp
Original file line number Diff line number Diff line change
@@ -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"
1 change: 1 addition & 0 deletions Source/control.cpp
Original file line number Diff line number Diff line change
@@ -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"
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
@@ -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);

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 {
@@ -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:
20 changes: 19 additions & 1 deletion Source/controls/controller_buttons.h
Original file line number Diff line number Diff line change
@@ -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
@@ -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
@@ -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"
@@ -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())
@@ -91,7 +92,8 @@ bool TriggersQuickSpellAction(ControllerButton button)

bool IsPressedForMovement(ControllerButton button)
{
return !PadMenuNavigatorActive
return gbRunGame
&& !PadMenuNavigatorActive
&& IsControllerButtonPressed(button)
&& !IsMovementOverriddenByPadmapper(button)
&& !(SpellSelectFlag && TriggersQuickSpellAction(button));
@@ -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);
@@ -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";
@@ -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;
38 changes: 32 additions & 6 deletions Source/controls/game_controls.cpp
Original file line number Diff line number Diff line change
@@ -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"
@@ -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) {
@@ -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
@@ -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");
}

@@ -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;
};
@@ -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);
7 changes: 0 additions & 7 deletions Source/controls/game_controls.h
Original file line number Diff line number Diff line change
@@ -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,
Loading
Loading