summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorTilka <tilkax@gmail.com>2019-02-03 00:56:05 +0000
committerGitHub <noreply@github.com>2019-02-03 00:56:05 +0000
commitcfbc852fb065532ebd2ce01d2cb277b3f8035b33 (patch)
treeeb81d6aecbd333e5d9133af6e38684c94170cd13 /Source/Core
parent6ec11c68017434cdd7dddb681e537aa733ff1464 (diff)
parent3bc4968c1173eee90813fd9b34656e4933de60e9 (diff)
Merge pull request #7777 from jordan-woyak/input-rounding
ControllerEmu: Round input floats instead of casting.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/GCPadEmu.cpp24
-rw-r--r--Source/Core/InputCommon/ControllerEmu/ControllerEmu.h25
2 files changed, 35 insertions, 14 deletions
diff --git a/Source/Core/Core/HW/GCPadEmu.cpp b/Source/Core/Core/HW/GCPadEmu.cpp
index c0d6836f7d..a797e32fa3 100644
--- a/Source/Core/Core/HW/GCPadEmu.cpp
+++ b/Source/Core/Core/HW/GCPadEmu.cpp
@@ -68,7 +68,7 @@ GCPad::GCPad(const unsigned int index) : m_index(index)
groups.emplace_back(m_main_stick = new ControllerEmu::OctagonAnalogStick(
"Main Stick", _trans("Control Stick"), main_gate_radius));
- constexpr auto c_gate_radius = ControlState(C_STICK_GATE_RADIUS) / GCPadStatus::MAIN_STICK_RADIUS;
+ constexpr auto c_gate_radius = ControlState(C_STICK_GATE_RADIUS) / GCPadStatus::C_STICK_RADIUS;
groups.emplace_back(m_c_stick = new ControllerEmu::OctagonAnalogStick(
"C-Stick", _trans("C Stick"), c_gate_radius));
@@ -160,23 +160,19 @@ GCPadStatus GCPad::GetInput() const
m_dpad->GetState(&pad.button, dpad_bitmasks);
// sticks
- const ControllerEmu::AnalogStick::StateData main_stick_state = m_main_stick->GetState();
- pad.stickX = static_cast<u8>(GCPadStatus::MAIN_STICK_CENTER_X +
- (main_stick_state.x * GCPadStatus::MAIN_STICK_RADIUS));
- pad.stickY = static_cast<u8>(GCPadStatus::MAIN_STICK_CENTER_Y +
- (main_stick_state.y * GCPadStatus::MAIN_STICK_RADIUS));
-
- const ControllerEmu::AnalogStick::StateData c_stick_state = m_c_stick->GetState();
- pad.substickX = static_cast<u8>(GCPadStatus::C_STICK_CENTER_X +
- (c_stick_state.x * GCPadStatus::C_STICK_RADIUS));
- pad.substickY = static_cast<u8>(GCPadStatus::C_STICK_CENTER_Y +
- (c_stick_state.y * GCPadStatus::C_STICK_RADIUS));
+ const auto main_stick_state = m_main_stick->GetState();
+ pad.stickX = MapFloat<u8>(main_stick_state.x, GCPadStatus::MAIN_STICK_CENTER_X);
+ pad.stickY = MapFloat<u8>(main_stick_state.y, GCPadStatus::MAIN_STICK_CENTER_Y);
+
+ const auto c_stick_state = m_c_stick->GetState();
+ pad.substickX = MapFloat<u8>(c_stick_state.x, GCPadStatus::C_STICK_CENTER_X);
+ pad.substickY = MapFloat<u8>(c_stick_state.y, GCPadStatus::C_STICK_CENTER_Y);
// triggers
std::array<ControlState, 2> triggers;
m_triggers->GetState(&pad.button, trigger_bitmasks, triggers.data());
- pad.triggerLeft = static_cast<u8>(triggers[0] * 0xFF);
- pad.triggerRight = static_cast<u8>(triggers[1] * 0xFF);
+ pad.triggerLeft = MapFloat<u8>(triggers[0], 0);
+ pad.triggerRight = MapFloat<u8>(triggers[1], 0);
return pad;
}
diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h
index 4f734e2824..1cc9f5fd1e 100644
--- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h
+++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h
@@ -4,9 +4,11 @@
#pragma once
+#include <cmath>
#include <memory>
#include <mutex>
#include <string>
+#include <type_traits>
#include <vector>
#include "Common/Common.h"
@@ -50,6 +52,29 @@ public:
std::vector<std::unique_ptr<ControlGroup>> groups;
+ // Maps a float from -1.0..+1.0 to an integer of the provided values.
+ template <typename T, typename F>
+ static T MapFloat(F input_value, T zero_value, T neg_1_value = std::numeric_limits<T>::min(),
+ T pos_1_value = std::numeric_limits<T>::max())
+ {
+ static_assert(std::is_integral<T>(), "T is only sane for int types.");
+ static_assert(std::is_floating_point<F>(), "F is only sane for float types.");
+
+ static_assert(std::numeric_limits<long>::min() <= std::numeric_limits<T>::min() &&
+ std::numeric_limits<long>::max() >= std::numeric_limits<T>::max(),
+ "long is not a superset of T. use of std::lround is not sane.");
+
+ // Here we round when converting from float to int.
+ // After applying our deadzone, resizing, and reshaping math
+ // we sometimes have a near-zero value which is slightly negative. (e.g. -0.0001)
+ // Casting would round down but rounding will yield our "zero_value".
+
+ if (input_value > 0)
+ return T(std::lround((pos_1_value - zero_value) * input_value + zero_value));
+ else
+ return T(std::lround((zero_value - neg_1_value) * input_value + zero_value));
+ }
+
private:
ciface::Core::DeviceQualifier m_default_device;
bool m_default_device_is_connected{false};