mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
ControllerEmu: Add new "input override" system
This commit is contained in:
parent
cb6d476538
commit
cb16d20f2d
@ -138,14 +138,15 @@ GCPadStatus GCPad::GetInput() const
|
|||||||
const auto lock = GetStateLock();
|
const auto lock = GetStateLock();
|
||||||
GCPadStatus pad = {};
|
GCPadStatus pad = {};
|
||||||
|
|
||||||
if (!(m_always_connected_setting.GetValue() || IsDefaultDeviceConnected()))
|
if (!(m_always_connected_setting.GetValue() || IsDefaultDeviceConnected() ||
|
||||||
|
m_input_override_function))
|
||||||
{
|
{
|
||||||
pad.isConnected = false;
|
pad.isConnected = false;
|
||||||
return pad;
|
return pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
m_buttons->GetState(&pad.button, button_bitmasks);
|
m_buttons->GetState(&pad.button, button_bitmasks, m_input_override_function);
|
||||||
|
|
||||||
// set analog A/B analog to full or w/e, prolly not needed
|
// set analog A/B analog to full or w/e, prolly not needed
|
||||||
if (pad.button & PAD_BUTTON_A)
|
if (pad.button & PAD_BUTTON_A)
|
||||||
@ -154,20 +155,20 @@ GCPadStatus GCPad::GetInput() const
|
|||||||
pad.analogB = 0xFF;
|
pad.analogB = 0xFF;
|
||||||
|
|
||||||
// dpad
|
// dpad
|
||||||
m_dpad->GetState(&pad.button, dpad_bitmasks);
|
m_dpad->GetState(&pad.button, dpad_bitmasks, m_input_override_function);
|
||||||
|
|
||||||
// sticks
|
// sticks
|
||||||
const auto main_stick_state = m_main_stick->GetState();
|
const auto main_stick_state = m_main_stick->GetState(m_input_override_function);
|
||||||
pad.stickX = MapFloat<u8>(main_stick_state.x, GCPadStatus::MAIN_STICK_CENTER_X, 1);
|
pad.stickX = MapFloat<u8>(main_stick_state.x, GCPadStatus::MAIN_STICK_CENTER_X, 1);
|
||||||
pad.stickY = MapFloat<u8>(main_stick_state.y, GCPadStatus::MAIN_STICK_CENTER_Y, 1);
|
pad.stickY = MapFloat<u8>(main_stick_state.y, GCPadStatus::MAIN_STICK_CENTER_Y, 1);
|
||||||
|
|
||||||
const auto c_stick_state = m_c_stick->GetState();
|
const auto c_stick_state = m_c_stick->GetState(m_input_override_function);
|
||||||
pad.substickX = MapFloat<u8>(c_stick_state.x, GCPadStatus::C_STICK_CENTER_X, 1);
|
pad.substickX = MapFloat<u8>(c_stick_state.x, GCPadStatus::C_STICK_CENTER_X, 1);
|
||||||
pad.substickY = MapFloat<u8>(c_stick_state.y, GCPadStatus::C_STICK_CENTER_Y, 1);
|
pad.substickY = MapFloat<u8>(c_stick_state.y, GCPadStatus::C_STICK_CENTER_Y, 1);
|
||||||
|
|
||||||
// triggers
|
// triggers
|
||||||
std::array<ControlState, 2> triggers;
|
std::array<ControlState, 2> triggers;
|
||||||
m_triggers->GetState(&pad.button, trigger_bitmasks, triggers.data());
|
m_triggers->GetState(&pad.button, trigger_bitmasks, triggers.data(), m_input_override_function);
|
||||||
pad.triggerLeft = MapFloat<u8>(triggers[0], 0);
|
pad.triggerLeft = MapFloat<u8>(triggers[0], 0);
|
||||||
pad.triggerRight = MapFloat<u8>(triggers[1], 0);
|
pad.triggerRight = MapFloat<u8>(triggers[1], 0);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
#include "Core/Config/SYSCONFSettings.h"
|
#include "Core/Config/SYSCONFSettings.h"
|
||||||
@ -221,9 +222,10 @@ WiimoteCommon::AccelData ConvertAccelData(const Common::Vec3& accel, u16 zero_g,
|
|||||||
u16(std::clamp(std::lround(scaled_accel.z + zero_g), 0l, MAX_VALUE))});
|
u16(std::clamp(std::lround(scaled_accel.z + zero_g), 0l, MAX_VALUE))});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmulatePoint(MotionState* state, ControllerEmu::Cursor* ir_group, float time_elapsed)
|
void EmulatePoint(MotionState* state, ControllerEmu::Cursor* ir_group,
|
||||||
|
const ControllerEmu::InputOverrideFunction& override_func, float time_elapsed)
|
||||||
{
|
{
|
||||||
const auto cursor = ir_group->GetState(true);
|
const auto cursor = ir_group->GetState(true, override_func);
|
||||||
|
|
||||||
if (!cursor.IsVisible())
|
if (!cursor.IsVisible())
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "InputCommon/ControllerEmu/ControlGroup/IMUCursor.h"
|
#include "InputCommon/ControllerEmu/ControlGroup/IMUCursor.h"
|
||||||
#include "InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.h"
|
#include "InputCommon/ControllerEmu/ControlGroup/IMUGyroscope.h"
|
||||||
#include "InputCommon/ControllerEmu/ControlGroup/Tilt.h"
|
#include "InputCommon/ControllerEmu/ControlGroup/Tilt.h"
|
||||||
|
#include "InputCommon/ControllerEmu/ControllerEmu.h"
|
||||||
|
|
||||||
namespace WiimoteEmu
|
namespace WiimoteEmu
|
||||||
{
|
{
|
||||||
@ -81,7 +82,8 @@ void ApproachAngleWithAccel(RotationalState* state, const Common::Vec3& target,
|
|||||||
void EmulateShake(PositionalState* state, ControllerEmu::Shake* shake_group, float time_elapsed);
|
void EmulateShake(PositionalState* state, ControllerEmu::Shake* shake_group, float time_elapsed);
|
||||||
void EmulateTilt(RotationalState* state, ControllerEmu::Tilt* tilt_group, float time_elapsed);
|
void EmulateTilt(RotationalState* state, ControllerEmu::Tilt* tilt_group, float time_elapsed);
|
||||||
void EmulateSwing(MotionState* state, ControllerEmu::Force* swing_group, float time_elapsed);
|
void EmulateSwing(MotionState* state, ControllerEmu::Force* swing_group, float time_elapsed);
|
||||||
void EmulatePoint(MotionState* state, ControllerEmu::Cursor* ir_group, float time_elapsed);
|
void EmulatePoint(MotionState* state, ControllerEmu::Cursor* ir_group,
|
||||||
|
const ControllerEmu::InputOverrideFunction& override_func, float time_elapsed);
|
||||||
void EmulateIMUCursor(IMUCursorState* state, ControllerEmu::IMUCursor* imu_ir_group,
|
void EmulateIMUCursor(IMUCursorState* state, ControllerEmu::IMUCursor* imu_ir_group,
|
||||||
ControllerEmu::IMUAccelerometer* imu_accelerometer_group,
|
ControllerEmu::IMUAccelerometer* imu_accelerometer_group,
|
||||||
ControllerEmu::IMUGyroscope* imu_gyroscope_group, float time_elapsed);
|
ControllerEmu::IMUGyroscope* imu_gyroscope_group, float time_elapsed);
|
||||||
|
@ -113,7 +113,8 @@ void Classic::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// left stick
|
// left stick
|
||||||
{
|
{
|
||||||
const ControllerEmu::AnalogStick::StateData left_stick_state = m_left_stick->GetState();
|
const ControllerEmu::AnalogStick::StateData left_stick_state =
|
||||||
|
m_left_stick->GetState(m_input_override_function);
|
||||||
|
|
||||||
const u8 x = static_cast<u8>(LEFT_STICK_CENTER + (left_stick_state.x * LEFT_STICK_RADIUS));
|
const u8 x = static_cast<u8>(LEFT_STICK_CENTER + (left_stick_state.x * LEFT_STICK_RADIUS));
|
||||||
const u8 y = static_cast<u8>(LEFT_STICK_CENTER + (left_stick_state.y * LEFT_STICK_RADIUS));
|
const u8 y = static_cast<u8>(LEFT_STICK_CENTER + (left_stick_state.y * LEFT_STICK_RADIUS));
|
||||||
@ -123,7 +124,8 @@ void Classic::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// right stick
|
// right stick
|
||||||
{
|
{
|
||||||
const ControllerEmu::AnalogStick::StateData right_stick_data = m_right_stick->GetState();
|
const ControllerEmu::AnalogStick::StateData right_stick_data =
|
||||||
|
m_right_stick->GetState(m_input_override_function);
|
||||||
|
|
||||||
const u8 x = static_cast<u8>(RIGHT_STICK_CENTER + (right_stick_data.x * RIGHT_STICK_RADIUS));
|
const u8 x = static_cast<u8>(RIGHT_STICK_CENTER + (right_stick_data.x * RIGHT_STICK_RADIUS));
|
||||||
const u8 y = static_cast<u8>(RIGHT_STICK_CENTER + (right_stick_data.y * RIGHT_STICK_RADIUS));
|
const u8 y = static_cast<u8>(RIGHT_STICK_CENTER + (right_stick_data.y * RIGHT_STICK_RADIUS));
|
||||||
@ -135,19 +137,20 @@ void Classic::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// triggers
|
// triggers
|
||||||
{
|
{
|
||||||
ControlState trigs[2] = {0, 0};
|
ControlState triggers[2] = {0, 0};
|
||||||
m_triggers->GetState(&buttons, classic_trigger_bitmasks.data(), trigs);
|
m_triggers->GetState(&buttons, classic_trigger_bitmasks.data(), triggers,
|
||||||
|
m_input_override_function);
|
||||||
|
|
||||||
const u8 lt = static_cast<u8>(trigs[0] * TRIGGER_RANGE);
|
const u8 lt = static_cast<u8>(triggers[0] * TRIGGER_RANGE);
|
||||||
const u8 rt = static_cast<u8>(trigs[1] * TRIGGER_RANGE);
|
const u8 rt = static_cast<u8>(triggers[1] * TRIGGER_RANGE);
|
||||||
|
|
||||||
classic_data.SetLeftTrigger(lt);
|
classic_data.SetLeftTrigger(lt);
|
||||||
classic_data.SetRightTrigger(rt);
|
classic_data.SetRightTrigger(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// buttons and dpad
|
// buttons and dpad
|
||||||
m_buttons->GetState(&buttons, classic_button_bitmasks.data());
|
m_buttons->GetState(&buttons, classic_button_bitmasks.data(), m_input_override_function);
|
||||||
m_dpad->GetState(&buttons, classic_dpad_bitmasks.data());
|
m_dpad->GetState(&buttons, classic_dpad_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
classic_data.SetButtons(buttons);
|
classic_data.SetButtons(buttons);
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ void DrawsomeTablet::BuildDesiredExtensionState(DesiredExtensionState* target_st
|
|||||||
constexpr double CENTER_X = (MAX_X + MIN_X) / 2.0;
|
constexpr double CENTER_X = (MAX_X + MIN_X) / 2.0;
|
||||||
constexpr double CENTER_Y = (MAX_Y + MIN_Y) / 2.0;
|
constexpr double CENTER_Y = (MAX_Y + MIN_Y) / 2.0;
|
||||||
|
|
||||||
const auto stylus_state = m_stylus->GetState();
|
const auto stylus_state = m_stylus->GetState(m_input_override_function);
|
||||||
const auto stylus_x = u16(std::lround(CENTER_X + stylus_state.x * (MAX_X - CENTER_X)));
|
const auto stylus_x = u16(std::lround(CENTER_X + stylus_state.x * (MAX_X - CENTER_X)));
|
||||||
const auto stylus_y = u16(std::lround(CENTER_Y + stylus_state.y * (MAX_Y - CENTER_Y)));
|
const auto stylus_y = u16(std::lround(CENTER_Y + stylus_state.y * (MAX_Y - CENTER_Y)));
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ void DrawsomeTablet::BuildDesiredExtensionState(DesiredExtensionState* target_st
|
|||||||
// Pressure (0 - 0x7ff):
|
// Pressure (0 - 0x7ff):
|
||||||
constexpr u16 MAX_PRESSURE = 0x7ff;
|
constexpr u16 MAX_PRESSURE = 0x7ff;
|
||||||
|
|
||||||
const auto touch_state = m_touch->GetState();
|
const auto touch_state = m_touch->GetState(m_input_override_function);
|
||||||
const auto pressure = u16(std::lround(touch_state.data[0] * MAX_PRESSURE));
|
const auto pressure = u16(std::lround(touch_state.data[0] * MAX_PRESSURE));
|
||||||
|
|
||||||
tablet_data.pressure1 = u8(pressure);
|
tablet_data.pressure1 = u8(pressure);
|
||||||
|
@ -84,17 +84,18 @@ void Drums::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
DesiredState& state = target_state->data.emplace<DesiredState>();
|
DesiredState& state = target_state->data.emplace<DesiredState>();
|
||||||
|
|
||||||
{
|
{
|
||||||
const ControllerEmu::AnalogStick::StateData stick_state = m_stick->GetState();
|
const ControllerEmu::AnalogStick::StateData stick_state =
|
||||||
|
m_stick->GetState(m_input_override_function);
|
||||||
|
|
||||||
state.stick_x = MapFloat(stick_state.x, STICK_CENTER, STICK_MIN, STICK_MAX);
|
state.stick_x = MapFloat(stick_state.x, STICK_CENTER, STICK_MIN, STICK_MAX);
|
||||||
state.stick_y = MapFloat(stick_state.y, STICK_CENTER, STICK_MIN, STICK_MAX);
|
state.stick_y = MapFloat(stick_state.y, STICK_CENTER, STICK_MIN, STICK_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.buttons = 0;
|
state.buttons = 0;
|
||||||
m_buttons->GetState(&state.buttons, drum_button_bitmasks.data());
|
m_buttons->GetState(&state.buttons, drum_button_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
state.drum_pads = 0;
|
state.drum_pads = 0;
|
||||||
m_pads->GetState(&state.drum_pads, drum_pad_bitmasks.data());
|
m_pads->GetState(&state.drum_pads, drum_pad_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
state.softness = u8(7 - std::lround(m_hit_strength_setting.GetValue() * 7 / 100));
|
state.softness = u8(7 - std::lround(m_hit_strength_setting.GetValue() * 7 / 100));
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,8 @@ void Guitar::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// stick
|
// stick
|
||||||
{
|
{
|
||||||
const ControllerEmu::AnalogStick::StateData stick_state = m_stick->GetState();
|
const ControllerEmu::AnalogStick::StateData stick_state =
|
||||||
|
m_stick->GetState(m_input_override_function);
|
||||||
|
|
||||||
guitar_data.sx = static_cast<u8>((stick_state.x * STICK_RADIUS) + STICK_CENTER);
|
guitar_data.sx = static_cast<u8>((stick_state.x * STICK_RADIUS) + STICK_CENTER);
|
||||||
guitar_data.sy = static_cast<u8>((stick_state.y * STICK_RADIUS) + STICK_CENTER);
|
guitar_data.sy = static_cast<u8>((stick_state.y * STICK_RADIUS) + STICK_CENTER);
|
||||||
@ -111,7 +112,8 @@ void Guitar::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
if (m_slider_bar->controls[0]->control_ref->BoundCount() &&
|
if (m_slider_bar->controls[0]->control_ref->BoundCount() &&
|
||||||
m_slider_bar->controls[1]->control_ref->BoundCount())
|
m_slider_bar->controls[1]->control_ref->BoundCount())
|
||||||
{
|
{
|
||||||
const ControllerEmu::Slider::StateData slider_data = m_slider_bar->GetState();
|
const ControllerEmu::Slider::StateData slider_data =
|
||||||
|
m_slider_bar->GetState(m_input_override_function);
|
||||||
|
|
||||||
guitar_data.sb = s_slider_bar_control_codes.lower_bound(slider_data.value)->second;
|
guitar_data.sb = s_slider_bar_control_codes.lower_bound(slider_data.value)->second;
|
||||||
}
|
}
|
||||||
@ -122,17 +124,18 @@ void Guitar::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// whammy bar
|
// whammy bar
|
||||||
const ControllerEmu::Triggers::StateData whammy_state = m_whammy->GetState();
|
const ControllerEmu::Triggers::StateData whammy_state =
|
||||||
|
m_whammy->GetState(m_input_override_function);
|
||||||
guitar_data.whammy = static_cast<u8>(whammy_state.data[0] * 0x1F);
|
guitar_data.whammy = static_cast<u8>(whammy_state.data[0] * 0x1F);
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
m_buttons->GetState(&guitar_data.bt, guitar_button_bitmasks.data());
|
m_buttons->GetState(&guitar_data.bt, guitar_button_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
// frets
|
// frets
|
||||||
m_frets->GetState(&guitar_data.bt, guitar_fret_bitmasks.data());
|
m_frets->GetState(&guitar_data.bt, guitar_fret_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
// strum
|
// strum
|
||||||
m_strum->GetState(&guitar_data.bt, guitar_strum_bitmasks.data());
|
m_strum->GetState(&guitar_data.bt, guitar_strum_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
// flip button bits
|
// flip button bits
|
||||||
guitar_data.bt ^= 0xFFFF;
|
guitar_data.bt ^= 0xFFFF;
|
||||||
|
@ -67,29 +67,34 @@ void Nunchuk::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
DataFormat nc_data = {};
|
DataFormat nc_data = {};
|
||||||
|
|
||||||
// stick
|
// stick
|
||||||
const ControllerEmu::AnalogStick::StateData stick_state = m_stick->GetState();
|
bool override_occurred = false;
|
||||||
|
const ControllerEmu::AnalogStick::StateData stick_state =
|
||||||
|
m_stick->GetState(m_input_override_function, &override_occurred);
|
||||||
nc_data.jx = u8(STICK_CENTER + stick_state.x * STICK_RADIUS);
|
nc_data.jx = u8(STICK_CENTER + stick_state.x * STICK_RADIUS);
|
||||||
nc_data.jy = u8(STICK_CENTER + stick_state.y * STICK_RADIUS);
|
nc_data.jy = u8(STICK_CENTER + stick_state.y * STICK_RADIUS);
|
||||||
|
|
||||||
// Some terribly coded games check whether to move with a check like
|
if (!override_occurred)
|
||||||
//
|
|
||||||
// if (x != 0 && y != 0)
|
|
||||||
// do_movement(x, y);
|
|
||||||
//
|
|
||||||
// With keyboard controls, these games break if you simply hit
|
|
||||||
// of the axes. Adjust this if you're hitting one of the axes so that
|
|
||||||
// we slightly tweak the other axis.
|
|
||||||
if (nc_data.jx != STICK_CENTER || nc_data.jy != STICK_CENTER)
|
|
||||||
{
|
{
|
||||||
if (nc_data.jx == STICK_CENTER)
|
// Some terribly coded games check whether to move with a check like
|
||||||
++nc_data.jx;
|
//
|
||||||
if (nc_data.jy == STICK_CENTER)
|
// if (x != 0 && y != 0)
|
||||||
++nc_data.jy;
|
// do_movement(x, y);
|
||||||
|
//
|
||||||
|
// With keyboard controls, these games break if you simply hit one
|
||||||
|
// of the axes. Adjust this if you're hitting one of the axes so that
|
||||||
|
// we slightly tweak the other axis.
|
||||||
|
if (nc_data.jx != STICK_CENTER || nc_data.jy != STICK_CENTER)
|
||||||
|
{
|
||||||
|
if (nc_data.jx == STICK_CENTER)
|
||||||
|
++nc_data.jx;
|
||||||
|
if (nc_data.jy == STICK_CENTER)
|
||||||
|
++nc_data.jy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
u8 buttons = 0;
|
u8 buttons = 0;
|
||||||
m_buttons->GetState(&buttons, nunchuk_button_bitmasks.data());
|
m_buttons->GetState(&buttons, nunchuk_button_bitmasks.data(), m_input_override_function);
|
||||||
nc_data.SetButtons(buttons);
|
nc_data.SetButtons(buttons);
|
||||||
|
|
||||||
// Acceleration data:
|
// Acceleration data:
|
||||||
@ -108,6 +113,8 @@ void Nunchuk::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
// shake
|
// shake
|
||||||
accel += m_shake_state.acceleration;
|
accel += m_shake_state.acceleration;
|
||||||
|
|
||||||
|
accel = Wiimote::OverrideVec3(m_imu_accelerometer, accel, m_input_override_function);
|
||||||
|
|
||||||
// Calibration values are 8-bit but we want 10-bit precision, so << 2.
|
// Calibration values are 8-bit but we want 10-bit precision, so << 2.
|
||||||
const auto acc = ConvertAccelData(accel, ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2);
|
const auto acc = ConvertAccelData(accel, ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2);
|
||||||
nc_data.SetAccel(acc.value);
|
nc_data.SetAccel(acc.value);
|
||||||
|
@ -54,8 +54,8 @@ void TaTaCon::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
{
|
{
|
||||||
DataFormat tatacon_data = {};
|
DataFormat tatacon_data = {};
|
||||||
|
|
||||||
m_center->GetState(&tatacon_data.state, center_bitmasks.data());
|
m_center->GetState(&tatacon_data.state, center_bitmasks.data(), m_input_override_function);
|
||||||
m_rim->GetState(&tatacon_data.state, rim_bitmasks.data());
|
m_rim->GetState(&tatacon_data.state, rim_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
// Flip button bits.
|
// Flip button bits.
|
||||||
tatacon_data.state ^= 0xff;
|
tatacon_data.state ^= 0xff;
|
||||||
|
@ -86,7 +86,8 @@ void Turntable::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// stick
|
// stick
|
||||||
{
|
{
|
||||||
const ControllerEmu::AnalogStick::StateData stick_state = m_stick->GetState();
|
const ControllerEmu::AnalogStick::StateData stick_state =
|
||||||
|
m_stick->GetState(m_input_override_function);
|
||||||
|
|
||||||
tt_data.sx = static_cast<u8>((stick_state.x * STICK_RADIUS) + STICK_CENTER);
|
tt_data.sx = static_cast<u8>((stick_state.x * STICK_RADIUS) + STICK_CENTER);
|
||||||
tt_data.sy = static_cast<u8>((stick_state.y * STICK_RADIUS) + STICK_CENTER);
|
tt_data.sy = static_cast<u8>((stick_state.y * STICK_RADIUS) + STICK_CENTER);
|
||||||
@ -94,7 +95,7 @@ void Turntable::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// left table
|
// left table
|
||||||
{
|
{
|
||||||
const ControllerEmu::Slider::StateData lt = m_left_table->GetState();
|
const ControllerEmu::Slider::StateData lt = m_left_table->GetState(m_input_override_function);
|
||||||
const s8 tt = static_cast<s8>(lt.value * TABLE_RANGE);
|
const s8 tt = static_cast<s8>(lt.value * TABLE_RANGE);
|
||||||
|
|
||||||
tt_data.ltable1 = tt;
|
tt_data.ltable1 = tt;
|
||||||
@ -103,7 +104,7 @@ void Turntable::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// right table
|
// right table
|
||||||
{
|
{
|
||||||
const ControllerEmu::Slider::StateData rt = m_right_table->GetState();
|
const ControllerEmu::Slider::StateData rt = m_right_table->GetState(m_input_override_function);
|
||||||
const s8 tt = static_cast<s8>(rt.value * TABLE_RANGE);
|
const s8 tt = static_cast<s8>(rt.value * TABLE_RANGE);
|
||||||
|
|
||||||
tt_data.rtable1 = tt;
|
tt_data.rtable1 = tt;
|
||||||
@ -114,7 +115,7 @@ void Turntable::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// effect dial
|
// effect dial
|
||||||
{
|
{
|
||||||
const auto dial_state = m_effect_dial->GetState();
|
const auto dial_state = m_effect_dial->GetState(m_input_override_function);
|
||||||
const u8 dial = static_cast<u8>(dial_state.value * EFFECT_DIAL_RANGE) + EFFECT_DIAL_CENTER;
|
const u8 dial = static_cast<u8>(dial_state.value * EFFECT_DIAL_RANGE) + EFFECT_DIAL_CENTER;
|
||||||
|
|
||||||
tt_data.dial1 = dial;
|
tt_data.dial1 = dial;
|
||||||
@ -123,13 +124,13 @@ void Turntable::BuildDesiredExtensionState(DesiredExtensionState* target_state)
|
|||||||
|
|
||||||
// crossfade slider
|
// crossfade slider
|
||||||
{
|
{
|
||||||
const ControllerEmu::Slider::StateData cfs = m_crossfade->GetState();
|
const ControllerEmu::Slider::StateData cfs = m_crossfade->GetState(m_input_override_function);
|
||||||
|
|
||||||
tt_data.slider = static_cast<u8>((cfs.value * CROSSFADE_RANGE) + CROSSFADE_CENTER);
|
tt_data.slider = static_cast<u8>((cfs.value * CROSSFADE_RANGE) + CROSSFADE_CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
m_buttons->GetState(&tt_data.bt, turntable_button_bitmasks.data());
|
m_buttons->GetState(&tt_data.bt, turntable_button_bitmasks.data(), m_input_override_function);
|
||||||
|
|
||||||
// flip button bits :/
|
// flip button bits :/
|
||||||
tt_data.bt ^= (BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE | BUTTON_R_GREEN | BUTTON_R_RED |
|
tt_data.bt ^= (BUTTON_L_GREEN | BUTTON_L_RED | BUTTON_L_BLUE | BUTTON_R_GREEN | BUTTON_R_RED |
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
@ -458,9 +459,10 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state)
|
|||||||
|
|
||||||
// Fetch pressed buttons from user input.
|
// Fetch pressed buttons from user input.
|
||||||
target_state->buttons.hex = 0;
|
target_state->buttons.hex = 0;
|
||||||
m_buttons->GetState(&target_state->buttons.hex, button_bitmasks);
|
m_buttons->GetState(&target_state->buttons.hex, button_bitmasks, m_input_override_function);
|
||||||
m_dpad->GetState(&target_state->buttons.hex,
|
m_dpad->GetState(&target_state->buttons.hex,
|
||||||
IsSideways() ? dpad_sideways_bitmasks : dpad_bitmasks);
|
IsSideways() ? dpad_sideways_bitmasks : dpad_bitmasks,
|
||||||
|
m_input_override_function);
|
||||||
|
|
||||||
// Calculate accelerometer state.
|
// Calculate accelerometer state.
|
||||||
// Calibration values are 8-bit but we want 10-bit precision, so << 2.
|
// Calibration values are 8-bit but we want 10-bit precision, so << 2.
|
||||||
@ -628,9 +630,6 @@ void Wiimote::SendDataReport(const DesiredWiimoteState& target_state)
|
|||||||
std::fill_n(ext_data, ext_size, u8(0xff));
|
std::fill_n(ext_data, ext_size, u8(0xff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Movie::CallWiiInputManip(rpt_builder, m_bt_device_index, m_active_extension,
|
|
||||||
GetExtensionEncryptionKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Movie::CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
|
Movie::CheckWiimoteStatus(m_bt_device_index, rpt_builder, m_active_extension,
|
||||||
@ -651,8 +650,9 @@ ButtonData Wiimote::GetCurrentlyPressedButtons()
|
|||||||
const auto lock = GetStateLock();
|
const auto lock = GetStateLock();
|
||||||
|
|
||||||
ButtonData buttons{};
|
ButtonData buttons{};
|
||||||
m_buttons->GetState(&buttons.hex, button_bitmasks);
|
m_buttons->GetState(&buttons.hex, button_bitmasks, m_input_override_function);
|
||||||
m_dpad->GetState(&buttons.hex, IsSideways() ? dpad_sideways_bitmasks : dpad_bitmasks);
|
m_dpad->GetState(&buttons.hex, IsSideways() ? dpad_sideways_bitmasks : dpad_bitmasks,
|
||||||
|
m_input_override_function);
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
@ -789,7 +789,7 @@ void Wiimote::StepDynamics()
|
|||||||
{
|
{
|
||||||
EmulateSwing(&m_swing_state, m_swing, 1.f / ::Wiimote::UPDATE_FREQ);
|
EmulateSwing(&m_swing_state, m_swing, 1.f / ::Wiimote::UPDATE_FREQ);
|
||||||
EmulateTilt(&m_tilt_state, m_tilt, 1.f / ::Wiimote::UPDATE_FREQ);
|
EmulateTilt(&m_tilt_state, m_tilt, 1.f / ::Wiimote::UPDATE_FREQ);
|
||||||
EmulatePoint(&m_point_state, m_ir, 1.f / ::Wiimote::UPDATE_FREQ);
|
EmulatePoint(&m_point_state, m_ir, m_input_override_function, 1.f / ::Wiimote::UPDATE_FREQ);
|
||||||
EmulateShake(&m_shake_state, m_shake, 1.f / ::Wiimote::UPDATE_FREQ);
|
EmulateShake(&m_shake_state, m_shake, 1.f / ::Wiimote::UPDATE_FREQ);
|
||||||
EmulateIMUCursor(&m_imu_cursor_state, m_imu_ir, m_imu_accelerometer, m_imu_gyroscope,
|
EmulateIMUCursor(&m_imu_cursor_state, m_imu_ir, m_imu_accelerometer, m_imu_gyroscope,
|
||||||
1.f / ::Wiimote::UPDATE_FREQ);
|
1.f / ::Wiimote::UPDATE_FREQ);
|
||||||
@ -831,20 +831,87 @@ Common::Quaternion Wiimote::GetOrientation() const
|
|||||||
Common::Quaternion::RotateX(float(MathUtil::TAU / 4 * IsUpright()));
|
Common::Quaternion::RotateX(float(MathUtil::TAU / 4 * IsUpright()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<Common::Vec3> Wiimote::OverrideVec3(const ControllerEmu::ControlGroup* control_group,
|
||||||
|
std::optional<Common::Vec3> optional_vec) const
|
||||||
|
{
|
||||||
|
bool has_value = optional_vec.has_value();
|
||||||
|
Common::Vec3 vec = has_value ? *optional_vec : Common::Vec3{};
|
||||||
|
|
||||||
|
if (m_input_override_function)
|
||||||
|
{
|
||||||
|
if (const std::optional<ControlState> x_override = m_input_override_function(
|
||||||
|
control_group->name, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE, vec.x))
|
||||||
|
{
|
||||||
|
has_value = true;
|
||||||
|
vec.x = *x_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> y_override = m_input_override_function(
|
||||||
|
control_group->name, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE, vec.y))
|
||||||
|
{
|
||||||
|
has_value = true;
|
||||||
|
vec.y = *y_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> z_override = m_input_override_function(
|
||||||
|
control_group->name, ControllerEmu::ReshapableInput::Z_INPUT_OVERRIDE, vec.z))
|
||||||
|
{
|
||||||
|
has_value = true;
|
||||||
|
vec.z = *z_override;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_value ? std::make_optional(vec) : std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::Vec3 Wiimote::OverrideVec3(const ControllerEmu::ControlGroup* control_group,
|
||||||
|
Common::Vec3 vec) const
|
||||||
|
{
|
||||||
|
return OverrideVec3(control_group, vec, m_input_override_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::Vec3
|
||||||
|
Wiimote::OverrideVec3(const ControllerEmu::ControlGroup* control_group, Common::Vec3 vec,
|
||||||
|
const ControllerEmu::InputOverrideFunction& input_override_function)
|
||||||
|
{
|
||||||
|
if (input_override_function)
|
||||||
|
{
|
||||||
|
if (const std::optional<ControlState> x_override = input_override_function(
|
||||||
|
control_group->name, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE, vec.x))
|
||||||
|
{
|
||||||
|
vec.x = *x_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> y_override = input_override_function(
|
||||||
|
control_group->name, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE, vec.y))
|
||||||
|
{
|
||||||
|
vec.y = *y_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> z_override = input_override_function(
|
||||||
|
control_group->name, ControllerEmu::ReshapableInput::Z_INPUT_OVERRIDE, vec.z))
|
||||||
|
{
|
||||||
|
vec.z = *z_override;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
Common::Vec3 Wiimote::GetTotalAcceleration() const
|
Common::Vec3 Wiimote::GetTotalAcceleration() const
|
||||||
{
|
{
|
||||||
if (const auto accel = m_imu_accelerometer->GetState())
|
const Common::Vec3 default_accel = Common::Vec3(0, 0, float(GRAVITY_ACCELERATION));
|
||||||
return GetAcceleration(*accel);
|
const Common::Vec3 accel = m_imu_accelerometer->GetState().value_or(default_accel);
|
||||||
|
|
||||||
return GetAcceleration();
|
return OverrideVec3(m_imu_accelerometer, GetAcceleration(accel));
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Vec3 Wiimote::GetTotalAngularVelocity() const
|
Common::Vec3 Wiimote::GetTotalAngularVelocity() const
|
||||||
{
|
{
|
||||||
if (const auto ang_vel = m_imu_gyroscope->GetState())
|
const Common::Vec3 default_ang_vel = {};
|
||||||
return GetAngularVelocity(*ang_vel);
|
const Common::Vec3 ang_vel = m_imu_gyroscope->GetState().value_or(default_ang_vel);
|
||||||
|
|
||||||
return GetAngularVelocity();
|
return OverrideVec3(m_imu_gyroscope, GetAngularVelocity(ang_vel));
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Matrix44 Wiimote::GetTotalTransformation() const
|
Common::Matrix44 Wiimote::GetTotalTransformation() const
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Core/HW/WiimoteCommon/WiimoteReport.h"
|
#include "Core/HW/WiimoteCommon/WiimoteReport.h"
|
||||||
@ -146,6 +147,10 @@ public:
|
|||||||
// Active extension number is exposed for TAS.
|
// Active extension number is exposed for TAS.
|
||||||
ExtensionNumber GetActiveExtensionNumber() const;
|
ExtensionNumber GetActiveExtensionNumber() const;
|
||||||
|
|
||||||
|
static Common::Vec3
|
||||||
|
OverrideVec3(const ControllerEmu::ControlGroup* control_group, Common::Vec3 vec,
|
||||||
|
const ControllerEmu::InputOverrideFunction& input_override_function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Used only for error generation:
|
// Used only for error generation:
|
||||||
static constexpr u8 EEPROM_I2C_ADDR = 0x50;
|
static constexpr u8 EEPROM_I2C_ADDR = 0x50;
|
||||||
@ -161,11 +166,10 @@ private:
|
|||||||
void BuildDesiredWiimoteState(DesiredWiimoteState* target_state);
|
void BuildDesiredWiimoteState(DesiredWiimoteState* target_state);
|
||||||
|
|
||||||
// Returns simulated accelerometer data in m/s^2.
|
// Returns simulated accelerometer data in m/s^2.
|
||||||
Common::Vec3 GetAcceleration(
|
Common::Vec3 GetAcceleration(Common::Vec3 extra_acceleration) const;
|
||||||
Common::Vec3 extra_acceleration = Common::Vec3(0, 0, float(GRAVITY_ACCELERATION))) const;
|
|
||||||
|
|
||||||
// Returns simulated gyroscope data in radians/s.
|
// Returns simulated gyroscope data in radians/s.
|
||||||
Common::Vec3 GetAngularVelocity(Common::Vec3 extra_angular_velocity = {}) const;
|
Common::Vec3 GetAngularVelocity(Common::Vec3 extra_angular_velocity) const;
|
||||||
|
|
||||||
// Returns the transformation of the world around the wiimote.
|
// Returns the transformation of the world around the wiimote.
|
||||||
// Used for simulating camera data and for rotating acceleration data.
|
// Used for simulating camera data and for rotating acceleration data.
|
||||||
@ -176,6 +180,10 @@ private:
|
|||||||
// Returns the world rotation from the effects of sideways/upright settings.
|
// Returns the world rotation from the effects of sideways/upright settings.
|
||||||
Common::Quaternion GetOrientation() const;
|
Common::Quaternion GetOrientation() const;
|
||||||
|
|
||||||
|
std::optional<Common::Vec3> OverrideVec3(const ControllerEmu::ControlGroup* control_group,
|
||||||
|
std::optional<Common::Vec3> optional_vec) const;
|
||||||
|
Common::Vec3 OverrideVec3(const ControllerEmu::ControlGroup* control_group,
|
||||||
|
Common::Vec3 vec) const;
|
||||||
Common::Vec3 GetTotalAcceleration() const;
|
Common::Vec3 GetTotalAcceleration() const;
|
||||||
Common::Vec3 GetTotalAngularVelocity() const;
|
Common::Vec3 GetTotalAngularVelocity() const;
|
||||||
Common::Matrix44 GetTotalTransformation() const;
|
Common::Matrix44 GetTotalTransformation() const;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "InputCommon/ControllerEmu/ControlGroup/AnalogStick.h"
|
#include "InputCommon/ControllerEmu/ControlGroup/AnalogStick.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
@ -48,6 +49,34 @@ AnalogStick::StateData AnalogStick::GetState() const
|
|||||||
return GetReshapableState(true);
|
return GetReshapableState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnalogStick::StateData AnalogStick::GetState(const InputOverrideFunction& override_func) const
|
||||||
|
{
|
||||||
|
bool override_occurred = false;
|
||||||
|
return GetState(override_func, &override_occurred);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalogStick::StateData AnalogStick::GetState(const InputOverrideFunction& override_func,
|
||||||
|
bool* override_occurred) const
|
||||||
|
{
|
||||||
|
StateData state = GetState();
|
||||||
|
if (!override_func)
|
||||||
|
return state;
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> x_override = override_func(name, X_INPUT_OVERRIDE, state.x))
|
||||||
|
{
|
||||||
|
state.x = *x_override;
|
||||||
|
*override_occurred = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> y_override = override_func(name, Y_INPUT_OVERRIDE, state.y))
|
||||||
|
{
|
||||||
|
state.y = *y_override;
|
||||||
|
*override_occurred = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
ControlState AnalogStick::GetGateRadiusAtAngle(double ang) const
|
ControlState AnalogStick::GetGateRadiusAtAngle(double ang) const
|
||||||
{
|
{
|
||||||
return m_stick_gate->GetRadiusAtAngle(ang);
|
return m_stick_gate->GetRadiusAtAngle(ang);
|
||||||
|
@ -21,6 +21,8 @@ public:
|
|||||||
ControlState GetGateRadiusAtAngle(double ang) const override;
|
ControlState GetGateRadiusAtAngle(double ang) const override;
|
||||||
|
|
||||||
StateData GetState() const;
|
StateData GetState() const;
|
||||||
|
StateData GetState(const InputOverrideFunction& override_func) const;
|
||||||
|
StateData GetState(const InputOverrideFunction& override_func, bool* override_occurred) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Control* GetModifierInput() const override;
|
Control* GetModifierInput() const override;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "InputCommon/ControlReference/ControlReference.h"
|
#include "InputCommon/ControlReference/ControlReference.h"
|
||||||
@ -24,5 +25,21 @@ public:
|
|||||||
for (auto& control : controls)
|
for (auto& control : controls)
|
||||||
*buttons |= *(bitmasks++) * control->GetState<bool>();
|
*buttons |= *(bitmasks++) * control->GetState<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
void GetState(C* const buttons, const C* bitmasks,
|
||||||
|
const InputOverrideFunction& override_func) const
|
||||||
|
{
|
||||||
|
if (!override_func)
|
||||||
|
return GetState(buttons, bitmasks);
|
||||||
|
|
||||||
|
for (auto& control : controls)
|
||||||
|
{
|
||||||
|
ControlState state = control->GetState();
|
||||||
|
if (std::optional<ControlState> state_override = override_func(name, control->name, state))
|
||||||
|
state = *state_override;
|
||||||
|
*buttons |= *(bitmasks++) * (std::lround(state) > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
@ -5,14 +5,18 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
#include "InputCommon/ControllerEmu/Control/Control.h"
|
#include "InputCommon/ControllerEmu/Control/Control.h"
|
||||||
|
#include "InputCommon/ControllerInterface/CoreDevice.h"
|
||||||
|
|
||||||
namespace ControllerEmu
|
namespace ControllerEmu
|
||||||
{
|
{
|
||||||
@ -27,6 +31,9 @@ class NumericSetting;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class SettingValue;
|
class SettingValue;
|
||||||
|
|
||||||
|
using InputOverrideFunction = std::function<std::optional<ControlState>(
|
||||||
|
const std::string_view group_name, const std::string_view control_name, ControlState state)>;
|
||||||
|
|
||||||
enum class GroupType
|
enum class GroupType
|
||||||
{
|
{
|
||||||
Other,
|
Other,
|
||||||
|
@ -82,15 +82,28 @@ ControlState Cursor::GetGateRadiusAtAngle(double ang) const
|
|||||||
|
|
||||||
Cursor::StateData Cursor::GetState(const bool adjusted)
|
Cursor::StateData Cursor::GetState(const bool adjusted)
|
||||||
{
|
{
|
||||||
if (!adjusted)
|
const ReshapeData input = GetReshapableState(adjusted);
|
||||||
{
|
const StateData state = adjusted ? UpdateState(input) : StateData{input.x, input.y};
|
||||||
const auto raw_input = GetReshapableState(false);
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
return {raw_input.x, raw_input.y};
|
Cursor::StateData Cursor::GetState(const bool adjusted,
|
||||||
}
|
const ControllerEmu::InputOverrideFunction& override_func)
|
||||||
|
{
|
||||||
|
StateData state = GetState(adjusted);
|
||||||
|
if (!override_func)
|
||||||
|
return state;
|
||||||
|
|
||||||
const auto input = GetReshapableState(true);
|
if (const std::optional<ControlState> x_override = override_func(name, X_INPUT_OVERRIDE, state.x))
|
||||||
|
state.x = *x_override;
|
||||||
|
if (const std::optional<ControlState> y_override = override_func(name, Y_INPUT_OVERRIDE, state.y))
|
||||||
|
state.y = *y_override;
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor::StateData Cursor::UpdateState(Cursor::ReshapeData input)
|
||||||
|
{
|
||||||
// TODO: Using system time is ugly.
|
// TODO: Using system time is ugly.
|
||||||
// Kill this after state is moved into wiimote rather than this class.
|
// Kill this after state is moved into wiimote rather than this class.
|
||||||
const auto now = Clock::now();
|
const auto now = Clock::now();
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
|
|
||||||
// Modifies the state
|
// Modifies the state
|
||||||
StateData GetState(bool adjusted);
|
StateData GetState(bool adjusted);
|
||||||
|
StateData GetState(bool adjusted, const ControllerEmu::InputOverrideFunction& override_func);
|
||||||
|
|
||||||
// Yaw movement in radians.
|
// Yaw movement in radians.
|
||||||
ControlState GetTotalYaw() const;
|
ControlState GetTotalYaw() const;
|
||||||
@ -40,6 +41,8 @@ public:
|
|||||||
ControlState GetVerticalOffset() const;
|
ControlState GetVerticalOffset() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Cursor::StateData UpdateState(Cursor::ReshapeData input);
|
||||||
|
|
||||||
// This is used to reduce the cursor speed for relative input
|
// This is used to reduce the cursor speed for relative input
|
||||||
// to something that makes sense with the default range.
|
// to something that makes sense with the default range.
|
||||||
static constexpr double STEP_PER_SEC = 0.01 * 200;
|
static constexpr double STEP_PER_SEC = 0.01 * 200;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h"
|
#include "InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -63,6 +64,53 @@ void MixedTriggers::GetState(u16* const digital, const u16* bitmasks, ControlSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MixedTriggers::GetState(u16* digital, const u16* bitmasks, ControlState* analog,
|
||||||
|
const InputOverrideFunction& override_func, bool adjusted) const
|
||||||
|
{
|
||||||
|
if (!override_func)
|
||||||
|
return GetState(digital, bitmasks, analog, adjusted);
|
||||||
|
|
||||||
|
const ControlState threshold = GetThreshold();
|
||||||
|
ControlState deadzone = GetDeadzone();
|
||||||
|
|
||||||
|
// Return raw values. (used in UI)
|
||||||
|
if (!adjusted)
|
||||||
|
{
|
||||||
|
deadzone = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int trigger_count = int(controls.size() / 2);
|
||||||
|
for (int i = 0; i != trigger_count; ++i)
|
||||||
|
{
|
||||||
|
bool button_bool = false;
|
||||||
|
const ControlState button_value = ApplyDeadzone(controls[i]->GetState(), deadzone);
|
||||||
|
ControlState analog_value = ApplyDeadzone(controls[trigger_count + i]->GetState(), deadzone);
|
||||||
|
|
||||||
|
// Apply threshold:
|
||||||
|
if (button_value > threshold)
|
||||||
|
{
|
||||||
|
analog_value = 1.0;
|
||||||
|
button_bool = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> button_override =
|
||||||
|
override_func(name, controls[i]->name, static_cast<ControlState>(button_bool)))
|
||||||
|
{
|
||||||
|
button_bool = std::lround(*button_override) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const std::optional<ControlState> analog_override =
|
||||||
|
override_func(name, controls[trigger_count + i]->name, analog_value))
|
||||||
|
{
|
||||||
|
analog_value = *analog_override;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button_bool)
|
||||||
|
*digital |= bitmasks[i];
|
||||||
|
analog[i] = std::min(analog_value, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ControlState MixedTriggers::GetDeadzone() const
|
ControlState MixedTriggers::GetDeadzone() const
|
||||||
{
|
{
|
||||||
return m_deadzone_setting.GetValue() / 100;
|
return m_deadzone_setting.GetValue() / 100;
|
||||||
|
@ -17,6 +17,8 @@ public:
|
|||||||
|
|
||||||
void GetState(u16* digital, const u16* bitmasks, ControlState* analog,
|
void GetState(u16* digital, const u16* bitmasks, ControlState* analog,
|
||||||
bool adjusted = true) const;
|
bool adjusted = true) const;
|
||||||
|
void GetState(u16* digital, const u16* bitmasks, ControlState* analog,
|
||||||
|
const InputOverrideFunction& override_func, bool adjusted = true) const;
|
||||||
|
|
||||||
ControlState GetDeadzone() const;
|
ControlState GetDeadzone() const;
|
||||||
ControlState GetThreshold() const;
|
ControlState GetThreshold() const;
|
||||||
|
@ -35,4 +35,21 @@ Slider::StateData Slider::GetState() const
|
|||||||
|
|
||||||
return {std::clamp(ApplyDeadzone(state, deadzone), -1.0, 1.0)};
|
return {std::clamp(ApplyDeadzone(state, deadzone), -1.0, 1.0)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slider::StateData Slider::GetState(const InputOverrideFunction& override_func) const
|
||||||
|
{
|
||||||
|
if (!override_func)
|
||||||
|
return GetState();
|
||||||
|
|
||||||
|
const ControlState deadzone = m_deadzone_setting.GetValue() / 100;
|
||||||
|
ControlState state = controls[1]->GetState() - controls[0]->GetState();
|
||||||
|
|
||||||
|
state = ApplyDeadzone(state, deadzone);
|
||||||
|
|
||||||
|
if (std::optional<ControlState> state_override = override_func(name, X_INPUT_OVERRIDE, state))
|
||||||
|
state = *state_override;
|
||||||
|
|
||||||
|
return {std::clamp(state, -1.0, 1.0)};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
@ -23,6 +23,9 @@ public:
|
|||||||
explicit Slider(const std::string& name_);
|
explicit Slider(const std::string& name_);
|
||||||
|
|
||||||
StateData GetState() const;
|
StateData GetState() const;
|
||||||
|
StateData GetState(const InputOverrideFunction& override_func) const;
|
||||||
|
|
||||||
|
static constexpr const char* X_INPUT_OVERRIDE = "X";
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SettingValue<double> m_deadzone_setting;
|
SettingValue<double> m_deadzone_setting;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
@ -31,4 +32,25 @@ Triggers::StateData Triggers::GetState() const
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Triggers::StateData Triggers::GetState(const InputOverrideFunction& override_func) const
|
||||||
|
{
|
||||||
|
if (!override_func)
|
||||||
|
return GetState();
|
||||||
|
|
||||||
|
const size_t trigger_count = controls.size();
|
||||||
|
const ControlState deadzone = m_deadzone_setting.GetValue() / 100;
|
||||||
|
|
||||||
|
StateData result(trigger_count);
|
||||||
|
for (size_t i = 0; i < trigger_count; ++i)
|
||||||
|
{
|
||||||
|
ControlState state = ApplyDeadzone(controls[i]->GetState(), deadzone);
|
||||||
|
if (std::optional<ControlState> state_override = override_func(name, controls[i]->name, state))
|
||||||
|
state = *state_override;
|
||||||
|
result.data[i] = std::min(state, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
explicit Triggers(const std::string& name);
|
explicit Triggers(const std::string& name);
|
||||||
|
|
||||||
StateData GetState() const;
|
StateData GetState() const;
|
||||||
|
StateData GetState(const InputOverrideFunction& override_func) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SettingValue<double> m_deadzone_setting;
|
SettingValue<double> m_deadzone_setting;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
|
|
||||||
@ -176,4 +177,15 @@ void EmulatedController::LoadDefaults(const ControllerInterface& ciface)
|
|||||||
SetDefaultDevice(default_device_string);
|
SetDefaultDevice(default_device_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmulatedController::SetInputOverrideFunction(InputOverrideFunction override_func)
|
||||||
|
{
|
||||||
|
m_input_override_function = std::move(override_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedController::ClearInputOverrideFunction()
|
||||||
|
{
|
||||||
|
m_input_override_function = {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ControllerEmu
|
} // namespace ControllerEmu
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
#include "InputCommon/ControlReference/ExpressionParser.h"
|
#include "InputCommon/ControlReference/ExpressionParser.h"
|
||||||
|
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||||
#include "InputCommon/ControllerInterface/CoreDevice.h"
|
#include "InputCommon/ControllerInterface/CoreDevice.h"
|
||||||
|
|
||||||
class ControllerInterface;
|
class ControllerInterface;
|
||||||
@ -184,6 +185,9 @@ public:
|
|||||||
void SetDefaultDevice(const std::string& device);
|
void SetDefaultDevice(const std::string& device);
|
||||||
void SetDefaultDevice(ciface::Core::DeviceQualifier devq);
|
void SetDefaultDevice(ciface::Core::DeviceQualifier devq);
|
||||||
|
|
||||||
|
void SetInputOverrideFunction(InputOverrideFunction override_func);
|
||||||
|
void ClearInputOverrideFunction();
|
||||||
|
|
||||||
void UpdateReferences(const ControllerInterface& devi);
|
void UpdateReferences(const ControllerInterface& devi);
|
||||||
void UpdateSingleControlReference(const ControllerInterface& devi, ControlReference* ref);
|
void UpdateSingleControlReference(const ControllerInterface& devi, ControlReference* ref);
|
||||||
|
|
||||||
@ -228,6 +232,8 @@ protected:
|
|||||||
// so theirs won't be used (and thus shouldn't even exist).
|
// so theirs won't be used (and thus shouldn't even exist).
|
||||||
ciface::ExpressionParser::ControlEnvironment::VariableContainer m_expression_vars;
|
ciface::ExpressionParser::ControlEnvironment::VariableContainer m_expression_vars;
|
||||||
|
|
||||||
|
InputOverrideFunction m_input_override_function;
|
||||||
|
|
||||||
void UpdateReferences(ciface::ExpressionParser::ControlEnvironment& env);
|
void UpdateReferences(ciface::ExpressionParser::ControlEnvironment& env);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -106,6 +106,10 @@ public:
|
|||||||
const ReshapeData& GetCenter() const;
|
const ReshapeData& GetCenter() const;
|
||||||
void SetCenter(ReshapeData center);
|
void SetCenter(ReshapeData center);
|
||||||
|
|
||||||
|
static constexpr const char* X_INPUT_OVERRIDE = "X";
|
||||||
|
static constexpr const char* Y_INPUT_OVERRIDE = "Y";
|
||||||
|
static constexpr const char* Z_INPUT_OVERRIDE = "Z";
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ReshapeData Reshape(ControlState x, ControlState y, ControlState modifier = 0.0,
|
ReshapeData Reshape(ControlState x, ControlState y, ControlState modifier = 0.0,
|
||||||
ControlState clamp = 1.0) const;
|
ControlState clamp = 1.0) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user