Browse Source

GamepadAim

pull/8140/head
wkdgmr 7 months ago
parent
commit
2fcf0a9217
  1. 65
      Source/controls/controller_motion.cpp
  2. 4
      Source/controls/controller_motion.h
  3. 4
      Source/controls/modifier_hints.cpp
  4. 60
      Source/controls/plrctrls.cpp

65
Source/controls/controller_motion.cpp

@ -20,7 +20,12 @@
namespace devilution {
bool SimulatingMouseWithPadmapper;
static bool GamepadAimActive = false;
bool IsGamepadAimActive()
{
return GamepadAimActive;
}
namespace {
@ -98,15 +103,19 @@ bool IsPressedForMovement(ControllerButton button)
&& !(SpellSelectFlag && TriggersQuickSpellAction(button));
}
void SetSimulatingMouseWithPadmapper(bool value)
void SetGamepadAimActive(bool value)
{
if (SimulatingMouseWithPadmapper == value)
if (GamepadAimActive == value)
return;
SimulatingMouseWithPadmapper = value;
GamepadAimActive = value;
if (value) {
LogVerbose("Control: begin simulating mouse with D-Pad");
LogVerbose("GamepadAim: begin aiming");
// Show cursor for aiming (if needed)
} else {
LogVerbose("Control: end simulating mouse with D-Pad");
LogVerbose("GamepadAim: end aiming");
// Hide/reset cursor when movement resumes
ResetCursor();
}
}
@ -188,14 +197,41 @@ void ProcessControllerMotion(const SDL_Event &event)
GameController *const controller = GameController::Get(event);
if (controller != nullptr && devilution::GameController::ProcessAxisMotion(event)) {
ScaleJoysticks();
SetSimulatingMouseWithPadmapper(false);
// End aiming and hide cursor only when left stick axis moved
if (event.type == SDL_CONTROLLERAXISMOTION) {
if (event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX || event.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY) {
SetGamepadAimActive(false);
}
}
return;
}
#endif
Joystick *const joystick = Joystick::Get(event);
if (joystick != nullptr && devilution::Joystick::ProcessAxisMotion(event)) {
ScaleJoysticks();
SetSimulatingMouseWithPadmapper(false);
if (event.type == SDL_JOYAXISMOTION) {
#ifdef JOY_AXIS_LEFTX
if (event.jaxis.axis == JOY_AXIS_LEFTX)
SetGamepadAimActive(false);
#endif
#ifdef JOY_AXIS_LEFTY
if (event.jaxis.axis == JOY_AXIS_LEFTY)
SetGamepadAimActive(false);
#endif
}
}
// D-pad movement detection (button events, not padmapper mouse simulation)
StaticVector<ControllerButtonEvent, 4> buttonEvents = ToControllerButtonEvents(event);
for (const auto &ctrlEvent : buttonEvents) {
if (!ctrlEvent.up && IsDPadButton(ctrlEvent.button)) {
// Only clear aim if this is NOT a padmapper mouse simulation combo
// (i.e., no modifier or not SELECT + D-pad)
ControllerButtonCombo combo(ctrlEvent.button);
if (combo.modifier == ControllerButton_NONE) {
SetGamepadAimActive(false);
}
}
}
}
@ -216,7 +252,7 @@ AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper)
isDownPressed |= PadmapperIsActionActive("MoveDown");
isLeftPressed |= PadmapperIsActionActive("MoveLeft");
isRightPressed |= PadmapperIsActionActive("MoveRight");
} else if (!SimulatingMouseWithPadmapper) {
} else if (!IsGamepadAimActive()) {
isUpPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_UP);
isDownPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_DOWN);
isLeftPressed |= IsPressedForMovement(ControllerButton_BUTTON_DPAD_LEFT);
@ -259,11 +295,9 @@ void SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent)
const bool downTriggered = actionName == "MouseDown";
const bool leftTriggered = actionName == "MouseLeft";
const bool rightTriggered = actionName == "MouseRight";
if (!upTriggered && !downTriggered && !leftTriggered && !rightTriggered) {
if (rightStickX == 0 && rightStickY == 0)
SetSimulatingMouseWithPadmapper(false);
return;
}
if (!upTriggered && !downTriggered && !leftTriggered && !rightTriggered) {
return;
}
const bool upActive = (upTriggered && !ctrlEvent.up) || (!upTriggered && PadmapperIsActionActive("MouseUp"));
const bool downActive = (downTriggered && !ctrlEvent.up) || (!downTriggered && PadmapperIsActionActive("MouseDown"));
@ -280,7 +314,8 @@ void SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent)
rightStickX -= 1.F;
if (rightActive)
rightStickX += 1.F;
SetSimulatingMouseWithPadmapper(true);
// Begin aiming when any direction is active
SetGamepadAimActive(true);
}
} // namespace devilution

4
Source/controls/controller_motion.h

