Merge pull request #6222 from iwubcode/emulated_input_improvements
Emulated wii input improvements
This commit is contained in:
commit
cc6526f553
|
@ -0,0 +1,26 @@
|
|||
# RBKJ13, RBKK69, RBKP69, RBKE69 - Boom Blox
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
|
||||
[OnLoad]
|
||||
# Add memory patches to be loaded once on boot here.
|
||||
|
||||
[OnFrame]
|
||||
# Add memory patches to be applied every frame here.
|
||||
|
||||
[ActionReplay]
|
||||
# Add action replay cheats here.
|
||||
|
||||
[Video_Settings]
|
||||
# Add any video settings here
|
||||
|
||||
[Wiimote.Shake]
|
||||
Soft = 3.0
|
||||
Medium = 4.0
|
||||
Hard = 4.8
|
||||
|
||||
[Wiimote.Swing]
|
||||
Slow = 3.5
|
||||
Medium = 4.8
|
||||
Fast = 6
|
|
@ -0,0 +1,26 @@
|
|||
# RYBP69, RYBE69 - Boom Blox Bash Party
|
||||
|
||||
[Core]
|
||||
# Values set here will override the main Dolphin settings.
|
||||
|
||||
[OnLoad]
|
||||
# Add memory patches to be loaded once on boot here.
|
||||
|
||||
[OnFrame]
|
||||
# Add memory patches to be applied every frame here.
|
||||
|
||||
[ActionReplay]
|
||||
# Add action replay cheats here.
|
||||
|
||||
[Video_Settings]
|
||||
# Add any video settings here
|
||||
|
||||
[Wiimote.Shake]
|
||||
Soft = 3.0
|
||||
Medium = 4.0
|
||||
Hard = 4.8
|
||||
|
||||
[Wiimote.Swing]
|
||||
Slow = 3.5
|
||||
Medium = 4.8
|
||||
Fast = 6
|
|
@ -30,6 +30,7 @@ add_library(core
|
|||
Config/NetplaySettings.cpp
|
||||
Config/SYSCONFSettings.cpp
|
||||
Config/UISettings.cpp
|
||||
Config/WiimoteInputSettings.cpp
|
||||
ConfigLoaders/BaseConfigLoader.cpp
|
||||
ConfigLoaders/GameConfigLoader.cpp
|
||||
ConfigLoaders/IsSettingSaveable.cpp
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Core/Config/WiimoteInputSettings.h"
|
||||
|
||||
namespace Config
|
||||
{
|
||||
// Configuration Information
|
||||
|
||||
// WiimoteInput.Settings
|
||||
|
||||
const ConfigInfo<double> WIIMOTE_INPUT_SWING_INTENSITY_FAST{{System::WiiPad, "Swing", "Fast"}, 4.5};
|
||||
const ConfigInfo<double> WIIMOTE_INPUT_SWING_INTENSITY_MEDIUM{{System::WiiPad, "Swing", "Medium"},
|
||||
2.5};
|
||||
const ConfigInfo<double> WIIMOTE_INPUT_SWING_INTENSITY_SLOW{{System::WiiPad, "Swing", "Slow"}, 1.5};
|
||||
|
||||
const ConfigInfo<double> WIIMOTE_INPUT_SHAKE_INTENSITY_HARD{{System::WiiPad, "Shake", "Hard"}, 5.0};
|
||||
const ConfigInfo<double> WIIMOTE_INPUT_SHAKE_INTENSITY_MEDIUM{{System::WiiPad, "Shake", "Medium"},
|
||||
3.0};
|
||||
const ConfigInfo<double> WIIMOTE_INPUT_SHAKE_INTENSITY_SOFT{{System::WiiPad, "Shake", "Soft"}, 2.0};
|
||||
|
||||
// Dynamic settings
|
||||
const ConfigInfo<int> WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_HELD_FAST{
|
||||
{System::WiiPad, "Dynamic_Swing", "FramesHeldFast"}, 100};
|
||||
const ConfigInfo<int> WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_HELD_SLOW{
|
||||
{System::WiiPad, "Dynamic_Swing", "FramesHeldSlow"}, 30};
|
||||
const ConfigInfo<int> WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_LENGTH{
|
||||
{System::WiiPad, "Dynamic_Swing", "FrameCount"}, 30};
|
||||
|
||||
const ConfigInfo<int> WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_HELD_HARD{
|
||||
{System::WiiPad, "Dynamic_Shake", "FramesHeldHard"}, 45};
|
||||
const ConfigInfo<int> WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_HELD_SOFT{
|
||||
{System::WiiPad, "Dynamic_Shake", "FramesHeldSoft"}, 15};
|
||||
const ConfigInfo<int> WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_LENGTH{
|
||||
{System::WiiPad, "Dynamic_Shake", "FrameCount"}, 30};
|
||||
|
||||
// NunchuckInput.Settings
|
||||
|
||||
const ConfigInfo<double> NUNCHUK_INPUT_SWING_INTENSITY_FAST{
|
||||
{System::WiiPad, "Nunchuk_Swing", "Fast"}, 4.5};
|
||||
const ConfigInfo<double> NUNCHUK_INPUT_SWING_INTENSITY_MEDIUM{
|
||||
{System::WiiPad, "Nunchuk_Swing", "Medium"}, 2.5};
|
||||
const ConfigInfo<double> NUNCHUK_INPUT_SWING_INTENSITY_SLOW{
|
||||
{System::WiiPad, "Nunchuk_Swing", "Slow"}, 1.5};
|
||||
|
||||
const ConfigInfo<double> NUNCHUK_INPUT_SHAKE_INTENSITY_HARD{
|
||||
{System::WiiPad, "Nunchuk_Shake", "Hard"}, 5.0};
|
||||
const ConfigInfo<double> NUNCHUK_INPUT_SHAKE_INTENSITY_MEDIUM{
|
||||
{System::WiiPad, "Nunchuk_Shake", "Medium"}, 3.0};
|
||||
const ConfigInfo<double> NUNCHUK_INPUT_SHAKE_INTENSITY_SOFT{
|
||||
{System::WiiPad, "Nunchuk_Shake", "Soft"}, 2.0};
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
namespace Config
|
||||
{
|
||||
// Configuration Information
|
||||
|
||||
// WiimoteInput.Settings
|
||||
|
||||
extern const ConfigInfo<double> WIIMOTE_INPUT_SWING_INTENSITY_FAST;
|
||||
extern const ConfigInfo<double> WIIMOTE_INPUT_SWING_INTENSITY_MEDIUM;
|
||||
extern const ConfigInfo<double> WIIMOTE_INPUT_SWING_INTENSITY_SLOW;
|
||||
|
||||
extern const ConfigInfo<double> WIIMOTE_INPUT_SHAKE_INTENSITY_HARD;
|
||||
extern const ConfigInfo<double> WIIMOTE_INPUT_SHAKE_INTENSITY_MEDIUM;
|
||||
extern const ConfigInfo<double> WIIMOTE_INPUT_SHAKE_INTENSITY_SOFT;
|
||||
|
||||
// Below settings are for dynamic input only (based on how long the user holds a button)
|
||||
|
||||
extern const ConfigInfo<int>
|
||||
WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_HELD_FAST; // How long button held constitutes a fast swing
|
||||
extern const ConfigInfo<int>
|
||||
WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_HELD_SLOW; // How long button held constitutes a slow swing
|
||||
extern const ConfigInfo<int>
|
||||
WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_LENGTH; // How long to execute the swing
|
||||
|
||||
extern const ConfigInfo<int>
|
||||
WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_HELD_HARD; // How long button held constitutes a hard shake
|
||||
extern const ConfigInfo<int>
|
||||
WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_HELD_SOFT; // How long button held constitutes a soft shake
|
||||
extern const ConfigInfo<int>
|
||||
WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_LENGTH; // How long to execute a shake
|
||||
|
||||
// NunchuckInput.Settings
|
||||
|
||||
extern const ConfigInfo<double> NUNCHUK_INPUT_SWING_INTENSITY_FAST;
|
||||
extern const ConfigInfo<double> NUNCHUK_INPUT_SWING_INTENSITY_MEDIUM;
|
||||
extern const ConfigInfo<double> NUNCHUK_INPUT_SWING_INTENSITY_SLOW;
|
||||
|
||||
extern const ConfigInfo<double> NUNCHUK_INPUT_SHAKE_INTENSITY_HARD;
|
||||
extern const ConfigInfo<double> NUNCHUK_INPUT_SHAKE_INTENSITY_MEDIUM;
|
||||
extern const ConfigInfo<double> NUNCHUK_INPUT_SHAKE_INTENSITY_SOFT;
|
||||
|
||||
} // namespace Config
|
|
@ -56,6 +56,7 @@
|
|||
<ClCompile Include="ConfigLoaders\MovieConfigLoader.cpp" />
|
||||
<ClCompile Include="ConfigLoaders\NetPlayConfigLoader.cpp" />
|
||||
<ClCompile Include="ConfigManager.cpp" />
|
||||
<ClCompile Include="Config\WiimoteInputSettings.cpp" />
|
||||
<ClCompile Include="Core.cpp" />
|
||||
<ClCompile Include="CoreTiming.cpp" />
|
||||
<ClCompile Include="Debugger\Debugger_SymbolMap.cpp" />
|
||||
|
@ -321,6 +322,7 @@
|
|||
<ClInclude Include="ConfigLoaders\NetPlayConfigLoader.h" />
|
||||
<ClInclude Include="ConfigManager.h" />
|
||||
<ClInclude Include="Config\UISettings.h" />
|
||||
<ClInclude Include="Config\WiimoteInputSettings.h" />
|
||||
<ClInclude Include="Core.h" />
|
||||
<ClInclude Include="CoreTiming.h" />
|
||||
<ClInclude Include="Debugger\Debugger_SymbolMap.h" />
|
||||
|
@ -600,4 +602,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -910,6 +910,9 @@
|
|||
<ClCompile Include="Config\UISettings.cpp">
|
||||
<Filter>Config</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Config\WiimoteInputSettings.cpp">
|
||||
<Filter>Config</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BootManager.h" />
|
||||
|
@ -1604,6 +1607,9 @@
|
|||
<ClInclude Include="Config\UISettings.h">
|
||||
<Filter>Config</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Config\WiimoteInputSettings.h">
|
||||
<Filter>Config</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Common/Common.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Core/Config/WiimoteInputSettings.h"
|
||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||
|
||||
#include "InputCommon/ControllerEmu/Control/Input.h"
|
||||
|
@ -42,6 +43,8 @@ Nunchuk::Nunchuk(ExtensionReg& reg) : Attachment(_trans("Nunchuk"), reg)
|
|||
|
||||
// swing
|
||||
groups.emplace_back(m_swing = new ControllerEmu::Force(_trans("Swing")));
|
||||
groups.emplace_back(m_swing_slow = new ControllerEmu::Force("SwingSlow"));
|
||||
groups.emplace_back(m_swing_fast = new ControllerEmu::Force("SwingFast"));
|
||||
|
||||
// tilt
|
||||
groups.emplace_back(m_tilt = new ControllerEmu::Tilt(_trans("Tilt")));
|
||||
|
@ -55,6 +58,16 @@ Nunchuk::Nunchuk(ExtensionReg& reg) : Attachment(_trans("Nunchuk"), reg)
|
|||
// i18n: Refers to a 3D axis (used when mapping motion controls)
|
||||
m_shake->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::Translate, _trans("Z")));
|
||||
|
||||
groups.emplace_back(m_shake_soft = new ControllerEmu::Buttons("ShakeSoft"));
|
||||
m_shake_soft->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "X"));
|
||||
m_shake_soft->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Y"));
|
||||
m_shake_soft->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Z"));
|
||||
|
||||
groups.emplace_back(m_shake_hard = new ControllerEmu::Buttons("ShakeHard"));
|
||||
m_shake_hard->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "X"));
|
||||
m_shake_hard->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Y"));
|
||||
m_shake_hard->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Z"));
|
||||
|
||||
m_id = nunchuk_id;
|
||||
}
|
||||
|
||||
|
@ -91,9 +104,18 @@ void Nunchuk::GetState(u8* const data)
|
|||
EmulateTilt(&accel, m_tilt);
|
||||
|
||||
// swing
|
||||
EmulateSwing(&accel, m_swing);
|
||||
EmulateSwing(&accel, m_swing, Config::Get(Config::NUNCHUK_INPUT_SWING_INTENSITY_MEDIUM));
|
||||
EmulateSwing(&accel, m_swing_slow, Config::Get(Config::NUNCHUK_INPUT_SWING_INTENSITY_SLOW));
|
||||
EmulateSwing(&accel, m_swing_fast, Config::Get(Config::NUNCHUK_INPUT_SWING_INTENSITY_FAST));
|
||||
|
||||
// shake
|
||||
EmulateShake(&accel, m_shake, m_shake_step.data());
|
||||
EmulateShake(&accel, m_shake, Config::Get(Config::NUNCHUK_INPUT_SHAKE_INTENSITY_MEDIUM),
|
||||
m_shake_step.data());
|
||||
EmulateShake(&accel, m_shake_soft, Config::Get(Config::NUNCHUK_INPUT_SHAKE_INTENSITY_SOFT),
|
||||
m_shake_soft_step.data());
|
||||
EmulateShake(&accel, m_shake_hard, Config::Get(Config::NUNCHUK_INPUT_SHAKE_INTENSITY_HARD),
|
||||
m_shake_hard_step.data());
|
||||
|
||||
// buttons
|
||||
m_buttons->GetState(&nc_data.bt.hex, nunchuk_button_bitmasks.data());
|
||||
|
||||
|
|
|
@ -55,12 +55,18 @@ public:
|
|||
private:
|
||||
ControllerEmu::Tilt* m_tilt;
|
||||
ControllerEmu::Force* m_swing;
|
||||
ControllerEmu::Force* m_swing_slow;
|
||||
ControllerEmu::Force* m_swing_fast;
|
||||
|
||||
ControllerEmu::Buttons* m_shake;
|
||||
ControllerEmu::Buttons* m_shake_soft;
|
||||
ControllerEmu::Buttons* m_shake_hard;
|
||||
|
||||
ControllerEmu::Buttons* m_buttons;
|
||||
ControllerEmu::AnalogStick* m_stick;
|
||||
|
||||
std::array<u8, 3> m_shake_step{};
|
||||
std::array<u8, 3> m_shake_soft_step{};
|
||||
std::array<u8, 3> m_shake_hard_step{};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Common/MsgHandler.h"
|
||||
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/Config/WiimoteInputSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Wiimote.h"
|
||||
|
@ -99,15 +100,12 @@ static const ReportFeatures reporting_mode_features[] = {
|
|||
};
|
||||
|
||||
void EmulateShake(AccelData* const accel, ControllerEmu::Buttons* const buttons_group,
|
||||
u8* const shake_step)
|
||||
const double intensity, u8* const shake_step)
|
||||
{
|
||||
// frame count of one up/down shake
|
||||
// < 9 no shake detection in "Wario Land: Shake It"
|
||||
auto const shake_step_max = 15;
|
||||
|
||||
// peak G-force
|
||||
auto const shake_intensity = 3.0;
|
||||
|
||||
// shake is a bitfield of X,Y,Z shake button states
|
||||
static const unsigned int btns[] = {0x01, 0x02, 0x04};
|
||||
unsigned int shake = 0;
|
||||
|
@ -117,7 +115,7 @@ void EmulateShake(AccelData* const accel, ControllerEmu::Buttons* const buttons_
|
|||
{
|
||||
if (shake & (1 << i))
|
||||
{
|
||||
(&(accel->x))[i] = std::sin(TAU * shake_step[i] / shake_step_max) * shake_intensity;
|
||||
(&(accel->x))[i] = std::sin(TAU * shake_step[i] / shake_step_max) * intensity;
|
||||
shake_step[i] = (shake_step[i] + 1) % shake_step_max;
|
||||
}
|
||||
else
|
||||
|
@ -125,6 +123,55 @@ void EmulateShake(AccelData* const accel, ControllerEmu::Buttons* const buttons_
|
|||
}
|
||||
}
|
||||
|
||||
void EmulateDynamicShake(AccelData* const accel, DynamicData& dynamic_data,
|
||||
ControllerEmu::Buttons* const buttons_group,
|
||||
const DynamicConfiguration& config, u8* const shake_step)
|
||||
{
|
||||
// frame count of one up/down shake
|
||||
// < 9 no shake detection in "Wario Land: Shake It"
|
||||
auto const shake_step_max = 15;
|
||||
|
||||
// shake is a bitfield of X,Y,Z shake button states
|
||||
static const unsigned int btns[] = {0x01, 0x02, 0x04};
|
||||
unsigned int shake = 0;
|
||||
buttons_group->GetState(&shake, btns);
|
||||
|
||||
for (int i = 0; i != 3; ++i)
|
||||
{
|
||||
if ((shake & (1 << i)) && dynamic_data.executing_frames_left[i] == 0)
|
||||
{
|
||||
dynamic_data.timing[i]++;
|
||||
}
|
||||
else if (dynamic_data.executing_frames_left[i] > 0)
|
||||
{
|
||||
(&(accel->x))[i] = std::sin(TAU * shake_step[i] / shake_step_max) * dynamic_data.intensity[i];
|
||||
shake_step[i] = (shake_step[i] + 1) % shake_step_max;
|
||||
dynamic_data.executing_frames_left[i]--;
|
||||
}
|
||||
else if (shake == 0 && dynamic_data.timing[i] > 0)
|
||||
{
|
||||
if (dynamic_data.timing[i] > config.frames_needed_for_high_intensity)
|
||||
{
|
||||
dynamic_data.intensity[i] = config.high_intensity;
|
||||
}
|
||||
else if (dynamic_data.timing[i] < config.frames_needed_for_low_intensity)
|
||||
{
|
||||
dynamic_data.intensity[i] = config.low_intensity;
|
||||
}
|
||||
else
|
||||
{
|
||||
dynamic_data.intensity[i] = config.med_intensity;
|
||||
}
|
||||
dynamic_data.timing[i] = 0;
|
||||
dynamic_data.executing_frames_left[i] = config.frames_to_execute;
|
||||
}
|
||||
else
|
||||
{
|
||||
shake_step[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmulateTilt(AccelData* const accel, ControllerEmu::Tilt* const tilt_group, const bool sideways,
|
||||
const bool upright)
|
||||
{
|
||||
|
@ -160,10 +207,8 @@ void EmulateTilt(AccelData* const accel, ControllerEmu::Tilt* const tilt_group,
|
|||
(&accel->x)[fb] = sin(pitch) * sgn[fb];
|
||||
}
|
||||
|
||||
#define SWING_INTENSITY 2.5 //-uncalibrated(aprox) 0x40-calibrated
|
||||
|
||||
void EmulateSwing(AccelData* const accel, ControllerEmu::Force* const swing_group,
|
||||
const bool sideways, const bool upright)
|
||||
const double intensity, const bool sideways, const bool upright)
|
||||
{
|
||||
ControlState swing[3];
|
||||
swing_group->GetState(swing);
|
||||
|
@ -184,7 +229,61 @@ void EmulateSwing(AccelData* const accel, ControllerEmu::Force* const swing_grou
|
|||
g_dir[axis_map[0]] *= -1;
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
(&accel->x)[axis_map[i]] += swing[i] * g_dir[i] * SWING_INTENSITY;
|
||||
(&accel->x)[axis_map[i]] += swing[i] * g_dir[i] * intensity;
|
||||
}
|
||||
|
||||
void EmulateDynamicSwing(AccelData* const accel, DynamicData& dynamic_data,
|
||||
ControllerEmu::Force* const swing_group,
|
||||
const DynamicConfiguration& config, const bool sideways,
|
||||
const bool upright)
|
||||
{
|
||||
ControlState swing[3];
|
||||
swing_group->GetState(swing);
|
||||
|
||||
s8 g_dir[3] = {-1, -1, -1};
|
||||
u8 axis_map[3];
|
||||
|
||||
// determine which axis is which direction
|
||||
axis_map[0] = upright ? (sideways ? 0 : 1) : 2; // up/down
|
||||
axis_map[1] = sideways; // left|right
|
||||
axis_map[2] = upright ? 2 : (sideways ? 0 : 1); // forward/backward
|
||||
|
||||
// some orientations have up as positive, some as negative
|
||||
// same with forward
|
||||
if (sideways && !upright)
|
||||
g_dir[axis_map[2]] *= -1;
|
||||
if (!sideways && upright)
|
||||
g_dir[axis_map[0]] *= -1;
|
||||
|
||||
for (unsigned int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (swing[i] > 0 && dynamic_data.executing_frames_left[i] == 0)
|
||||
{
|
||||
dynamic_data.timing[i]++;
|
||||
}
|
||||
else if (dynamic_data.executing_frames_left[i] > 0)
|
||||
{
|
||||
(&accel->x)[axis_map[i]] += g_dir[i] * dynamic_data.intensity[i];
|
||||
dynamic_data.executing_frames_left[i]--;
|
||||
}
|
||||
else if (swing[i] == 0 && dynamic_data.timing[i] > 0)
|
||||
{
|
||||
if (dynamic_data.timing[i] > config.frames_needed_for_high_intensity)
|
||||
{
|
||||
dynamic_data.intensity[i] = config.high_intensity;
|
||||
}
|
||||
else if (dynamic_data.timing[i] < config.frames_needed_for_low_intensity)
|
||||
{
|
||||
dynamic_data.intensity[i] = config.low_intensity;
|
||||
}
|
||||
else
|
||||
{
|
||||
dynamic_data.intensity[i] = config.med_intensity;
|
||||
}
|
||||
dynamic_data.timing[i] = 0;
|
||||
dynamic_data.executing_frames_left[i] = config.frames_to_execute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const u16 button_bitmasks[] = {
|
||||
|
@ -238,7 +337,11 @@ void Wiimote::Reset()
|
|||
// 0x55 - 0xff: level 4
|
||||
m_status.battery = (u8)(m_battery_setting->GetValue() * 100);
|
||||
|
||||
memset(m_shake_step, 0, sizeof(m_shake_step));
|
||||
m_shake_step = {};
|
||||
m_shake_soft_step = {};
|
||||
m_shake_hard_step = {};
|
||||
m_swing_dynamic_data = {};
|
||||
m_shake_dynamic_data = {};
|
||||
|
||||
// clear read request queue
|
||||
while (!m_read_requests.empty())
|
||||
|
@ -271,6 +374,9 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1
|
|||
|
||||
// swing
|
||||
groups.emplace_back(m_swing = new ControllerEmu::Force(_trans("Swing")));
|
||||
groups.emplace_back(m_swing_slow = new ControllerEmu::Force("SwingSlow"));
|
||||
groups.emplace_back(m_swing_fast = new ControllerEmu::Force("SwingFast"));
|
||||
groups.emplace_back(m_swing_dynamic = new ControllerEmu::Force("Swing Dynamic"));
|
||||
|
||||
// tilt
|
||||
groups.emplace_back(m_tilt = new ControllerEmu::Tilt(_trans("Tilt")));
|
||||
|
@ -284,6 +390,24 @@ Wiimote::Wiimote(const unsigned int index) : m_index(index), ir_sin(0), ir_cos(1
|
|||
// i18n: Refers to a 3D axis (used when mapping motion controls)
|
||||
m_shake->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::Translate, _trans("Z")));
|
||||
|
||||
groups.emplace_back(m_shake_soft = new ControllerEmu::Buttons("ShakeSoft"));
|
||||
m_shake_soft->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "X"));
|
||||
m_shake_soft->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Y"));
|
||||
m_shake_soft->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Z"));
|
||||
|
||||
groups.emplace_back(m_shake_hard = new ControllerEmu::Buttons("ShakeHard"));
|
||||
m_shake_hard->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "X"));
|
||||
m_shake_hard->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Y"));
|
||||
m_shake_hard->controls.emplace_back(new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Z"));
|
||||
|
||||
groups.emplace_back(m_shake_dynamic = new ControllerEmu::Buttons("Shake Dynamic"));
|
||||
m_shake_dynamic->controls.emplace_back(
|
||||
new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "X"));
|
||||
m_shake_dynamic->controls.emplace_back(
|
||||
new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Y"));
|
||||
m_shake_dynamic->controls.emplace_back(
|
||||
new ControllerEmu::Input(ControllerEmu::DoNotTranslate, "Z"));
|
||||
|
||||
// extension
|
||||
groups.emplace_back(m_extension = new ControllerEmu::Extension(_trans("Extension")));
|
||||
m_extension->attachments.emplace_back(new WiimoteEmu::None(m_reg_ext));
|
||||
|
@ -484,8 +608,44 @@ void Wiimote::GetAccelData(u8* const data, const ReportFeatures& rptf)
|
|||
m_upright_setting->GetValue() ^ upright_modifier_toggle ^ upright_modifier_switch;
|
||||
|
||||
EmulateTilt(&m_accel, m_tilt, is_sideways, is_upright);
|
||||
EmulateSwing(&m_accel, m_swing, is_sideways, is_upright);
|
||||
EmulateShake(&m_accel, m_shake, m_shake_step);
|
||||
|
||||
DynamicConfiguration swing_config;
|
||||
swing_config.low_intensity = Config::Get(Config::WIIMOTE_INPUT_SWING_INTENSITY_SLOW);
|
||||
swing_config.med_intensity = Config::Get(Config::WIIMOTE_INPUT_SWING_INTENSITY_MEDIUM);
|
||||
swing_config.high_intensity = Config::Get(Config::WIIMOTE_INPUT_SWING_INTENSITY_FAST);
|
||||
swing_config.frames_needed_for_high_intensity =
|
||||
Config::Get(Config::WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_HELD_FAST);
|
||||
swing_config.frames_needed_for_low_intensity =
|
||||
Config::Get(Config::WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_HELD_SLOW);
|
||||
swing_config.frames_to_execute = Config::Get(Config::WIIMOTE_INPUT_SWING_DYNAMIC_FRAMES_LENGTH);
|
||||
|
||||
EmulateSwing(&m_accel, m_swing, Config::Get(Config::WIIMOTE_INPUT_SWING_INTENSITY_MEDIUM),
|
||||
is_sideways, is_upright);
|
||||
EmulateSwing(&m_accel, m_swing_slow, Config::Get(Config::WIIMOTE_INPUT_SWING_INTENSITY_SLOW),
|
||||
is_sideways, is_upright);
|
||||
EmulateSwing(&m_accel, m_swing_fast, Config::Get(Config::WIIMOTE_INPUT_SWING_INTENSITY_FAST),
|
||||
is_sideways, is_upright);
|
||||
EmulateDynamicSwing(&m_accel, m_swing_dynamic_data, m_swing_dynamic, swing_config, is_sideways,
|
||||
is_upright);
|
||||
|
||||
DynamicConfiguration shake_config;
|
||||
shake_config.low_intensity = Config::Get(Config::WIIMOTE_INPUT_SHAKE_INTENSITY_SOFT);
|
||||
shake_config.med_intensity = Config::Get(Config::WIIMOTE_INPUT_SHAKE_INTENSITY_MEDIUM);
|
||||
shake_config.high_intensity = Config::Get(Config::WIIMOTE_INPUT_SHAKE_INTENSITY_HARD);
|
||||
shake_config.frames_needed_for_high_intensity =
|
||||
Config::Get(Config::WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_HELD_HARD);
|
||||
shake_config.frames_needed_for_low_intensity =
|
||||
Config::Get(Config::WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_HELD_SOFT);
|
||||
shake_config.frames_to_execute = Config::Get(Config::WIIMOTE_INPUT_SHAKE_DYNAMIC_FRAMES_LENGTH);
|
||||
|
||||
EmulateShake(&m_accel, m_shake, Config::Get(Config::WIIMOTE_INPUT_SHAKE_INTENSITY_MEDIUM),
|
||||
m_shake_step.data());
|
||||
EmulateShake(&m_accel, m_shake_soft, Config::Get(Config::WIIMOTE_INPUT_SHAKE_INTENSITY_SOFT),
|
||||
m_shake_soft_step.data());
|
||||
EmulateShake(&m_accel, m_shake_hard, Config::Get(Config::WIIMOTE_INPUT_SHAKE_INTENSITY_HARD),
|
||||
m_shake_hard_step.data());
|
||||
EmulateDynamicShake(&m_accel, m_shake_dynamic_data, m_shake_dynamic, shake_config,
|
||||
m_shake_dynamic_step.data());
|
||||
|
||||
wm_accel& accel = *reinterpret_cast<wm_accel*>(data + rptf.accel);
|
||||
wm_buttons& core = *reinterpret_cast<wm_buttons*>(data + rptf.core);
|
||||
|
@ -562,8 +722,8 @@ void Wiimote::GetIRData(u8* const data, bool use_accel)
|
|||
static const int camHeight = 768;
|
||||
static const double bndup = -0.315447;
|
||||
static const double bnddown = 0.85;
|
||||
static const double bndleft = 0.443364;
|
||||
static const double bndright = -0.443364;
|
||||
static const double bndleft = 0.78820266;
|
||||
static const double bndright = -0.78820266;
|
||||
static const double dist1 = 100.0 / camWidth; // this seems the optimal distance for zelda
|
||||
static const double dist2 = 1.2 * dist1;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
|
@ -123,6 +124,33 @@ struct AccelData
|
|||
double x, y, z;
|
||||
};
|
||||
|
||||
// Used for a dynamic swing or
|
||||
// shake
|
||||
struct DynamicData
|
||||
{
|
||||
std::array<int, 3> timing; // Hold length in frames for each axis
|
||||
std::array<double, 3> intensity; // Swing or shake intensity
|
||||
std::array<int, 3> executing_frames_left; // Number of frames to execute the intensity operation
|
||||
};
|
||||
|
||||
// Used for a dynamic swing or
|
||||
// shake. This is used to pass
|
||||
// in data that defines the dynamic
|
||||
// action
|
||||
struct DynamicConfiguration
|
||||
{
|
||||
double low_intensity;
|
||||
int frames_needed_for_low_intensity;
|
||||
|
||||
double med_intensity;
|
||||
// Frames needed for med intensity can be calculated between high & low
|
||||
|
||||
double high_intensity;
|
||||
int frames_needed_for_high_intensity;
|
||||
|
||||
int frames_to_execute; // How many frames should we execute the action for?
|
||||
};
|
||||
|
||||
struct ADPCMState
|
||||
{
|
||||
s32 predictor, step;
|
||||
|
@ -154,13 +182,22 @@ struct ExtensionReg
|
|||
#pragma pack(pop)
|
||||
|
||||
void EmulateShake(AccelData* const accel_data, ControllerEmu::Buttons* const buttons_group,
|
||||
u8* const shake_step);
|
||||
const double intensity, u8* const shake_step);
|
||||
|
||||
void EmulateDynamicShake(AccelData* const accel, DynamicData& dynamic_data,
|
||||
ControllerEmu::Buttons* const buttons_group,
|
||||
const DynamicConfiguration& config, u8* const shake_step);
|
||||
|
||||
void EmulateTilt(AccelData* const accel, ControllerEmu::Tilt* const tilt_group,
|
||||
const bool sideways = false, const bool upright = false);
|
||||
|
||||
void EmulateSwing(AccelData* const accel, ControllerEmu::Force* const tilt_group,
|
||||
const bool sideways = false, const bool upright = false);
|
||||
const double intensity, const bool sideways = false, const bool upright = false);
|
||||
|
||||
void EmulateDynamicSwing(AccelData* const accel, DynamicData& dynamic_data,
|
||||
ControllerEmu::Force* const swing_group,
|
||||
const DynamicConfiguration& config, const bool sideways = false,
|
||||
const bool upright = false);
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -247,9 +284,15 @@ private:
|
|||
ControllerEmu::Buttons* m_buttons;
|
||||
ControllerEmu::Buttons* m_dpad;
|
||||
ControllerEmu::Buttons* m_shake;
|
||||
ControllerEmu::Buttons* m_shake_soft;
|
||||
ControllerEmu::Buttons* m_shake_hard;
|
||||
ControllerEmu::Buttons* m_shake_dynamic;
|
||||
ControllerEmu::Cursor* m_ir;
|
||||
ControllerEmu::Tilt* m_tilt;
|
||||
ControllerEmu::Force* m_swing;
|
||||
ControllerEmu::Force* m_swing_slow;
|
||||
ControllerEmu::Force* m_swing_fast;
|
||||
ControllerEmu::Force* m_swing_dynamic;
|
||||
ControllerEmu::ControlGroup* m_rumble;
|
||||
ControllerEmu::Output* m_motor;
|
||||
ControllerEmu::Extension* m_extension;
|
||||
|
@ -259,6 +302,9 @@ private:
|
|||
ControllerEmu::NumericSetting* m_battery_setting;
|
||||
ControllerEmu::ModifySettingsButton* m_hotkeys;
|
||||
|
||||
DynamicData m_swing_dynamic_data;
|
||||
DynamicData m_shake_dynamic_data;
|
||||
|
||||
// Wiimote accel data
|
||||
AccelData m_accel;
|
||||
|
||||
|
@ -274,7 +320,10 @@ private:
|
|||
u8 m_reporting_mode;
|
||||
u16 m_reporting_channel;
|
||||
|
||||
u8 m_shake_step[3];
|
||||
std::array<u8, 3> m_shake_step{};
|
||||
std::array<u8, 3> m_shake_soft_step{};
|
||||
std::array<u8, 3> m_shake_hard_step{};
|
||||
std::array<u8, 3> m_shake_dynamic_step{};
|
||||
|
||||
bool m_sensor_bar_on_top;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "InputCommon/GCPadStatus.h"
|
||||
|
||||
// clang-format off
|
||||
constexpr std::array<const char*, 114> s_hotkey_labels{{
|
||||
constexpr std::array<const char*, 130> s_hotkey_labels{{
|
||||
_trans("Open"),
|
||||
_trans("Change Disc"),
|
||||
_trans("Eject Disc"),
|
||||
|
@ -69,6 +69,23 @@ constexpr std::array<const char*, 114> s_hotkey_labels{{
|
|||
_trans("Connect Wii Remote 4"),
|
||||
_trans("Connect Balance Board"),
|
||||
|
||||
_trans("Next Profile for Wii Remote 1"),
|
||||
_trans("Previous Profile for Wii Remote 1"),
|
||||
_trans("Next Game Profile for Wii Remote 1"),
|
||||
_trans("Previous Game Profile for Wii Remote 1"),
|
||||
_trans("Next Profile for Wii Remote 2"),
|
||||
_trans("Previous Profile for Wii Remote 2"),
|
||||
_trans("Next Game Profile for Wii Remote 2"),
|
||||
_trans("Previous Game Profile for Wii Remote 2"),
|
||||
_trans("Next Profile for Wii Remote 3"),
|
||||
_trans("Previous Profile for Wii Remote 3"),
|
||||
_trans("Next Game Profile for Wii Remote 3"),
|
||||
_trans("Previous Game Profile for Wii Remote 3"),
|
||||
_trans("Next Profile for Wii Remote 4"),
|
||||
_trans("Previous Profile for Wii Remote 4"),
|
||||
_trans("Next Game Profile for Wii Remote 4"),
|
||||
_trans("Previous Game Profile for Wii Remote 4"),
|
||||
|
||||
_trans("Toggle Crop"),
|
||||
_trans("Toggle Aspect Ratio"),
|
||||
_trans("Toggle EFB Copies"),
|
||||
|
@ -255,6 +272,7 @@ constexpr std::array<HotkeyGroupInfo, NUM_HOTKEY_GROUPS> s_groups_info = {
|
|||
{_trans("Program Counter"), HK_SHOW_PC, HK_SET_PC},
|
||||
{_trans("Breakpoint"), HK_BP_TOGGLE, HK_MBP_ADD},
|
||||
{_trans("Wii"), HK_TRIGGER_SYNC_BUTTON, HK_BALANCEBOARD_CONNECT},
|
||||
{_trans("Controller Profile"), HK_NEXT_WIIMOTE_PROFILE_1, HK_PREV_GAME_WIIMOTE_PROFILE_4},
|
||||
{_trans("Graphics Toggles"), HK_TOGGLE_CROP, HK_TOGGLE_TEXTURES},
|
||||
{_trans("Internal Resolution"), HK_INCREASE_IR, HK_DECREASE_IR},
|
||||
{_trans("Freelook"), HK_FREELOOK_DECREASE_SPEED, HK_FREELOOK_RESET},
|
||||
|
|
|
@ -67,6 +67,23 @@ enum Hotkey
|
|||
HK_WIIMOTE4_CONNECT,
|
||||
HK_BALANCEBOARD_CONNECT,
|
||||
|
||||
HK_NEXT_WIIMOTE_PROFILE_1,
|
||||
HK_PREV_WIIMOTE_PROFILE_1,
|
||||
HK_NEXT_GAME_WIIMOTE_PROFILE_1,
|
||||
HK_PREV_GAME_WIIMOTE_PROFILE_1,
|
||||
HK_NEXT_WIIMOTE_PROFILE_2,
|
||||
HK_PREV_WIIMOTE_PROFILE_2,
|
||||
HK_NEXT_GAME_WIIMOTE_PROFILE_2,
|
||||
HK_PREV_GAME_WIIMOTE_PROFILE_2,
|
||||
HK_NEXT_WIIMOTE_PROFILE_3,
|
||||
HK_PREV_WIIMOTE_PROFILE_3,
|
||||
HK_NEXT_GAME_WIIMOTE_PROFILE_3,
|
||||
HK_PREV_GAME_WIIMOTE_PROFILE_3,
|
||||
HK_NEXT_WIIMOTE_PROFILE_4,
|
||||
HK_PREV_WIIMOTE_PROFILE_4,
|
||||
HK_NEXT_GAME_WIIMOTE_PROFILE_4,
|
||||
HK_PREV_GAME_WIIMOTE_PROFILE_4,
|
||||
|
||||
HK_TOGGLE_CROP,
|
||||
HK_TOGGLE_AR,
|
||||
HK_TOGGLE_EFBCOPIES,
|
||||
|
@ -166,6 +183,7 @@ enum HotkeyGroup : int
|
|||
HKGP_PC,
|
||||
HKGP_BREAKPOINT,
|
||||
HKGP_WII,
|
||||
HKGP_CONTROLLER_PROFILE,
|
||||
HKGP_GRAPHICS_TOGGLES,
|
||||
HKGP_IR,
|
||||
HKGP_FREELOOK,
|
||||
|
|
|
@ -50,6 +50,7 @@ add_executable(dolphin-emu
|
|||
Config/Mapping/GCPadEmu.cpp
|
||||
Config/Mapping/GCPadWiiUConfigDialog.cpp
|
||||
Config/Mapping/Hotkey3D.cpp
|
||||
Config/Mapping/HotkeyControllerProfile.cpp
|
||||
Config/Mapping/HotkeyDebugging.cpp
|
||||
Config/Mapping/HotkeyGeneral.cpp
|
||||
Config/Mapping/HotkeyGraphics.cpp
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Mapping/HotkeyControllerProfile.h"
|
||||
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "Core/HotkeyManager.h"
|
||||
|
||||
HotkeyControllerProfile::HotkeyControllerProfile(MappingWindow* window) : MappingWidget(window)
|
||||
{
|
||||
CreateMainLayout();
|
||||
}
|
||||
|
||||
void HotkeyControllerProfile::CreateMainLayout()
|
||||
{
|
||||
m_main_layout = new QHBoxLayout();
|
||||
|
||||
m_main_layout->addWidget(CreateGroupBox(
|
||||
tr("Controller Profile"), HotkeyManagerEmu::GetHotkeyGroup(HKGP_CONTROLLER_PROFILE)));
|
||||
|
||||
setLayout(m_main_layout);
|
||||
}
|
||||
|
||||
InputConfig* HotkeyControllerProfile::GetConfig()
|
||||
{
|
||||
return HotkeyManagerEmu::GetConfig();
|
||||
}
|
||||
|
||||
void HotkeyControllerProfile::LoadSettings()
|
||||
{
|
||||
HotkeyManagerEmu::LoadConfig();
|
||||
}
|
||||
|
||||
void HotkeyControllerProfile::SaveSettings()
|
||||
{
|
||||
HotkeyManagerEmu::GetConfig()->SaveConfig();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DolphinQt/Config/Mapping/MappingWidget.h"
|
||||
|
||||
class QHBoxLayout;
|
||||
|
||||
class HotkeyControllerProfile final : public MappingWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HotkeyControllerProfile(MappingWindow* window);
|
||||
|
||||
InputConfig* GetConfig() override;
|
||||
|
||||
private:
|
||||
void LoadSettings() override;
|
||||
void SaveSettings() override;
|
||||
void CreateMainLayout();
|
||||
|
||||
// Main
|
||||
QHBoxLayout* m_main_layout;
|
||||
};
|
|
@ -25,6 +25,7 @@
|
|||
#include "DolphinQt/Config/Mapping/GCMicrophone.h"
|
||||
#include "DolphinQt/Config/Mapping/GCPadEmu.h"
|
||||
#include "DolphinQt/Config/Mapping/Hotkey3D.h"
|
||||
#include "DolphinQt/Config/Mapping/HotkeyControllerProfile.h"
|
||||
#include "DolphinQt/Config/Mapping/HotkeyDebugging.h"
|
||||
#include "DolphinQt/Config/Mapping/HotkeyGeneral.h"
|
||||
#include "DolphinQt/Config/Mapping/HotkeyGraphics.h"
|
||||
|
@ -316,6 +317,7 @@ void MappingWindow::SetMappingType(MappingWindow::Type type)
|
|||
AddWidget(tr("Debugging"), new HotkeyDebugging(this));
|
||||
|
||||
AddWidget(tr("Wii and Wii Remote"), new HotkeyWii(this));
|
||||
AddWidget(tr("Controller Profile"), new HotkeyControllerProfile(this));
|
||||
AddWidget(tr("Graphics"), new HotkeyGraphics(this));
|
||||
AddWidget(tr("3D"), new Hotkey3D(this));
|
||||
AddWidget(tr("Save and Load State"), new HotkeyStates(this));
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
<QtMoc Include="Config\Mapping\GCPadEmu.h" />
|
||||
<QtMoc Include="Config\Mapping\GCPadWiiUConfigDialog.h" />
|
||||
<QtMoc Include="Config\Mapping\Hotkey3D.h" />
|
||||
<QtMoc Include="Config\Mapping\HotkeyControllerProfile.h" />
|
||||
<QtMoc Include="Config\Mapping\HotkeyDebugging.h" />
|
||||
<QtMoc Include="Config\Mapping\HotkeyGeneral.h" />
|
||||
<QtMoc Include="Config\Mapping\HotkeyGraphics.h" />
|
||||
|
@ -204,6 +205,7 @@
|
|||
<ClCompile Include="$(QtMocOutPrefix)HacksWidget.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)Host.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)Hotkey3D.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)HotkeyControllerProfile.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)HotkeyDebugging.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)HotkeyGeneral.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)HotkeyGraphics.cpp" />
|
||||
|
@ -285,6 +287,7 @@
|
|||
<ClCompile Include="Config\Mapping\GCPadEmu.cpp" />
|
||||
<ClCompile Include="Config\Mapping\GCPadWiiUConfigDialog.cpp" />
|
||||
<ClCompile Include="Config\Mapping\Hotkey3D.cpp" />
|
||||
<ClCompile Include="Config\Mapping\HotkeyControllerProfile.cpp" />
|
||||
<ClCompile Include="Config\Mapping\HotkeyDebugging.cpp" />
|
||||
<ClCompile Include="Config\Mapping\HotkeyGeneral.cpp" />
|
||||
<ClCompile Include="Config\Mapping\HotkeyGraphics.cpp" />
|
||||
|
|
|
@ -240,6 +240,46 @@ void HotkeyScheduler::Run()
|
|||
emit ConnectWiiRemote(wiimote_id);
|
||||
}
|
||||
|
||||
if (IsHotkey(HK_PREV_WIIMOTE_PROFILE_1))
|
||||
m_profile_cycler.PreviousWiimoteProfile(0);
|
||||
else if (IsHotkey(HK_NEXT_WIIMOTE_PROFILE_1))
|
||||
m_profile_cycler.NextWiimoteProfile(0);
|
||||
|
||||
if (IsHotkey(HK_PREV_WIIMOTE_PROFILE_2))
|
||||
m_profile_cycler.PreviousWiimoteProfile(1);
|
||||
else if (IsHotkey(HK_NEXT_WIIMOTE_PROFILE_2))
|
||||
m_profile_cycler.NextWiimoteProfile(1);
|
||||
|
||||
if (IsHotkey(HK_PREV_WIIMOTE_PROFILE_3))
|
||||
m_profile_cycler.PreviousWiimoteProfile(2);
|
||||
else if (IsHotkey(HK_NEXT_WIIMOTE_PROFILE_3))
|
||||
m_profile_cycler.NextWiimoteProfile(2);
|
||||
|
||||
if (IsHotkey(HK_PREV_WIIMOTE_PROFILE_4))
|
||||
m_profile_cycler.PreviousWiimoteProfile(3);
|
||||
else if (IsHotkey(HK_NEXT_WIIMOTE_PROFILE_4))
|
||||
m_profile_cycler.NextWiimoteProfile(3);
|
||||
|
||||
if (IsHotkey(HK_PREV_GAME_WIIMOTE_PROFILE_1))
|
||||
m_profile_cycler.PreviousWiimoteProfileForGame(0);
|
||||
else if (IsHotkey(HK_NEXT_GAME_WIIMOTE_PROFILE_1))
|
||||
m_profile_cycler.NextWiimoteProfileForGame(0);
|
||||
|
||||
if (IsHotkey(HK_PREV_GAME_WIIMOTE_PROFILE_2))
|
||||
m_profile_cycler.PreviousWiimoteProfileForGame(1);
|
||||
else if (IsHotkey(HK_NEXT_GAME_WIIMOTE_PROFILE_2))
|
||||
m_profile_cycler.NextWiimoteProfileForGame(1);
|
||||
|
||||
if (IsHotkey(HK_PREV_GAME_WIIMOTE_PROFILE_3))
|
||||
m_profile_cycler.PreviousWiimoteProfileForGame(2);
|
||||
else if (IsHotkey(HK_NEXT_GAME_WIIMOTE_PROFILE_3))
|
||||
m_profile_cycler.NextWiimoteProfileForGame(2);
|
||||
|
||||
if (IsHotkey(HK_PREV_GAME_WIIMOTE_PROFILE_4))
|
||||
m_profile_cycler.PreviousWiimoteProfileForGame(3);
|
||||
else if (IsHotkey(HK_NEXT_GAME_WIIMOTE_PROFILE_4))
|
||||
m_profile_cycler.NextWiimoteProfileForGame(3);
|
||||
|
||||
const auto show_msg = [](OSDMessage message) {
|
||||
if (g_renderer)
|
||||
g_renderer->ShowOSDMessage(message);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <QObject>
|
||||
|
||||
#include "Common/Flag.h"
|
||||
#include "InputCommon/InputProfile.h"
|
||||
|
||||
class HotkeyScheduler : public QObject
|
||||
{
|
||||
|
@ -64,4 +65,6 @@ private:
|
|||
|
||||
Common::Flag m_stop_requested;
|
||||
std::thread m_thread;
|
||||
|
||||
InputProfile::ProfileCycler m_profile_cycler;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
add_library(inputcommon
|
||||
InputConfig.cpp
|
||||
InputProfile.cpp
|
||||
ControllerEmu/ControllerEmu.cpp
|
||||
ControllerEmu/Control/Control.cpp
|
||||
ControllerEmu/Control/Input.cpp
|
||||
|
|
|
@ -40,10 +40,7 @@ void Force::GetState(ControlState* axis)
|
|||
controls[i + 1]->control_ref->State() - controls[i]->control_ref->State();
|
||||
if (fabs(state) > deadzone)
|
||||
tmpf = ((state - (deadzone * sign(state))) / (1 - deadzone));
|
||||
|
||||
ControlState& ax = m_swing[i >> 1];
|
||||
*axis++ = (tmpf - ax);
|
||||
ax = tmpf;
|
||||
*axis++ = tmpf;
|
||||
}
|
||||
}
|
||||
} // namespace ControllerEmu
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
<DisableSpecificWarnings>4200;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputConfig.cpp" />
|
||||
<ClCompile Include="InputProfile.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ControllerEmu\ControllerEmu.h" />
|
||||
|
@ -105,6 +106,7 @@
|
|||
<ClInclude Include="GCAdapter.h" />
|
||||
<ClInclude Include="GCPadStatus.h" />
|
||||
<ClInclude Include="InputConfig.h" />
|
||||
<ClInclude Include="InputProfile.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
<ClCompile Include="ControlReference\ControlReference.cpp">
|
||||
<Filter>ControllerInterface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputProfile.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="GCAdapter.h" />
|
||||
|
@ -202,6 +203,7 @@
|
|||
<ClInclude Include="ControlReference\ControlReference.h">
|
||||
<Filter>ControllerInterface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InputProfile.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
|
|
@ -7,12 +7,15 @@
|
|||
#include "Common/FileUtil.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Wiimote.h"
|
||||
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
|
||||
#include "InputCommon/ControllerEmu/ControllerEmu.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
#include "InputCommon/InputProfile.h"
|
||||
|
||||
InputConfig::InputConfig(const std::string& ini_name, const std::string& gui_name,
|
||||
const std::string& profile_name)
|
||||
|
@ -51,17 +54,24 @@ bool InputConfig::LoadConfig(bool isGC)
|
|||
{
|
||||
if (control_section->Exists(type + "Profile" + num[i]))
|
||||
{
|
||||
if (control_section->Get(type + "Profile" + num[i], &profile[i]))
|
||||
std::string profile_setting;
|
||||
if (control_section->Get(type + "Profile" + num[i], &profile_setting))
|
||||
{
|
||||
if (File::Exists(File::GetUserPath(D_CONFIG_IDX) + path + profile[i] + ".ini"))
|
||||
{
|
||||
useProfile[i] = true;
|
||||
}
|
||||
else
|
||||
auto profiles = InputProfile::GetProfilesFromSetting(
|
||||
profile_setting, File::GetUserPath(D_CONFIG_IDX) + path);
|
||||
|
||||
if (profiles.empty())
|
||||
{
|
||||
const std::string error =
|
||||
"No profiles found for game setting '" + profile_setting + "'";
|
||||
// TODO: PanicAlert shouldn't be used for this.
|
||||
PanicAlertT("Selected controller profile does not exist");
|
||||
PanicAlertT("%s", error.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Use the first profile by default
|
||||
profile[i] = profiles[0];
|
||||
useProfile[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +85,14 @@ bool InputConfig::LoadConfig(bool isGC)
|
|||
// Load settings from ini
|
||||
if (useProfile[n])
|
||||
{
|
||||
std::string base;
|
||||
SplitPath(profile[n], nullptr, &base, nullptr);
|
||||
Core::DisplayMessage("Loading game specific input profile '" + base + "' for device '" +
|
||||
controller->GetName() + "'",
|
||||
6000);
|
||||
|
||||
IniFile profile_ini;
|
||||
profile_ini.Load(File::GetUserPath(D_CONFIG_IDX) + path + profile[n] + ".ini");
|
||||
profile_ini.Load(profile[n]);
|
||||
controller->LoadConfig(profile_ini.GetOrCreateSection("Profile"));
|
||||
}
|
||||
else
|
||||
|
@ -128,6 +144,11 @@ bool InputConfig::ControllersNeedToBeCreated() const
|
|||
return m_controllers.empty();
|
||||
}
|
||||
|
||||
std::size_t InputConfig::GetControllerCount() const
|
||||
{
|
||||
return m_controllers.size();
|
||||
}
|
||||
|
||||
bool InputConfig::IsControllerControlledByGamepadDevice(int index) const
|
||||
{
|
||||
if (static_cast<size_t>(index) >= m_controllers.size())
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
|
||||
std::string GetGUIName() const { return m_gui_name; }
|
||||
std::string GetProfileName() const { return m_profile_name; }
|
||||
std::size_t GetControllerCount() const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ControllerEmu::EmulatedController>> m_controllers;
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/FileSearch.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Wiimote.h"
|
||||
#include "Core/HotkeyManager.h"
|
||||
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
#include "InputCommon/InputProfile.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace InputProfile
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr int display_message_ms = 3000;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetProfilesFromSetting(const std::string& setting, const std::string& root)
|
||||
{
|
||||
const auto& setting_choices = SplitString(setting, ',');
|
||||
|
||||
std::vector<std::string> result;
|
||||
for (const std::string& setting_choice : setting_choices)
|
||||
{
|
||||
const std::string path = root + StripSpaces(setting_choice);
|
||||
if (File::IsDirectory(path))
|
||||
{
|
||||
const auto files_under_directory = Common::DoFileSearch({path}, {".ini"}, true);
|
||||
result.insert(result.end(), files_under_directory.begin(), files_under_directory.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string file_path = path + ".ini";
|
||||
if (File::Exists(file_path))
|
||||
{
|
||||
result.push_back(file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> ProfileCycler::GetProfilesForDevice(InputConfig* device_configuration)
|
||||
{
|
||||
const std::string device_profile_root_location(File::GetUserPath(D_CONFIG_IDX) + "Profiles/" +
|
||||
device_configuration->GetProfileName());
|
||||
return Common::DoFileSearch({device_profile_root_location}, {".ini"}, true);
|
||||
}
|
||||
|
||||
std::string ProfileCycler::GetProfile(CycleDirection cycle_direction, int& profile_index,
|
||||
const std::vector<std::string>& profiles)
|
||||
{
|
||||
// update the index and bind it to the number of available strings
|
||||
auto positive_modulo = [](int& i, int n) { i = (i % n + n) % n; };
|
||||
profile_index += static_cast<int>(cycle_direction);
|
||||
positive_modulo(profile_index, static_cast<int>(profiles.size()));
|
||||
|
||||
return profiles[profile_index];
|
||||
}
|
||||
|
||||
void ProfileCycler::UpdateToProfile(const std::string& profile_filename,
|
||||
ControllerEmu::EmulatedController* controller)
|
||||
{
|
||||
std::string base;
|
||||
SplitPath(profile_filename, nullptr, &base, nullptr);
|
||||
|
||||
IniFile ini_file;
|
||||
if (ini_file.Load(profile_filename))
|
||||
{
|
||||
Core::DisplayMessage("Loading input profile '" + base + "' for device '" +
|
||||
controller->GetName() + "'",
|
||||
display_message_ms);
|
||||
controller->LoadConfig(ini_file.GetOrCreateSection("Profile"));
|
||||
controller->UpdateReferences(g_controller_interface);
|
||||
}
|
||||
else
|
||||
{
|
||||
Core::DisplayMessage("Unable to load input profile '" + base + "' for device '" +
|
||||
controller->GetName() + "'",
|
||||
display_message_ms);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
ProfileCycler::GetMatchingProfilesFromSetting(const std::string& setting,
|
||||
const std::vector<std::string>& profiles,
|
||||
InputConfig* device_configuration)
|
||||
{
|
||||
const std::string device_profile_root_location(File::GetUserPath(D_CONFIG_IDX) + "Profiles/" +
|
||||
device_configuration->GetProfileName() + "/");
|
||||
|
||||
const auto& profiles_from_setting = GetProfilesFromSetting(setting, device_profile_root_location);
|
||||
if (profiles_from_setting.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string> result;
|
||||
std::set_intersection(profiles.begin(), profiles.end(), profiles_from_setting.begin(),
|
||||
profiles_from_setting.end(), std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void ProfileCycler::CycleProfile(CycleDirection cycle_direction, InputConfig* device_configuration,
|
||||
int& profile_index, int controller_index)
|
||||
{
|
||||
const auto& profiles = GetProfilesForDevice(device_configuration);
|
||||
if (profiles.empty())
|
||||
{
|
||||
Core::DisplayMessage("No input profiles found", display_message_ms);
|
||||
return;
|
||||
}
|
||||
const std::string profile = GetProfile(cycle_direction, profile_index, profiles);
|
||||
|
||||
auto* controller = device_configuration->GetController(controller_index);
|
||||
if (controller)
|
||||
{
|
||||
UpdateToProfile(profile, controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
Core::DisplayMessage("No controller found for index: " + std::to_string(controller_index),
|
||||
display_message_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileCycler::CycleProfileForGame(CycleDirection cycle_direction,
|
||||
InputConfig* device_configuration, int& profile_index,
|
||||
const std::string& setting, int controller_index)
|
||||
{
|
||||
const auto& profiles = GetProfilesForDevice(device_configuration);
|
||||
if (profiles.empty())
|
||||
{
|
||||
Core::DisplayMessage("No input profiles found", display_message_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
if (setting.empty())
|
||||
{
|
||||
Core::DisplayMessage("No setting found for game", display_message_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& profiles_for_game =
|
||||
GetMatchingProfilesFromSetting(setting, profiles, device_configuration);
|
||||
if (profiles_for_game.empty())
|
||||
{
|
||||
Core::DisplayMessage("No input profiles found for game", display_message_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string profile = GetProfile(cycle_direction, profile_index, profiles_for_game);
|
||||
|
||||
auto* controller = device_configuration->GetController(controller_index);
|
||||
if (controller)
|
||||
{
|
||||
UpdateToProfile(profile, controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
Core::DisplayMessage("No controller found for index: " + std::to_string(controller_index),
|
||||
display_message_ms);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ProfileCycler::GetWiimoteInputProfilesForGame(int controller_index)
|
||||
{
|
||||
IniFile game_ini = SConfig::GetInstance().LoadGameIni();
|
||||
const IniFile::Section* const control_section = game_ini.GetOrCreateSection("Controls");
|
||||
|
||||
std::string result;
|
||||
control_section->Get(StringFromFormat("WiimoteProfile%d", controller_index + 1), &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ProfileCycler::NextWiimoteProfile(int controller_index)
|
||||
{
|
||||
CycleProfile(CycleDirection::Forward, Wiimote::GetConfig(), m_wiimote_profile_index,
|
||||
controller_index);
|
||||
}
|
||||
|
||||
void ProfileCycler::PreviousWiimoteProfile(int controller_index)
|
||||
{
|
||||
CycleProfile(CycleDirection::Backward, Wiimote::GetConfig(), m_wiimote_profile_index,
|
||||
controller_index);
|
||||
}
|
||||
|
||||
void ProfileCycler::NextWiimoteProfileForGame(int controller_index)
|
||||
{
|
||||
CycleProfileForGame(CycleDirection::Forward, Wiimote::GetConfig(), m_wiimote_profile_index,
|
||||
GetWiimoteInputProfilesForGame(controller_index), controller_index);
|
||||
}
|
||||
|
||||
void ProfileCycler::PreviousWiimoteProfileForGame(int controller_index)
|
||||
{
|
||||
CycleProfileForGame(CycleDirection::Backward, Wiimote::GetConfig(), m_wiimote_profile_index,
|
||||
GetWiimoteInputProfilesForGame(controller_index), controller_index);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
class InputConfig;
|
||||
|
||||
namespace ControllerEmu
|
||||
{
|
||||
class EmulatedController;
|
||||
}
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace InputProfile
|
||||
{
|
||||
std::vector<std::string> GetProfilesFromSetting(const std::string& setting,
|
||||
const std::string& root);
|
||||
|
||||
enum class CycleDirection : int
|
||||
{
|
||||
Forward = 1,
|
||||
Backward = -1
|
||||
};
|
||||
|
||||
class ProfileCycler
|
||||
{
|
||||
public:
|
||||
void NextWiimoteProfile(int controller_index);
|
||||
void PreviousWiimoteProfile(int controller_index);
|
||||
void NextWiimoteProfileForGame(int controller_index);
|
||||
void PreviousWiimoteProfileForGame(int controller_index);
|
||||
|
||||
private:
|
||||
void CycleProfile(CycleDirection cycle_direction, InputConfig* device_configuration,
|
||||
int& profile_index, int controller_index);
|
||||
void CycleProfileForGame(CycleDirection cycle_direction, InputConfig* device_configuration,
|
||||
int& profile_index, const std::string& setting, int controller_index);
|
||||
std::vector<std::string> GetProfilesForDevice(InputConfig* device_configuration);
|
||||
std::string GetProfile(CycleDirection cycle_direction, int& profile_index,
|
||||
const std::vector<std::string>& profiles);
|
||||
std::vector<std::string> GetMatchingProfilesFromSetting(const std::string& setting,
|
||||
const std::vector<std::string>& profiles,
|
||||
InputConfig* device_configuration);
|
||||
void UpdateToProfile(const std::string& profile_filename,
|
||||
ControllerEmu::EmulatedController* controller);
|
||||
std::string GetWiimoteInputProfilesForGame(int controller_index);
|
||||
|
||||
int m_wiimote_profile_index = 0;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue