diff options
Diffstat (limited to 'Source/Core/InputCommon/ControllerEmu/ControlGroup')
22 files changed, 1046 insertions, 0 deletions
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 |