@ -8,9 +8,9 @@
#include "./controller.h"
namespace devilution {
// Returns true if gamepad aiming is currently active (right stick or padmapped mouse).
bool IsGamepadAimActive();
// Whether we're currently simulating the mouse with SELECT + D-Pad.
extern bool SimulatingMouseWithPadmapper;
// Raw axis values.
extern float leftStickXUnscaled, leftStickYUnscaled, rightStickXUnscaled, rightStickYUnscaled;

4
Source/controls/modifier_hints.cpp

@ -141,7 +141,7 @@ void DrawSpellsCircleMenuHint(const Surface &out, const Point &origin)
void DrawGamepadMenuNavigator(const Surface &out)
{
if (!PadMenuNavigatorActive || SimulatingMouseWithPadmapper)
if (!PadMenuNavigatorActive || IsGamepadAimActive())
return;
static const CircleMenuHint DPad(/*top=*/HintIcon::IconMenu, /*right=*/HintIcon::IconInv, /*bottom=*/HintIcon::IconMap, /*left=*/HintIcon::IconChar);
static const CircleMenuHint Buttons(/*top=*/HintIcon::IconNull, /*right=*/HintIcon::IconNull, /*bottom=*/HintIcon::IconSpells, /*left=*/HintIcon::IconQuests);
@ -152,7 +152,7 @@ void DrawGamepadMenuNavigator(const Surface &out)
void DrawGamepadHotspellMenu(const Surface &out)
{
if (!PadHotspellMenuActive || SimulatingMouseWithPadmapper)
if (!PadHotspellMenuActive || IsGamepadAimActive())
return;
const Rectangle &mainPanel = GetMainPanel();

60
Source/controls/plrctrls.cpp

@ -495,6 +495,13 @@ bool IsStandingGround()
void Interact()
{
if (IsGamepadAimActive()) {
const Player &myPlayer = *MyPlayer;
NetSendCmdLoc(MyPlayerId, true, myPlayer.UsesRangedWeapon() ? CMD_RATTACKXY : CMD_SATTACKXY, cursPosition);
LastPlayerAction = PlayerActionType::Attack;
return;
}
if (leveltype == DTYPE_TOWN && pcursmonst != -1) {
NetSendCmdLocParam1(true, CMD_TALKXY, Towners[pcursmonst].position, pcursmonst);
return;
@ -1642,7 +1649,7 @@ bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonE
return true;
}
return SimulatingMouseWithPadmapper || IsSimulatedMouseClickBinding(gamepadEvent);
return IsGamepadAimActive() || IsSimulatedMouseClickBinding(gamepadEvent);
}
std::string_view ControlTypeToString(ControlTypes controlType)
@ -1735,12 +1742,15 @@ void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &game
if (newControlDevice != ControlDevice) {
ControlDevice = newControlDevice;
#ifndef USE_SDL1
if (ControlDevice != ControlTypes::KeyboardAndMouse) {
if (IsHardwareCursor())
SetHardwareCursor(CursorInfo::UnknownCursor());
} else {
ResetCursor();
#ifndef USE_SDL1
// Prevent cursor hiding and device/mode swap while gamepad aiming is active
if (!IsGamepadAimActive()) {
if (ControlDevice != ControlTypes::KeyboardAndMouse) {
if (IsHardwareCursor())
SetHardwareCursor(CursorInfo::UnknownCursor());
} else {
ResetCursor();
}
}
if (ControlDevice == ControlTypes::Gamepad) {
const GamepadLayout newGamepadLayout = GameController::getLayout(event);
@ -1749,7 +1759,7 @@ void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &game
GamepadType = newGamepadLayout;
}
}
#endif
#endif
}
if (newControlMode != ControlMode) {
@ -1974,6 +1984,11 @@ void UseBeltItem(BeltItemType type)
void PerformPrimaryAction()
{
if (IsGamepadAimActive()) {
Interact();
return;
}
if (SpellSelectFlag) {
SetSpell();
return;
@ -2099,8 +2114,21 @@ void PerformSpellAction()
if (pcurs > CURSOR_HAND)
NewCursor(CURSOR_HAND);
const Player &myPlayer = *MyPlayer;
Player &myPlayer = *MyPlayer;
const SpellID spl = myPlayer._pRSpell;
// Controller aiming: always cast at cursor position and turn player
if (IsGamepadAimActive()) {
// Turn player to face cursor
Direction newDir = GetDirection(myPlayer.position.tile, cursPosition);
myPlayer._pdir = newDir;
// Set spell target
cursPosition = cursPosition;
CheckPlrSpell(false);
LastPlayerAction = PlayerActionType::Spell;
return;
}
if ((PlayerUnderCursor == nullptr && (spl == SpellID::Resurrect || spl == SpellID::HealOther))
|| (ObjectUnderCursor == nullptr && spl == SpellID::TrapDisarm)) {
myPlayer.Say(HeroSpeech::ICantCastThatHere);
@ -2190,6 +2218,20 @@ void PerformSecondaryAction()
if (!MyPlayer->HoldItem.isEmpty() && !TryDropItem())
return;
if (pcurs == CURSOR_TELEKINESIS
|| pcurs == CURSOR_IDENTIFY
|| pcurs == CURSOR_REPAIR
|| pcurs == CURSOR_RECHARGE
|| pcurs == CURSOR_DISARM
|| pcurs == CURSOR_OIL
|| pcurs == CURSOR_RESURRECT
|| pcurs == CURSOR_TELEPORT
|| pcurs == CURSOR_HEALOTHER) {
TryIconCurs();
return;
}
if (pcurs > CURSOR_HAND)
NewCursor(CURSOR_HAND);

Loading…
Cancel
Save