diff options
Diffstat (limited to 'Source/Core/InputCommon')
35 files changed, 1332 insertions, 725 deletions
diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 0c408a6567..b86c0500de 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -1,5 +1,19 @@ set(SRCS InputConfig.cpp ControllerEmu/ControllerEmu.cpp + ControllerEmu/Control/Control.cpp + ControllerEmu/Control/Input.cpp + ControllerEmu/Control/Output.cpp + ControllerEmu/ControlGroup/AnalogStick.cpp + ControllerEmu/ControlGroup/Buttons.cpp + ControllerEmu/ControlGroup/ControlGroup.cpp + ControllerEmu/ControlGroup/Cursor.cpp + ControllerEmu/ControlGroup/Extension.cpp + ControllerEmu/ControlGroup/Force.cpp + ControllerEmu/ControlGroup/MixedTriggers.cpp + ControllerEmu/ControlGroup/ModifySettingsButton.cpp + ControllerEmu/ControlGroup/Slider.cpp + ControllerEmu/ControlGroup/Tilt.cpp + ControllerEmu/ControlGroup/Triggers.cpp ControllerInterface/ControllerInterface.cpp ControllerInterface/Device.cpp ControlReference/ControlReference.cpp diff --git a/Source/Core/InputCommon/ControllerEmu/Control/Control.cpp b/Source/Core/InputCommon/ControllerEmu/Control/Control.cpp new file mode 100644 index 0000000000..00f9a71069 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/Control/Control.cpp @@ -0,0 +1,15 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControlReference/ControlReference.h" + +namespace ControllerEmu +{ +Control::Control(ControlReference* ref, const std::string& name_) : control_ref(ref), name(name_) +{ +} + +Control::~Control() = default; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/Control/Control.h b/Source/Core/InputCommon/ControllerEmu/Control/Control.h new file mode 100644 index 0000000000..ef88ebd328 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/Control/Control.h @@ -0,0 +1,25 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> + +class ControlReference; + +namespace ControllerEmu +{ +class Control +{ +public: + virtual ~Control(); + + std::unique_ptr<ControlReference> const control_ref; + const std::string name; + +protected: + Control(ControlReference* ref, const std::string& name); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/Control/Input.cpp b/Source/Core/InputCommon/ControllerEmu/Control/Input.cpp new file mode 100644 index 0000000000..0f2e400e56 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/Control/Input.cpp @@ -0,0 +1,15 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/Control/Input.h" + +#include <string> +#include "InputCommon/ControlReference/ControlReference.h" + +namespace ControllerEmu +{ +Input::Input(const std::string& name_) : Control(new InputReference, name_) +{ +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/Control/Input.h b/Source/Core/InputCommon/ControllerEmu/Control/Input.h new file mode 100644 index 0000000000..678514736e --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/Control/Input.h @@ -0,0 +1,17 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/Control/Control.h" + +namespace ControllerEmu +{ +class Input : public Control +{ +public: + explicit Input(const std::string& name); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/Control/Output.cpp b/Source/Core/InputCommon/ControllerEmu/Control/Output.cpp new file mode 100644 index 0000000000..24d7b30499 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/Control/Output.cpp @@ -0,0 +1,15 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/Control/Output.h" + +#include <string> +#include "InputCommon/ControlReference/ControlReference.h" + +namespace ControllerEmu +{ +Output::Output(const std::string& name_) : Control(new OutputReference, name_) +{ +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/Control/Output.h b/Source/Core/InputCommon/ControllerEmu/Control/Output.h new file mode 100644 index 0000000000..415c67f7d9 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/Control/Output.h @@ -0,0 +1,17 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/Control/Control.h" + +namespace ControllerEmu +{ +class Output : public Control +{ +public: + explicit Output(const std::string& name); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp new file mode 100644 index 0000000000..8ee7357963 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.cpp @@ -0,0 +1,71 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/AnalogStick.h" + +#include <algorithm> +#include <cmath> +#include <memory> + +#include "Common/Common.h" + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +namespace ControllerEmu +{ +AnalogStick::AnalogStick(const char* const name_, ControlState default_radius) + : AnalogStick(name_, name_, default_radius) +{ +} + +AnalogStick::AnalogStick(const char* const name_, const char* const ui_name_, + ControlState default_radius) + : ControlGroup(name_, ui_name_, GROUP_TYPE_STICK) +{ + for (auto& named_direction : named_directions) + controls.emplace_back(std::make_unique<Input>(named_direction)); + + controls.emplace_back(std::make_unique<Input>(_trans("Modifier"))); + numeric_settings.emplace_back( + std::make_unique<NumericSetting>(_trans("Radius"), default_radius, 0, 100)); + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); +} + +void AnalogStick::GetState(ControlState* const x, ControlState* const y) +{ + ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); + ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); + + ControlState radius = numeric_settings[SETTING_RADIUS]->GetValue(); + ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue(); + ControlState m = controls[4]->control_ref->State(); + + ControlState ang = atan2(yy, xx); + ControlState ang_sin = sin(ang); + ControlState ang_cos = cos(ang); + + ControlState dist = sqrt(xx * xx + yy * yy); + + // dead zone code + dist = std::max(0.0, dist - deadzone); + dist /= (1 - deadzone); + + // radius + dist *= radius; + + // The modifier halves the distance by 50%, which is useful + // for keyboard controls. + if (m) + dist *= 0.5; + + yy = std::max(-1.0, std::min(1.0, ang_sin * dist)); + xx = std::max(-1.0, std::min(1.0, ang_cos * dist)); + + *y = yy; + *x = xx; +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h new file mode 100644 index 0000000000..2d05b6baa4 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/AnalogStick.h @@ -0,0 +1,26 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class AnalogStick : public ControlGroup +{ +public: + enum + { + SETTING_RADIUS, + SETTING_DEADZONE, + }; + + // The GameCube controller and Wiimote attachments have a different default radius + AnalogStick(const char* name, ControlState default_radius); + AnalogStick(const char* name, const char* ui_name, ControlState default_radius); + + void GetState(ControlState* x, ControlState* y); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.cpp new file mode 100644 index 0000000000..55e4532e7a --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.cpp @@ -0,0 +1,24 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h" + +#include <memory> +#include <string> + +#include "Common/Common.h" + +namespace ControllerEmu +{ +Buttons::Buttons(const std::string& name_) : ControlGroup(name_, name_, GROUP_TYPE_BUTTONS) +{ + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.5)); +} + +Buttons::Buttons(const std::string& ini_name, const std::string& group_name) + : ControlGroup(ini_name, group_name, GROUP_TYPE_BUTTONS) +{ + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.5)); +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h new file mode 100644 index 0000000000..9b1acd866c --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h @@ -0,0 +1,33 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class Buttons : public ControlGroup +{ +public: + explicit Buttons(const std::string& name_); + Buttons(const std::string& ini_name, const std::string& group_name); + + template <typename C> + void GetState(C* const buttons, const C* bitmasks) + { + for (auto& control : controls) + { + if (control->control_ref->State() > numeric_settings[0]->GetValue()) // threshold + *buttons |= *bitmasks; + + bitmasks++; + } + } +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp new file mode 100644 index 0000000000..cd730697a5 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp @@ -0,0 +1,132 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +#include "Common/CommonTypes.h" +#include "Common/IniFile.h" + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/ControlGroup/Extension.h" +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +namespace ControllerEmu +{ +ControlGroup::ControlGroup(const std::string& name_, const u32 type_) + : name(name_), ui_name(name_), type(type_) +{ +} + +ControlGroup::ControlGroup(const std::string& name_, const std::string& ui_name_, const u32 type_) + : name(name_), ui_name(ui_name_), type(type_) +{ +} + +ControlGroup::~ControlGroup() = default; + +ControlGroup::BooleanSetting::~BooleanSetting() = default; + +void ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev, + const std::string& base) +{ + std::string group(base + name + "/"); + + // settings + for (auto& s : numeric_settings) + { + if (s->m_type == SettingType::VIRTUAL) + continue; + + sec->Get(group + s->m_name, &s->m_value, s->m_default_value * 100); + s->m_value /= 100; + } + + for (auto& s : boolean_settings) + { + if (s->m_type == SettingType::VIRTUAL) + continue; + + sec->Get(group + s->m_name, &s->m_value, s->m_default_value); + } + + for (auto& c : controls) + { + // control expression + sec->Get(group + c->name, &c->control_ref->expression, ""); + + // range + sec->Get(group + c->name + "/Range", &c->control_ref->range, 100.0); + c->control_ref->range /= 100; + } + + // extensions + if (type == GROUP_TYPE_EXTENSION) + { + Extension* const ext = (Extension*)this; + + ext->switch_extension = 0; + u32 n = 0; + std::string extname; + sec->Get(base + name, &extname, ""); + + for (auto& ai : ext->attachments) + { + ai->default_device.FromString(defdev); + ai->LoadConfig(sec, base + ai->GetName() + "/"); + + if (ai->GetName() == extname) + ext->switch_extension = n; + + n++; + } + } +} + +void ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, + const std::string& base) +{ + std::string group(base + name + "/"); + + for (auto& s : numeric_settings) + { + if (s->m_type == SettingType::VIRTUAL) + continue; + + sec->Set(group + s->m_name, s->m_value * 100.0, s->m_default_value * 100.0); + } + + for (auto& s : boolean_settings) + { + if (s->m_type == SettingType::VIRTUAL) + continue; + + sec->Set(group + s->m_name, s->m_value, s->m_default_value); + } + + for (auto& c : controls) + { + // control expression + sec->Set(group + c->name, c->control_ref->expression, ""); + + // range + sec->Set(group + c->name + "/Range", c->control_ref->range * 100.0, 100.0); + } + + // extensions + if (type == GROUP_TYPE_EXTENSION) + { + Extension* const ext = (Extension*)this; + sec->Set(base + name, ext->attachments[ext->switch_extension]->GetName(), "None"); + + for (auto& ai : ext->attachments) + ai->SaveConfig(sec, base + ai->GetName() + "/"); + } +} + +void ControlGroup::SetControlExpression(int index, const std::string& expression) +{ + controls.at(index)->control_ref->expression = expression; +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h new file mode 100644 index 0000000000..68eacb6e02 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h @@ -0,0 +1,117 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include <vector> + +#include "Common/CommonTypes.h" +#include "Common/IniFile.h" +#include "Core/ConfigManager.h" +#include "InputCommon/ControllerInterface/Device.h" + +namespace ControllerEmu +{ +class Control; + +enum +{ + GROUP_TYPE_OTHER, + GROUP_TYPE_STICK, + GROUP_TYPE_MIXED_TRIGGERS, + GROUP_TYPE_BUTTONS, + GROUP_TYPE_FORCE, + GROUP_TYPE_EXTENSION, + GROUP_TYPE_TILT, + GROUP_TYPE_CURSOR, + GROUP_TYPE_TRIGGERS, + GROUP_TYPE_SLIDER +}; + +class ControlGroup +{ +public: + enum class SettingType + { + NORMAL, // normal settings are saved to configuration files + VIRTUAL, // virtual settings are not saved at all + }; + + class NumericSetting + { + public: + NumericSetting(const std::string& setting_name, const ControlState default_value, + const u32 low = 0, const u32 high = 100, + const SettingType setting_type = SettingType::NORMAL) + : m_type(setting_type), m_name(setting_name), m_default_value(default_value), m_low(low), + m_high(high) + { + } + + ControlState GetValue() const { return m_value; } + void SetValue(ControlState value) { m_value = value; } + const SettingType m_type; + const std::string m_name; + const ControlState m_default_value; + const u32 m_low; + const u32 m_high; + ControlState m_value; + }; + + class BooleanSetting + { + public: + BooleanSetting(const std::string& setting_name, const bool default_value, + const SettingType setting_type = SettingType::NORMAL) + : m_type(setting_type), m_name(setting_name), m_default_value(default_value) + { + } + virtual ~BooleanSetting(); + + virtual bool GetValue() const { return m_value; } + virtual void SetValue(bool value) { m_value = value; } + const SettingType m_type; + const std::string m_name; + const bool m_default_value; + bool m_value; + }; + + class BackgroundInputSetting : public BooleanSetting + { + public: + BackgroundInputSetting(const std::string& setting_name) + : BooleanSetting(setting_name, false, SettingType::VIRTUAL) + { + } + + bool GetValue() const override { return SConfig::GetInstance().m_BackgroundInput; } + void SetValue(bool value) override + { + m_value = value; + SConfig::GetInstance().m_BackgroundInput = value; + } + }; + + explicit ControlGroup(const std::string& name, u32 type = GROUP_TYPE_OTHER); + ControlGroup(const std::string& name, const std::string& ui_name, u32 type = GROUP_TYPE_OTHER); + virtual ~ControlGroup(); + + virtual void LoadConfig(IniFile::Section* sec, const std::string& defdev = "", + const std::string& base = ""); + virtual void SaveConfig(IniFile::Section* sec, const std::string& defdev = "", + const std::string& base = ""); + + void SetControlExpression(int index, const std::string& expression); + + const std::string name; + const std::string ui_name; + const u32 type; + + std::vector<std::unique_ptr<Control>> controls; + std::vector<std::unique_ptr<NumericSetting>> numeric_settings; + std::vector<std::unique_ptr<BooleanSetting>> boolean_settings; +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp new file mode 100644 index 0000000000..1d0c55a8d5 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp @@ -0,0 +1,98 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Cursor.h" + +#include <algorithm> +#include <cmath> +#include <memory> +#include <string> + +#include "Common/Common.h" +#include "Common/MathUtil.h" + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +namespace ControllerEmu +{ +Cursor::Cursor(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_CURSOR) +{ + for (auto& named_direction : named_directions) + controls.emplace_back(std::make_unique<Input>(named_direction)); + + controls.emplace_back(std::make_unique<Input>("Forward")); + controls.emplace_back(std::make_unique<Input>("Backward")); + controls.emplace_back(std::make_unique<Input>(_trans("Hide"))); + controls.emplace_back(std::make_unique<Input>("Recenter")); + + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Center"), 0.5)); + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Width"), 0.5)); + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Height"), 0.5)); + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 20)); + boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Relative Input"), false)); +} + +void Cursor::GetState(ControlState* const x, ControlState* const y, ControlState* const z, + const bool adjusted) +{ + const ControlState zz = controls[4]->control_ref->State() - controls[5]->control_ref->State(); + + // silly being here + if (zz > m_z) + m_z = std::min(m_z + 0.1, zz); + else if (zz < m_z) + m_z = std::max(m_z - 0.1, zz); + + *z = m_z; + + // hide + if (controls[6]->control_ref->State() > 0.5) + { + *x = 10000; + *y = 0; + } + else + { + ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); + ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); + + // adjust cursor according to settings + if (adjusted) + { + xx *= (numeric_settings[1]->GetValue() * 2); + yy *= (numeric_settings[2]->GetValue() * 2); + yy += (numeric_settings[0]->GetValue() - 0.5); + } + + // relative input + if (boolean_settings[0]->GetValue()) + { + const ControlState deadzone = numeric_settings[3]->GetValue(); + // deadzone to avoid the cursor slowly drifting + if (std::abs(xx) > deadzone) + m_x = MathUtil::Clamp(m_x + xx * SPEED_MULTIPLIER, -1.0, 1.0); + if (std::abs(yy) > deadzone) + m_y = MathUtil::Clamp(m_y + yy * SPEED_MULTIPLIER, -1.0, 1.0); + + // recenter + if (controls[7]->control_ref->State() > 0.5) + { + m_x = 0.0; + m_y = 0.0; + } + } + else + { + m_x = xx; + m_y = yy; + } + + *x = m_x; + *y = m_y; + } +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h new file mode 100644 index 0000000000..3520d95d13 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h @@ -0,0 +1,29 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class Cursor : public ControlGroup +{ +public: + explicit Cursor(const std::string& name); + + void GetState(ControlState* x, ControlState* y, ControlState* z, bool adjusted = false); + + ControlState m_z = 0.0; + +private: + // This is used to reduce the cursor speed for relative input + // to something that makes sense with the default range. + static constexpr double SPEED_MULTIPLIER = 0.04; + + ControlState m_x = 0.0; + ControlState m_y = 0.0; +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Extension.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Extension.cpp new file mode 100644 index 0000000000..b35eb40bbd --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Extension.cpp @@ -0,0 +1,16 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Extension.h" + +#include <string> + +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +namespace ControllerEmu +{ +Extension::Extension(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_EXTENSION) +{ +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Extension.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Extension.h new file mode 100644 index 0000000000..366e94f248 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Extension.h @@ -0,0 +1,31 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <string> +#include <vector> + +#include "Common/CommonTypes.h" +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class EmulatedController; + +class Extension : public ControlGroup +{ +public: + explicit Extension(const std::string& name); + + void GetState(u8* data); + bool IsButtonPressed() const; + + std::vector<std::unique_ptr<EmulatedController>> attachments; + + int switch_extension = 0; + int active_extension = 0; +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp new file mode 100644 index 0000000000..29413ada2c --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp @@ -0,0 +1,51 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Force.h" + +#include <cmath> +#include <cstring> +#include <memory> +#include <string> + +#include "Common/Common.h" +#include "Common/CommonTypes.h" +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +namespace ControllerEmu +{ +Force::Force(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_FORCE) +{ + memset(m_swing, 0, sizeof(m_swing)); + + controls.emplace_back(std::make_unique<Input>(_trans("Up"))); + controls.emplace_back(std::make_unique<Input>(_trans("Down"))); + controls.emplace_back(std::make_unique<Input>(_trans("Left"))); + controls.emplace_back(std::make_unique<Input>(_trans("Right"))); + controls.emplace_back(std::make_unique<Input>(_trans("Forward"))); + controls.emplace_back(std::make_unique<Input>(_trans("Backward"))); + + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); +} + +void Force::GetState(ControlState* axis) +{ + const ControlState deadzone = numeric_settings[0]->GetValue(); + + for (u32 i = 0; i < 6; i += 2) + { + ControlState tmpf = 0; + const ControlState state = + 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; + } +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h new file mode 100644 index 0000000000..767009a1f8 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h @@ -0,0 +1,22 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class Force : public ControlGroup +{ +public: + explicit Force(const std::string& name); + + void GetState(ControlState* axis); + +private: + ControlState m_swing[3]; +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp new file mode 100644 index 0000000000..db8efc48a5 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp @@ -0,0 +1,42 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h" + +#include <cstddef> +#include <memory> +#include <string> + +#include "Common/Common.h" +#include "Common/CommonTypes.h" + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" + +namespace ControllerEmu +{ +MixedTriggers::MixedTriggers(const std::string& name_) + : ControlGroup(name_, GROUP_TYPE_MIXED_TRIGGERS) +{ + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.9)); +} + +void MixedTriggers::GetState(u16* const digital, const u16* bitmasks, ControlState* analog) +{ + const size_t trigger_count = controls.size() / 2; + + for (size_t i = 0; i < trigger_count; ++i, ++bitmasks, ++analog) + { + if (controls[i]->control_ref->State() > numeric_settings[0]->GetValue()) // threshold + { + *analog = 1.0; + *digital |= *bitmasks; + } + else + { + *analog = controls[i + trigger_count]->control_ref->State(); + } + } +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h new file mode 100644 index 0000000000..7cd606e53a --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.h @@ -0,0 +1,19 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class MixedTriggers : public ControlGroup +{ +public: + explicit MixedTriggers(const std::string& name); + + void GetState(u16* digital, const u16* bitmasks, ControlState* analog); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.cpp new file mode 100644 index 0000000000..b71b1ea2c1 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.cpp @@ -0,0 +1,77 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.h" + +#include <cstddef> +#include <memory> +#include <string> +#include <utility> + +#include "Common/Common.h" +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "VideoCommon/OnScreenDisplay.h" + +namespace ControllerEmu +{ +ModifySettingsButton::ModifySettingsButton(std::string button_name) + : Buttons(std::move(button_name)) +{ + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.5)); +} + +void ModifySettingsButton::AddInput(std::string button_name, bool toggle) +{ + controls.emplace_back(new Input(std::move(button_name))); + threshold_exceeded.emplace_back(false); + associated_settings.emplace_back(false); + associated_settings_toggle.emplace_back(toggle); +} + +void ModifySettingsButton::GetState() +{ + for (size_t i = 0; i < controls.size(); ++i) + { + ControlState state = controls[i]->control_ref->State(); + + if (!associated_settings_toggle[i]) + { + // not toggled + associated_settings[i] = state > numeric_settings[0]->GetValue(); + } + else + { + // toggle (loading savestates does not en-/disable toggle) + // after we passed the threshold, we en-/disable. but after that, we don't change it + // anymore + if (!threshold_exceeded[i] && state > numeric_settings[0]->GetValue()) + { + associated_settings[i] = !associated_settings[i]; + + if (associated_settings[i]) + OSD::AddMessage(controls[i]->name + ": " + _trans("on")); + else + OSD::AddMessage(controls[i]->name + ": " + _trans("off")); + + threshold_exceeded[i] = true; + } + + if (state < numeric_settings[0]->GetValue()) + threshold_exceeded[i] = false; + } + } +} + +const std::vector<bool>& ModifySettingsButton::isSettingToggled() const +{ + return associated_settings_toggle; +} + +const std::vector<bool>& ModifySettingsButton::getSettingsModifier() const +{ + return associated_settings; +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.h new file mode 100644 index 0000000000..667f3e5c7a --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ModifySettingsButton.h @@ -0,0 +1,31 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include <vector> + +#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h" + +namespace ControllerEmu +{ +class ModifySettingsButton : public Buttons +{ +public: + explicit ModifySettingsButton(std::string button_name); + + void AddInput(std::string button_name, bool toggle = false); + + void GetState(); + + const std::vector<bool>& isSettingToggled() const; + const std::vector<bool>& getSettingsModifier() const; + +private: + std::vector<bool> threshold_exceeded; // internal calculation (if "state" was above threshold) + std::vector<bool> associated_settings_toggle; // is setting toggled or hold? + std::vector<bool> associated_settings; // result +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp new file mode 100644 index 0000000000..5fdf349bba --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp @@ -0,0 +1,37 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Slider.h" + +#include <cmath> +#include <memory> +#include <string> + +#include "Common/Common.h" +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/Control/Input.h" +#include "InputCommon/ControllerEmu/ControllerEmu.h" + +namespace ControllerEmu +{ +Slider::Slider(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_SLIDER) +{ + controls.emplace_back(std::make_unique<Input>("Left")); + controls.emplace_back(std::make_unique<Input>("Right")); + + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); +} + +void Slider::GetState(ControlState* const slider) +{ + const ControlState deadzone = numeric_settings[0]->GetValue(); + const ControlState state = controls[1]->control_ref->State() - controls[0]->control_ref->State(); + + if (fabs(state) > deadzone) + *slider = (state - (deadzone * sign(state))) / (1 - deadzone); + else + *slider = 0; +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h new file mode 100644 index 0000000000..3d6f7f5a02 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h @@ -0,0 +1,19 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class Slider : public ControlGroup +{ +public: + explicit Slider(const std::string& name); + + void GetState(ControlState* slider); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp new file mode 100644 index 0000000000..5481d92606 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp @@ -0,0 +1,99 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Tilt.h" + +#include <algorithm> +#include <cmath> +#include <cstring> +#include <memory> +#include <string> + +#include "Common/Common.h" +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/Control/Input.h" + +namespace ControllerEmu +{ +Tilt::Tilt(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_TILT) +{ + memset(m_tilt, 0, sizeof(m_tilt)); + + controls.emplace_back(std::make_unique<Input>("Forward")); + controls.emplace_back(std::make_unique<Input>("Backward")); + controls.emplace_back(std::make_unique<Input>("Left")); + controls.emplace_back(std::make_unique<Input>("Right")); + + controls.emplace_back(std::make_unique<Input>(_trans("Modifier"))); + + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Circle Stick"), 0)); + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.9, 0, 180)); +} + +void Tilt::GetState(ControlState* const x, ControlState* const y, const bool step) +{ + // this is all a mess + + ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); + ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); + + ControlState deadzone = numeric_settings[0]->GetValue(); + ControlState circle = numeric_settings[1]->GetValue(); + auto const angle = numeric_settings[2]->GetValue() / 1.8; + ControlState m = controls[4]->control_ref->State(); + + // deadzone / circle stick code + // this section might be all wrong, but its working good enough, I think + + ControlState ang = atan2(yy, xx); + ControlState ang_sin = sin(ang); + ControlState ang_cos = cos(ang); + + // the amt a full square stick would have at current angle + ControlState square_full = + std::min(ang_sin ? 1 / fabs(ang_sin) : 2, ang_cos ? 1 / fabs(ang_cos) : 2); + + // the amt a full stick would have that was (user setting circular) at current angle + // I think this is more like a pointed circle rather than a rounded square like it should be + ControlState stick_full = (square_full * (1 - circle)) + (circle); + + ControlState dist = sqrt(xx * xx + yy * yy); + + // dead zone code + dist = std::max(0.0, dist - deadzone * stick_full); + dist /= (1 - deadzone); + + // circle stick code + ControlState amt = dist / stick_full; + dist += (square_full - 1) * amt * circle; + + if (m) + dist *= 0.5; + + yy = std::max(-1.0, std::min(1.0, ang_sin * dist)); + xx = std::max(-1.0, std::min(1.0, ang_cos * dist)); + + // this is kinda silly here + // gui being open will make this happen 2x as fast, o well + + // silly + if (step) + { + if (xx > m_tilt[0]) + m_tilt[0] = std::min(m_tilt[0] + 0.1, xx); + else if (xx < m_tilt[0]) + m_tilt[0] = std::max(m_tilt[0] - 0.1, xx); + + if (yy > m_tilt[1]) + m_tilt[1] = std::min(m_tilt[1] + 0.1, yy); + else if (yy < m_tilt[1]) + m_tilt[1] = std::max(m_tilt[1] - 0.1, yy); + } + + *y = m_tilt[1] * angle; + *x = m_tilt[0] * angle; +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h new file mode 100644 index 0000000000..940d7d9722 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h @@ -0,0 +1,22 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class Tilt : public ControlGroup +{ +public: + explicit Tilt(const std::string& name); + + void GetState(ControlState* x, ControlState* y, bool step = true); + +private: + ControlState m_tilt[2]; +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp new file mode 100644 index 0000000000..3e13b0b504 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp @@ -0,0 +1,31 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/ControllerEmu/ControlGroup/Triggers.h" + +#include <algorithm> +#include <cstddef> +#include <memory> +#include <string> + +#include "Common/Common.h" +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" + +namespace ControllerEmu +{ +Triggers::Triggers(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_TRIGGERS) +{ + numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); +} + +void Triggers::GetState(ControlState* analog) +{ + const size_t trigger_count = controls.size(); + const ControlState deadzone = numeric_settings[0]->GetValue(); + + for (size_t i = 0; i < trigger_count; ++i, ++analog) + *analog = std::max(controls[i]->control_ref->State() - deadzone, 0.0) / (1 - deadzone); +} +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h new file mode 100644 index 0000000000..5562e5c694 --- /dev/null +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.h @@ -0,0 +1,19 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include <string> +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" + +namespace ControllerEmu +{ +class Triggers : public ControlGroup +{ +public: + explicit Triggers(const std::string& name); + + void GetState(ControlState* analog); +}; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp index 62501494e6..2aa65b3d42 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.cpp @@ -3,23 +3,36 @@ // Refer to the license.txt file included. #include "InputCommon/ControllerEmu/ControllerEmu.h" + #include <memory> -#include "Common/Common.h" -#include "VideoCommon/OnScreenDisplay.h" +#include <mutex> +#include <string> + +#include "Common/IniFile.h" + +#include "InputCommon/ControlReference/ControlReference.h" +#include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" +#include "InputCommon/ControllerEmu/ControlGroup/Extension.h" + +namespace ControllerEmu +{ +static std::recursive_mutex s_get_state_mutex; + +EmulatedController::~EmulatedController() = default; // This should be called before calling GetState() or State() on a control reference // to prevent a race condition. // This is a recursive mutex because UpdateReferences is recursive. -static std::recursive_mutex s_get_state_mutex; -std::unique_lock<std::recursive_mutex> ControllerEmu::GetStateLock() +std::unique_lock<std::recursive_mutex> EmulatedController::GetStateLock() { std::unique_lock<std::recursive_mutex> lock(s_get_state_mutex); return lock; } -void ControllerEmu::UpdateReferences(ControllerInterface& devi) +void EmulatedController::UpdateReferences(ControllerInterface& devi) { - auto lock = ControllerEmu::GetStateLock(); + const auto lock = GetStateLock(); for (auto& ctrlGroup : groups) { for (auto& control : ctrlGroup->controls) @@ -34,7 +47,7 @@ void ControllerEmu::UpdateReferences(ControllerInterface& devi) } } -void ControllerEmu::UpdateDefaultDevice() +void EmulatedController::UpdateDefaultDevice() { for (auto& ctrlGroup : groups) { @@ -50,62 +63,7 @@ void ControllerEmu::UpdateDefaultDevice() } } -void ControllerEmu::ControlGroup::LoadConfig(IniFile::Section* sec, const std::string& defdev, - const std::string& base) -{ - std::string group(base + name + "/"); - - // settings - for (auto& s : numeric_settings) - { - if (s->m_type == SettingType::VIRTUAL) - continue; - sec->Get(group + s->m_name, &s->m_value, s->m_default_value * 100); - s->m_value /= 100; - } - for (auto& s : boolean_settings) - { - if (s->m_type == SettingType::VIRTUAL) - continue; - sec->Get(group + s->m_name, &s->m_value, s->m_default_value); - } - - for (auto& c : controls) - { - // control expression - sec->Get(group + c->name, &c->control_ref->expression, ""); - - // range - sec->Get(group + c->name + "/Range", &c->control_ref->range, 100.0); - c->control_ref->range /= 100; - } - - // extensions - if (type == GROUP_TYPE_EXTENSION) - { - Extension* const ext = (Extension*)this; - - ext->switch_extension = 0; - unsigned int n = 0; - std::string extname; - sec->Get(base + name, &extname, ""); - - for (auto& ai : ext->attachments) - { - ai->default_device.FromString(defdev); - ai->LoadConfig(sec, base + ai->GetName() + "/"); - - if (ai->GetName() == extname) - ext->switch_extension = n; - - n++; - } - } -} - -ControllerEmu::ControlGroup::BooleanSetting::~BooleanSetting() = default; - -void ControllerEmu::LoadConfig(IniFile::Section* sec, const std::string& base) +void EmulatedController::LoadConfig(IniFile::Section* sec, const std::string& base) { std::string defdev = default_device.ToString(); if (base.empty()) @@ -118,45 +76,7 @@ void ControllerEmu::LoadConfig(IniFile::Section* sec, const std::string& base) cg->LoadConfig(sec, defdev, base); } -void ControllerEmu::ControlGroup::SaveConfig(IniFile::Section* sec, const std::string& defdev, - const std::string& base) -{ - std::string group(base + name + "/"); - - for (auto& s : numeric_settings) - { - if (s->m_type == SettingType::VIRTUAL) - continue; - sec->Set(group + s->m_name, s->m_value * 100.0, s->m_default_value * 100.0); - } - for (auto& s : boolean_settings) - { - if (s->m_type == SettingType::VIRTUAL) - continue; - sec->Set(group + s->m_name, s->m_value, s->m_default_value); - } - - for (auto& c : controls) - { - // control expression - sec->Set(group + c->name, c->control_ref->expression, ""); - - // range - sec->Set(group + c->name + "/Range", c->control_ref->range * 100.0, 100.0); - } - - // extensions - if (type == GROUP_TYPE_EXTENSION) - { - Extension* const ext = (Extension*)this; - sec->Set(base + name, ext->attachments[ext->switch_extension]->GetName(), "None"); - - for (auto& ai : ext->attachments) - ai->SaveConfig(sec, base + ai->GetName() + "/"); - } -} - -void ControllerEmu::SaveConfig(IniFile::Section* sec, const std::string& base) +void EmulatedController::SaveConfig(IniFile::Section* sec, const std::string& base) { const std::string defdev = default_device.ToString(); if (base.empty()) @@ -166,154 +86,7 @@ void ControllerEmu::SaveConfig(IniFile::Section* sec, const std::string& base) ctrlGroup->SaveConfig(sec, defdev, base); } -void ControllerEmu::ControlGroup::SetControlExpression(int index, const std::string& expression) -{ - controls.at(index)->control_ref->expression = expression; -} - -ControllerEmu::AnalogStick::AnalogStick(const char* const _name, ControlState default_radius) - : AnalogStick(_name, _name, default_radius) -{ -} - -ControllerEmu::AnalogStick::AnalogStick(const char* const _name, const char* const _ui_name, - ControlState default_radius) - : ControlGroup(_name, _ui_name, GROUP_TYPE_STICK) -{ - for (auto& named_direction : named_directions) - controls.emplace_back(std::make_unique<Input>(named_direction)); - - controls.emplace_back(std::make_unique<Input>(_trans("Modifier"))); - numeric_settings.emplace_back( - std::make_unique<NumericSetting>(_trans("Radius"), default_radius, 0, 100)); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); -} - -ControllerEmu::Buttons::Buttons(const std::string& _name) - : ControlGroup(_name, _name, GROUP_TYPE_BUTTONS) -{ - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.5)); -} - -ControllerEmu::Buttons::Buttons(const std::string& ini_name, const std::string& group_name) - : ControlGroup(ini_name, group_name, GROUP_TYPE_BUTTONS) -{ - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.5)); -} - -ControllerEmu::ModifySettingsButton::ModifySettingsButton(std::string button_name) - : Buttons(std::move(button_name)) -{ - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.5)); -} - -void ControllerEmu::ModifySettingsButton::AddInput(std::string button_name, bool toggle) -{ - controls.emplace_back(new ControlGroup::Input(std::move(button_name))); - threshold_exceeded.emplace_back(false); - associated_settings.emplace_back(false); - associated_settings_toggle.emplace_back(toggle); -} - -void ControllerEmu::ModifySettingsButton::GetState() -{ - for (size_t i = 0; i < controls.size(); ++i) - { - ControlState state = controls[i]->control_ref->State(); - - if (!associated_settings_toggle[i]) - { - // not toggled - associated_settings[i] = state > numeric_settings[0]->GetValue(); - } - else - { - // toggle (loading savestates does not en-/disable toggle) - // after we passed the threshold, we en-/disable. but after that, we don't change it - // anymore - if (!threshold_exceeded[i] && state > numeric_settings[0]->GetValue()) - { - associated_settings[i] = !associated_settings[i]; - if (associated_settings[i]) - OSD::AddMessage(controls[i]->name + ": " + _trans("on")); - else - OSD::AddMessage(controls[i]->name + ": " + _trans("off")); - threshold_exceeded[i] = true; - } - if (state < numeric_settings[0]->GetValue()) - threshold_exceeded[i] = false; - } - } -} - -ControllerEmu::MixedTriggers::MixedTriggers(const std::string& _name) - : ControlGroup(_name, GROUP_TYPE_MIXED_TRIGGERS) -{ - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Threshold"), 0.9)); -} - -ControllerEmu::Triggers::Triggers(const std::string& _name) - : ControlGroup(_name, GROUP_TYPE_TRIGGERS) -{ - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); -} - -ControllerEmu::Slider::Slider(const std::string& _name) : ControlGroup(_name, GROUP_TYPE_SLIDER) -{ - controls.emplace_back(std::make_unique<Input>("Left")); - controls.emplace_back(std::make_unique<Input>("Right")); - - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); -} - -ControllerEmu::Force::Force(const std::string& _name) : ControlGroup(_name, GROUP_TYPE_FORCE) -{ - memset(m_swing, 0, sizeof(m_swing)); - - controls.emplace_back(std::make_unique<Input>(_trans("Up"))); - controls.emplace_back(std::make_unique<Input>(_trans("Down"))); - controls.emplace_back(std::make_unique<Input>(_trans("Left"))); - controls.emplace_back(std::make_unique<Input>(_trans("Right"))); - controls.emplace_back(std::make_unique<Input>(_trans("Forward"))); - controls.emplace_back(std::make_unique<Input>(_trans("Backward"))); - - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); -} - -ControllerEmu::Tilt::Tilt(const std::string& _name) : ControlGroup(_name, GROUP_TYPE_TILT) -{ - memset(m_tilt, 0, sizeof(m_tilt)); - - controls.emplace_back(std::make_unique<Input>("Forward")); - controls.emplace_back(std::make_unique<Input>("Backward")); - controls.emplace_back(std::make_unique<Input>("Left")); - controls.emplace_back(std::make_unique<Input>("Right")); - - controls.emplace_back(std::make_unique<Input>(_trans("Modifier"))); - - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50)); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Circle Stick"), 0)); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.9, 0, 180)); -} - -ControllerEmu::Cursor::Cursor(const std::string& _name) - : ControlGroup(_name, GROUP_TYPE_CURSOR), m_z(0) -{ - for (auto& named_direction : named_directions) - controls.emplace_back(std::make_unique<Input>(named_direction)); - controls.emplace_back(std::make_unique<Input>("Forward")); - controls.emplace_back(std::make_unique<Input>("Backward")); - controls.emplace_back(std::make_unique<Input>(_trans("Hide"))); - controls.emplace_back(std::make_unique<Input>("Recenter")); - - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Center"), 0.5)); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Width"), 0.5)); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Height"), 0.5)); - numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 20)); - boolean_settings.emplace_back(std::make_unique<BooleanSetting>(_trans("Relative Input"), false)); -} - -void ControllerEmu::LoadDefaults(const ControllerInterface& ciface) +void EmulatedController::LoadDefaults(const ControllerInterface& ciface) { // load an empty inifile section, clears everything IniFile::Section sec; @@ -326,3 +99,4 @@ void ControllerEmu::LoadDefaults(const ControllerInterface& ciface) UpdateDefaultDevice(); } } +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h index 65332ac87f..24f4434dcb 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h +++ b/Source/Core/InputCommon/ControllerEmu/ControllerEmu.h @@ -4,488 +4,27 @@ #pragma once -#include <algorithm> -#include <cmath> #include <memory> #include <mutex> #include <string> #include <vector> #include "Common/IniFile.h" -#include "Common/MathUtil.h" -#include "Core/ConfigManager.h" #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" -#include "InputCommon/GCPadStatus.h" #define sign(x) ((x) ? (x) < 0 ? -1 : 1 : 0) -enum -{ - GROUP_TYPE_OTHER, - GROUP_TYPE_STICK, - GROUP_TYPE_MIXED_TRIGGERS, - GROUP_TYPE_BUTTONS, - GROUP_TYPE_FORCE, - GROUP_TYPE_EXTENSION, - GROUP_TYPE_TILT, - GROUP_TYPE_CURSOR, - GROUP_TYPE_TRIGGERS, - GROUP_TYPE_SLIDER -}; +const char* const named_directions[] = {"Up", "Down", "Left", "Right"}; -enum +namespace ControllerEmu { - SETTING_RADIUS, - SETTING_DEADZONE, -}; - -const char* const named_directions[] = {"Up", "Down", "Left", "Right"}; +class ControlGroup; -class ControllerEmu +class EmulatedController { public: - class ControlGroup - { - public: - class Control - { - protected: - Control(ControlReference* const _ref, const std::string& _name) - : control_ref(_ref), name(_name) - { - } - - public: - virtual ~Control() {} - std::unique_ptr<ControlReference> const control_ref; - const std::string name; - }; - - class Input : public Control - { - public: - Input(const std::string& _name) : Control(new InputReference, _name) {} - }; - - class Output : public Control - { - public: - Output(const std::string& _name) : Control(new OutputReference, _name) {} - }; - - enum class SettingType - { - NORMAL, // normal settings are saved to configuration files - VIRTUAL, // virtual settings are not saved at all - }; - - class NumericSetting - { - public: - NumericSetting(const std::string& setting_name, const ControlState default_value, - const unsigned int low = 0, const unsigned int high = 100, - const SettingType setting_type = SettingType::NORMAL) - : m_type(setting_type), m_name(setting_name), m_default_value(default_value), m_low(low), - m_high(high) - { - } - - ControlState GetValue() const { return m_value; } - void SetValue(ControlState value) { m_value = value; } - const SettingType m_type; - const std::string m_name; - const ControlState m_default_value; - const unsigned int m_low, m_high; - ControlState m_value; - }; - - class BooleanSetting - { - public: - BooleanSetting(const std::string& setting_name, const bool default_value, - const SettingType setting_type = SettingType::NORMAL) - : m_type(setting_type), m_name(setting_name), m_default_value(default_value) - { - } - virtual ~BooleanSetting(); - - virtual bool GetValue() const { return m_value; } - virtual void SetValue(bool value) { m_value = value; } - const SettingType m_type; - const std::string m_name; - const bool m_default_value; - bool m_value; - }; - - class BackgroundInputSetting : public BooleanSetting - { - public: - BackgroundInputSetting(const std::string& setting_name) - : BooleanSetting(setting_name, false, SettingType::VIRTUAL) - { - } - - bool GetValue() const override { return SConfig::GetInstance().m_BackgroundInput; } - void SetValue(bool value) override - { - m_value = value; - SConfig::GetInstance().m_BackgroundInput = value; - } - }; - - ControlGroup(const std::string& _name, const unsigned int _type = GROUP_TYPE_OTHER) - : name(_name), ui_name(_name), type(_type) - { - } - ControlGroup(const std::string& _name, const std::string& _ui_name, - const unsigned int _type = GROUP_TYPE_OTHER) - : name(_name), ui_name(_ui_name), type(_type) - { - } - virtual ~ControlGroup() {} - virtual void LoadConfig(IniFile::Section* sec, const std::string& defdev = "", - const std::string& base = ""); - virtual void SaveConfig(IniFile::Section* sec, const std::string& defdev = "", - const std::string& base = ""); - - void SetControlExpression(int index, const std::string& expression); - - const std::string name; - const std::string ui_name; - const unsigned int type; - - std::vector<std::unique_ptr<Control>> controls; - std::vector<std::unique_ptr<NumericSetting>> numeric_settings; - std::vector<std::unique_ptr<BooleanSetting>> boolean_settings; - }; - - class AnalogStick : public ControlGroup - { - public: - // The GameCube controller and Wiimote attachments have a different default radius - AnalogStick(const char* const _name, ControlState default_radius); - AnalogStick(const char* const _name, const char* const _ui_name, ControlState default_radius); - - void GetState(ControlState* const x, ControlState* const y) - { - ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); - ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); - - ControlState radius = numeric_settings[SETTING_RADIUS]->GetValue(); - ControlState deadzone = numeric_settings[SETTING_DEADZONE]->GetValue(); - ControlState m = controls[4]->control_ref->State(); - - ControlState ang = atan2(yy, xx); - ControlState ang_sin = sin(ang); - ControlState ang_cos = cos(ang); - - ControlState dist = sqrt(xx * xx + yy * yy); - - // dead zone code - dist = std::max(0.0, dist - deadzone); - dist /= (1 - deadzone); - - // radius - dist *= radius; - - // The modifier halves the distance by 50%, which is useful - // for keyboard controls. - if (m) - dist *= 0.5; - - yy = std::max(-1.0, std::min(1.0, ang_sin * dist)); - xx = std::max(-1.0, std::min(1.0, ang_cos * dist)); - - *y = yy; - *x = xx; - } - }; - - class Buttons : public ControlGroup - { - public: - Buttons(const std::string& _name); - Buttons(const std::string& ini_name, const std::string& group_name); - - template <typename C> - void GetState(C* const buttons, const C* bitmasks) - { - for (auto& control : controls) - { - if (control->control_ref->State() > numeric_settings[0]->GetValue()) // threshold - *buttons |= *bitmasks; - - bitmasks++; - } - } - }; - - class ModifySettingsButton : public Buttons - { - public: - ModifySettingsButton(std::string button_name); - void AddInput(std::string button_name, bool toggle = false); - - void GetState(); - - const std::vector<bool>& isSettingToggled() const { return associated_settings_toggle; } - const std::vector<bool>& getSettingsModifier() const { return associated_settings; } - private: - std::vector<bool> threshold_exceeded; // internal calculation (if "state" was above threshold) - std::vector<bool> associated_settings_toggle; // is setting toggled or hold? - std::vector<bool> associated_settings; // result - }; - - class MixedTriggers : public ControlGroup - { - public: - MixedTriggers(const std::string& _name); - - void GetState(u16* const digital, const u16* bitmasks, ControlState* analog) - { - const unsigned int trig_count = ((unsigned int)(controls.size() / 2)); - for (unsigned int i = 0; i < trig_count; ++i, ++bitmasks, ++analog) - { - if (controls[i]->control_ref->State() > numeric_settings[0]->GetValue()) // threshold - { - *analog = 1.0; - *digital |= *bitmasks; - } - else - { - *analog = controls[i + trig_count]->control_ref->State(); - } - } - } - }; - - class Triggers : public ControlGroup - { - public: - Triggers(const std::string& _name); - - void GetState(ControlState* analog) - { - const unsigned int trig_count = ((unsigned int)(controls.size())); - const ControlState deadzone = numeric_settings[0]->GetValue(); - for (unsigned int i = 0; i < trig_count; ++i, ++analog) - *analog = std::max(controls[i]->control_ref->State() - deadzone, 0.0) / (1 - deadzone); - } - }; - - class Slider : public ControlGroup - { - public: - Slider(const std::string& _name); - - void GetState(ControlState* const slider) - { - const ControlState deadzone = numeric_settings[0]->GetValue(); - const ControlState state = - controls[1]->control_ref->State() - controls[0]->control_ref->State(); - - if (fabs(state) > deadzone) - *slider = (state - (deadzone * sign(state))) / (1 - deadzone); - else - *slider = 0; - } - }; - - class Force : public ControlGroup - { - public: - Force(const std::string& _name); - - void GetState(ControlState* axis) - { - const ControlState deadzone = numeric_settings[0]->GetValue(); - for (unsigned int i = 0; i < 6; i += 2) - { - ControlState tmpf = 0; - const ControlState state = - 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; - } - } - - private: - ControlState m_swing[3]; - }; - - class Tilt : public ControlGroup - { - public: - Tilt(const std::string& _name); - - void GetState(ControlState* const x, ControlState* const y, const bool step = true) - { - // this is all a mess - - ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); - ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); - - ControlState deadzone = numeric_settings[0]->GetValue(); - ControlState circle = numeric_settings[1]->GetValue(); - auto const angle = numeric_settings[2]->GetValue() / 1.8; - ControlState m = controls[4]->control_ref->State(); - - // deadzone / circle stick code - // this section might be all wrong, but its working good enough, I think - - ControlState ang = atan2(yy, xx); - ControlState ang_sin = sin(ang); - ControlState ang_cos = cos(ang); - - // the amt a full square stick would have at current angle - ControlState square_full = - std::min(ang_sin ? 1 / fabs(ang_sin) : 2, ang_cos ? 1 / fabs(ang_cos) : 2); - - // the amt a full stick would have that was (user setting circular) at current angle - // I think this is more like a pointed circle rather than a rounded square like it should be - ControlState stick_full = (square_full * (1 - circle)) + (circle); - - ControlState dist = sqrt(xx * xx + yy * yy); - - // dead zone code - dist = std::max(0.0, dist - deadzone * stick_full); - dist /= (1 - deadzone); - - // circle stick code - ControlState amt = dist / stick_full; - dist += (square_full - 1) * amt * circle; - - if (m) - dist *= 0.5; - - yy = std::max(-1.0, std::min(1.0, ang_sin * dist)); - xx = std::max(-1.0, std::min(1.0, ang_cos * dist)); - - // this is kinda silly here - // gui being open will make this happen 2x as fast, o well - - // silly - if (step) - { - if (xx > m_tilt[0]) - m_tilt[0] = std::min(m_tilt[0] + 0.1, xx); - else if (xx < m_tilt[0]) - m_tilt[0] = std::max(m_tilt[0] - 0.1, xx); - - if (yy > m_tilt[1]) - m_tilt[1] = std::min(m_tilt[1] + 0.1, yy); - else if (yy < m_tilt[1]) - m_tilt[1] = std::max(m_tilt[1] - 0.1, yy); - } - - *y = m_tilt[1] * angle; - *x = m_tilt[0] * angle; - } - - private: - ControlState m_tilt[2]; - }; - - class Cursor : public ControlGroup - { - public: - Cursor(const std::string& _name); - - void GetState(ControlState* const x, ControlState* const y, ControlState* const z, - const bool adjusted = false) - { - const ControlState zz = controls[4]->control_ref->State() - controls[5]->control_ref->State(); - - // silly being here - if (zz > m_z) - m_z = std::min(m_z + 0.1, zz); - else if (zz < m_z) - m_z = std::max(m_z - 0.1, zz); - - *z = m_z; - - // hide - if (controls[6]->control_ref->State() > 0.5) - { - *x = 10000; - *y = 0; - } - else - { - ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); - ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); - - // adjust cursor according to settings - if (adjusted) - { - xx *= (numeric_settings[1]->GetValue() * 2); - yy *= (numeric_settings[2]->GetValue() * 2); - yy += (numeric_settings[0]->GetValue() - 0.5); - } - - // relative input - if (boolean_settings[0]->GetValue()) - { - const ControlState deadzone = numeric_settings[3]->GetValue(); - // deadzone to avoid the cursor slowly drifting - if (std::abs(xx) > deadzone) - m_x = MathUtil::Clamp(m_x + xx * SPEED_MULTIPLIER, -1.0, 1.0); - if (std::abs(yy) > deadzone) - m_y = MathUtil::Clamp(m_y + yy * SPEED_MULTIPLIER, -1.0, 1.0); - - // recenter - if (controls[7]->control_ref->State() > 0.5) - { - m_x = 0.0; - m_y = 0.0; - } - } - else - { - m_x = xx; - m_y = yy; - } - - *x = m_x; - *y = m_y; - } - } - - ControlState m_z; - - private: - // This is used to reduce the cursor speed for relative input - // to something that makes sense with the default range. - static constexpr double SPEED_MULTIPLIER = 0.04; - - ControlState m_x = 0.0; - ControlState m_y = 0.0; - }; - - class Extension : public ControlGroup - { - public: - Extension(const std::string& _name) - : ControlGroup(_name, GROUP_TYPE_EXTENSION), switch_extension(0), active_extension(0) - { - } - - ~Extension() {} - void GetState(u8* const data); - bool IsButtonPressed() const; - - std::vector<std::unique_ptr<ControllerEmu>> attachments; - - int switch_extension; - int active_extension; - }; - - virtual ~ControllerEmu() {} + virtual ~EmulatedController(); virtual std::string GetName() const = 0; virtual void LoadDefaults(const ControllerInterface& ciface); @@ -506,3 +45,4 @@ public: ciface::Core::DeviceQualifier default_device; }; +} // namespace ControllerEmu diff --git a/Source/Core/InputCommon/InputCommon.vcxproj b/Source/Core/InputCommon/InputCommon.vcxproj index 0f961839d7..954110646b 100644 --- a/Source/Core/InputCommon/InputCommon.vcxproj +++ b/Source/Core/InputCommon/InputCommon.vcxproj @@ -36,6 +36,20 @@ <PropertyGroup Label="UserMacros" /> <ItemGroup> <ClCompile Include="ControllerEmu\ControllerEmu.cpp" /> + <ClCompile Include="ControllerEmu\Control\Control.cpp" /> + <ClCompile Include="ControllerEmu\Control\Input.cpp" /> + <ClCompile Include="ControllerEmu\Control\Output.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\AnalogStick.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Buttons.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\ControlGroup.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Cursor.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Extension.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Force.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\MixedTriggers.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\ModifySettingsButton.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Slider.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Tilt.cpp" /> + <ClCompile Include="ControllerEmu\ControlGroup\Triggers.cpp" /> <ClCompile Include="ControllerInterface\ControllerInterface.cpp" /> <ClCompile Include="ControllerInterface\Device.cpp" /> <ClCompile Include="ControllerInterface\DInput\DInput.cpp" /> @@ -57,6 +71,20 @@ </ItemGroup> <ItemGroup> <ClInclude Include="ControllerEmu\ControllerEmu.h" /> + <ClInclude Include="ControllerEmu\Control\Control.h" /> + <ClInclude Include="ControllerEmu\Control\Input.h" /> + <ClInclude Include="ControllerEmu\Control\Output.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\AnalogStick.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Buttons.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\ControlGroup.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Cursor.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Extension.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Force.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\MixedTriggers.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\ModifySettingsButton.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Slider.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Tilt.h" /> + <ClInclude Include="ControllerEmu\ControlGroup\Triggers.h" /> <ClInclude Include="ControllerInterface\ControllerInterface.h" /> <ClInclude Include="ControllerInterface\Device.h" /> <ClInclude Include="ControllerInterface\DInput\DInput.h" /> diff --git a/Source/Core/InputCommon/InputCommon.vcxproj.filters b/Source/Core/InputCommon/InputCommon.vcxproj.filters index 1287497f01..4302e1233d 100644 --- a/Source/Core/InputCommon/InputCommon.vcxproj.filters +++ b/Source/Core/InputCommon/InputCommon.vcxproj.filters @@ -16,6 +16,12 @@ <Filter Include="ControllerEmu"> <UniqueIdentifier>{4c839215-4085-4e34-a960-7960986ad015}</UniqueIdentifier> </Filter> + <Filter Include="ControllerEmu\Control"> + <UniqueIdentifier>{19ddd862-a1e3-479b-b638-bb31700c5171}</UniqueIdentifier> + </Filter> + <Filter Include="ControllerEmu\ControlGroup"> + <UniqueIdentifier>{e805231c-dc4e-4540-8bf8-8c567f3d00ae}</UniqueIdentifier> + </Filter> </ItemGroup> <ItemGroup> <ClCompile Include="GCAdapter.cpp" /> @@ -23,6 +29,48 @@ <ClCompile Include="ControllerEmu\ControllerEmu.cpp"> <Filter>ControllerEmu</Filter> </ClCompile> + <ClCompile Include="ControllerEmu\Control\Control.cpp"> + <Filter>ControllerEmu\Control</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\Control\Input.cpp"> + <Filter>ControllerEmu\Control</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\Control\Output.cpp"> + <Filter>ControllerEmu\Control</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\AnalogStick.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Buttons.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\ControlGroup.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Cursor.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Extension.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Force.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\MixedTriggers.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\ModifySettingsButton.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Slider.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Tilt.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> + <ClCompile Include="ControllerEmu\ControlGroup\Triggers.cpp"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClCompile> <ClCompile Include="ControllerInterface\DInput\DInput.cpp"> <Filter>ControllerInterface\DInput</Filter> </ClCompile> @@ -61,6 +109,48 @@ <ClInclude Include="ControllerEmu\ControllerEmu.h"> <Filter>ControllerEmu</Filter> </ClInclude> + <ClInclude Include="ControllerEmu\Control\Control.h"> + <Filter>ControllerEmu\Control</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\Control\Input.h"> + <Filter>ControllerEmu\Control</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\Control\Output.h"> + <Filter>ControllerEmu\Control</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\AnalogStick.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Buttons.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\ControlGroup.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Cursor.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Extension.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Force.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\MixedTriggers.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\ModifySettingsButton.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Slider.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Tilt.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> + <ClInclude Include="ControllerEmu\ControlGroup\Triggers.h"> + <Filter>ControllerEmu\ControlGroup</Filter> + </ClInclude> <ClInclude Include="ControllerInterface\DInput\DInput.h"> <Filter>ControllerInterface\DInput</Filter> </ClInclude> @@ -98,4 +188,4 @@ <ItemGroup> <Text Include="CMakeLists.txt" /> </ItemGroup> -</Project> +</Project>
\ No newline at end of file diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index 1a723c5fbb..86bda0189f 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -9,10 +9,19 @@ #include "Common/MsgHandler.h" #include "Core/ConfigManager.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" +InputConfig::InputConfig(const std::string& ini_name, const std::string& gui_name, + const std::string& profile_name) + : m_ini_name(ini_name), m_gui_name(gui_name), m_profile_name(profile_name) +{ +} + +InputConfig::~InputConfig() = default; + bool InputConfig::LoadConfig(bool isGC) { IniFile inifile; @@ -104,7 +113,7 @@ void InputConfig::SaveConfig() inifile.Save(ini_filename); } -ControllerEmu* InputConfig::GetController(int index) +ControllerEmu::EmulatedController* InputConfig::GetController(int index) { return m_controllers.at(index).get(); } diff --git a/Source/Core/InputCommon/InputConfig.h b/Source/Core/InputCommon/InputConfig.h index 27cc70198e..fcbd8a59f9 100644 --- a/Source/Core/InputCommon/InputConfig.h +++ b/Source/Core/InputCommon/InputConfig.h @@ -9,16 +9,18 @@ #include <utility> #include <vector> -class ControllerEmu; +namespace ControllerEmu +{ +class EmulatedController; +} class InputConfig { public: InputConfig(const std::string& ini_name, const std::string& gui_name, - const std::string& profile_name) - : m_ini_name(ini_name), m_gui_name(gui_name), m_profile_name(profile_name) - { - } + const std::string& profile_name); + + ~InputConfig(); bool LoadConfig(bool isGC); void SaveConfig(); @@ -29,7 +31,7 @@ public: m_controllers.emplace_back(std::make_unique<T>(std::forward<Args>(args)...)); } - ControllerEmu* GetController(int index); + ControllerEmu::EmulatedController* GetController(int index); void ClearControllers(); bool ControllersNeedToBeCreated() const; bool IsControllerControlledByGamepadDevice(int index) const; @@ -37,7 +39,7 @@ public: std::string GetGUIName() const { return m_gui_name; } std::string GetProfileName() const { return m_profile_name; } private: - std::vector<std::unique_ptr<ControllerEmu>> m_controllers; + std::vector<std::unique_ptr<ControllerEmu::EmulatedController>> m_controllers; const std::string m_ini_name; const std::string m_gui_name; const std::string m_profile_name; |
