Skip to content

Commit

Permalink
Add "Analog trigger threshold" setting, for conversion of analog trig…
Browse files Browse the repository at this point in the history
…ger inputs to digital button inputs.
  • Loading branch information
hrydgard committed Dec 28, 2023
1 parent 15b5c7f commit 3895cff
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 11 deletions.
1 change: 1 addition & 0 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ static const ConfigSetting controlSettings[] = {
ConfigSetting("AnalogAutoRotSpeed", &g_Config.fAnalogAutoRotSpeed, 8.0f, CfgFlag::PER_GAME),

ConfigSetting("AnalogLimiterDeadzone", &g_Config.fAnalogLimiterDeadzone, 0.6f, CfgFlag::DEFAULT),
ConfigSetting("AnalogTriggerThreshold", &g_Config.fAnalogTriggerThreshold, 0.75f, CfgFlag::DEFAULT),

ConfigSetting("AllowMappingCombos", &g_Config.bAllowMappingCombos, false, CfgFlag::DEFAULT),

Expand Down
3 changes: 3 additions & 0 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,9 @@ struct Config {
// Sets up how much the analog limiter button restricts digital->analog input.
float fAnalogLimiterDeadzone;

// Trigger configuration
float fAnalogTriggerThreshold;

// Sets whether combo mapping is enabled.
bool bAllowMappingCombos;

Expand Down
26 changes: 20 additions & 6 deletions Core/ControlMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,23 @@

using KeyMap::MultiInputMapping;

// TODO: Possibly make these thresholds configurable?
static float GetDeviceAxisThreshold(int device) {
return device == DEVICE_ID_MOUSE ? AXIS_BIND_THRESHOLD_MOUSE : AXIS_BIND_THRESHOLD;
const float AXIS_BIND_THRESHOLD = 0.75f;
const float AXIS_BIND_THRESHOLD_MOUSE = 0.01f;

float GetDeviceAxisThreshold(int device, const InputMapping &mapping) {
if (device == DEVICE_ID_MOUSE) {
return AXIS_BIND_THRESHOLD_MOUSE;
}
if (mapping.IsAxis()) {
switch (KeyMap::GetAxisType((InputAxis)mapping.Axis(nullptr))) {
case KeyMap::AxisType::TRIGGER:
return g_Config.fAnalogTriggerThreshold;
default:
return AXIS_BIND_THRESHOLD;
}
} else {
return AXIS_BIND_THRESHOLD;
}
}

static int GetOppositeVKey(int vkey) {
Expand Down Expand Up @@ -311,7 +325,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no
} else {
curTime = iter->second.timestamp;
}
bool down = iter->second.value > GetDeviceAxisThreshold(iter->first.deviceId);
bool down = iter->second.value > GetDeviceAxisThreshold(iter->first.deviceId, mapping);
if (!down)
all = false;
}
Expand Down Expand Up @@ -364,7 +378,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping, double no
}

if (mapping.IsAxis()) {
threshold = GetDeviceAxisThreshold(iter->first.deviceId);
threshold = GetDeviceAxisThreshold(iter->first.deviceId, mapping);
float value = MapAxisValue(iter->second.value, idForMapping, mapping, changedMapping, &touchedByMapping);
product *= value;
} else {
Expand Down Expand Up @@ -510,7 +524,7 @@ void ControlMapper::ToggleSwapAxes() {
void ControlMapper::UpdateCurInputAxis(const InputMapping &mapping, float value, double timestamp) {
InputSample &input = curInput_[mapping];
input.value = value;
if (value > GetDeviceAxisThreshold(mapping.deviceId)) {
if (value >= GetDeviceAxisThreshold(mapping.deviceId, mapping)) {
if (input.timestamp == 0.0) {
input.timestamp = time_now_d();
}
Expand Down
1 change: 1 addition & 0 deletions Core/ControlMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ class ControlMapper {
};

void ConvertAnalogStick(float x, float y, float *outX, float *outY);
float GetDeviceAxisThreshold(int device, const InputMapping &mapping);
21 changes: 20 additions & 1 deletion Core/KeyMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ std::set<std::string> g_seenPads;
std::map<InputDeviceID, std::string> g_padNames;
std::set<InputDeviceID> g_seenDeviceIds;

AxisType GetAxisType(InputAxis input) {
switch (input) {
case JOYSTICK_AXIS_GAS:
case JOYSTICK_AXIS_BRAKE:
case JOYSTICK_AXIS_LTRIGGER:
case JOYSTICK_AXIS_RTRIGGER:
return AxisType::TRIGGER;
case JOYSTICK_AXIS_X:
case JOYSTICK_AXIS_Y:
case JOYSTICK_AXIS_Z:
case JOYSTICK_AXIS_RX:
case JOYSTICK_AXIS_RY:
case JOYSTICK_AXIS_RZ:
return AxisType::STICK;
default:
return AxisType::OTHER;
}
}

// Utility for UI navigation
void SingleInputMappingFromPspButton(int btn, std::vector<InputMapping> *mappings, bool ignoreMouse) {
std::vector<MultiInputMapping> multiMappings;
Expand Down Expand Up @@ -874,7 +893,7 @@ bool HasChanged(int &prevGeneration) {
return false;
}

static const char *g_vKeyNames[] = {
static const char * const g_vKeyNames[] = {
"AXIS_X_MIN",
"AXIS_Y_MIN",
"AXIS_X_MAX",
Expand Down
13 changes: 9 additions & 4 deletions Core/KeyMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,6 @@ enum {
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
};

const float AXIS_BIND_THRESHOLD = 0.75f;
const float AXIS_BIND_RELEASE_THRESHOLD = 0.35f; // Used during mapping only to detect a "key-up" reliably.
const float AXIS_BIND_THRESHOLD_MOUSE = 0.01f;

struct MappedAnalogAxis {
int axisId;
int direction;
Expand Down Expand Up @@ -224,4 +220,13 @@ namespace KeyMap {
bool IsKeyMapped(InputDeviceID device, int key);

bool HasChanged(int &prevGeneration);

// Used for setting thresholds. Technically we could allow a setting per axis, but this is a reasonable compromise.
enum class AxisType {
TRIGGER,
STICK,
OTHER,
};

AxisType GetAxisType(InputAxis axis);
} // namespace KeyMap
1 change: 1 addition & 0 deletions GPU/Common/TextureReplacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w,
desc.hashfiles = hashfiles;
}

_dbg_assert_(!hashfiles.empty());
// OK, we might already have a matching texture, we use hashfiles as a key. Look it up in the level cache.
auto iter = levelCache_.find(hashfiles);
if (iter != levelCache_.end()) {
Expand Down
4 changes: 4 additions & 0 deletions UI/ControlMappingScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ bool KeyMappingNewMouseKeyDialog::key(const KeyInput &key) {
return true;
}

// Only used during the bind process. In other places, it's configurable for some types of axis, like trigger.
const float AXIS_BIND_THRESHOLD = 0.75f;
const float AXIS_BIND_RELEASE_THRESHOLD = 0.35f; // Used during mapping only to detect a "key-up" reliably.

void KeyMappingNewKeyDialog::axis(const AxisInput &axis) {
if (time_now_d() < delayUntil_)
return;
Expand Down
1 change: 1 addition & 0 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings)
controlsSettings->Add(new ItemHeader(ms->T("Controls")));
controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
controlsSettings->Add(new Choice(co->T("Calibrate Analog Stick")))->OnClick.Handle(this, &GameSettingsScreen::OnCalibrateAnalogs);
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fAnalogTriggerThreshold, 0.25f, 0.98f, 0.75f, co->T("Analog trigger threshold"), screenManager()));

#if defined(USING_WIN_UI) || (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID))
controlsSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys")));
Expand Down

0 comments on commit 3895cff

Please sign in to comment.