Skip to content

Commit

Permalink
input: implement ramp up/down for analog axes mapped to buttons
Browse files Browse the repository at this point in the history
Full analog axes now have a ramp up/down of 100 ms when the mapped
button is pressed/released. Works also for keyboards.
Issue #1017
  • Loading branch information
flyinghead committed Nov 26, 2024
1 parent 516982c commit 792aa38
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 13 deletions.
76 changes: 76 additions & 0 deletions core/input/gamepad_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,82 @@ void GamepadDevice::SaveMaplePorts()
}
}

s16 (&GamepadDevice::getTargetArray(DigAnalog axis))[4]
{
switch (axis)
{
case DIGANA_LEFT:
case DIGANA_RIGHT:
return joyx;
case DIGANA_UP:;
case DIGANA_DOWN:
return joyy;
case DIGANA2_LEFT:
case DIGANA2_RIGHT:
return joyrx;
case DIGANA2_UP:
case DIGANA2_DOWN:
return joyry;
case DIGANA3_LEFT:
case DIGANA3_RIGHT:
return joy3x;
case DIGANA3_UP:
case DIGANA3_DOWN:
return joy3y;
default:
die("unknown axis");
}
}

void GamepadDevice::rampAnalog()
{
if (lastAnalogUpdate == 0)
// also used as a flag that no analog ramping is needed on this device (yet)
return;

const u64 now = getTimeMs();
const int delta = std::round(static_cast<float>(now - lastAnalogUpdate) * AnalogRamp);
lastAnalogUpdate = now;
for (unsigned port = 0; port < std::size(digitalToAnalogState); port++)
{
for (int axis = 0; axis < 12; axis += 2) // 3 sticks with 2 axes each
{
DigAnalog negDir = static_cast<DigAnalog>(1 << axis);
if ((rampAnalogState[port] & negDir) == 0)
// axis not active
continue;
DigAnalog posDir = static_cast<DigAnalog>(1 << (axis + 1));
const int socd = digitalToAnalogState[port] & (negDir | posDir);
s16& axisValue = getTargetArray(negDir)[port];
if (socd != 0 && socd != (negDir | posDir))
{
// One axis is pressed => ramp up
if (socd == posDir)
axisValue = std::min(32767, axisValue + delta);
else
axisValue = std::max(-32768, axisValue - delta);
}
else
{
// No axis is pressed (or both) => ramp down
if (axisValue > 0)
axisValue = std::max(0, axisValue - delta);
else if (axisValue < 0)
axisValue = std::min(0, axisValue + delta);
else
rampAnalogState[port] &= ~negDir;
}
}
}
}

void GamepadDevice::RampAnalog()
{
std::lock_guard<std::mutex> _(_gamepads_mutex);
for (auto& gamepad : _gamepads)
gamepad->rampAnalog();
}

#ifdef TEST_AUTOMATION
#include "cfg/option.h"
static bool replay_inited;
Expand Down
22 changes: 13 additions & 9 deletions core/input/gamepad_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once
#include "types.h"
#include "mapping.h"
#include "stdclass.h"

#include <map>
#include <memory>
Expand Down Expand Up @@ -98,6 +99,7 @@ class GamepadDevice
static int GetGamepadCount();
static std::shared_ptr<GamepadDevice> GetGamepad(int index);
static void SaveMaplePorts();
static void RampAnalog();

static void load_system_mappings();
bool find_mapping(int system = settings.platform.system);
Expand Down Expand Up @@ -163,16 +165,14 @@ class GamepadDevice
digitalToAnalogState[port] |= axis;
else
digitalToAnalogState[port] &= ~axis;
const u32 socd = digitalToAnalogState[port] & (NegDir | PosDir);
if (socd == 0 || socd == (NegDir | PosDir))
joystick = 0;
else if (socd == NegDir)
joystick = -32768;
else
joystick = 32767;

rampAnalogState[port] |= NegDir;
if (lastAnalogUpdate == 0)
lastAnalogUpdate = getTimeMs();
}

s16 (&getTargetArray(DigAnalog axis))[4];
void rampAnalog();

std::string _api_name;
int _maple_port;
bool _detecting_button = false;
Expand All @@ -184,7 +184,11 @@ class GamepadDevice
std::map<DreamcastKey, int> lastAxisValue[4];
bool perGameMapping = false;
bool instanceMapping = false;


u64 lastAnalogUpdate = 0;
u32 rampAnalogState[4] {};
static constexpr float AnalogRamp = 32767.f / 100.f; // 100 ms ramp time

static std::vector<std::shared_ptr<GamepadDevice>> _gamepads;
static std::mutex _gamepads_mutex;
};
Expand Down
9 changes: 5 additions & 4 deletions core/oslib/oslib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <shlobj.h>
#endif
#include "profiler/fc_profiler.h"
#include "input/gamepad_device.h"

namespace hostfs
{
Expand Down Expand Up @@ -370,12 +371,12 @@ void os_UpdateInputState()
{
FC_PROFILE_SCOPE;

// FIXME threading (android) this will be called on the render thread, events are on the main app thread
GamepadDevice::RampAnalog();
#if defined(USE_SDL)
input_sdl_handle();
#else
#if defined(USE_EVDEV)
input_evdev_handle();
#endif
#elif defined(USE_EVDEV)
input_evdev_handle();
#endif
}

Expand Down

0 comments on commit 792aa38

Please sign in to comment.