mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-05-02 09:18:36 +00:00
ControllerEmu: Separate ControlGroup from ControllerEmu
ControllerEmu, the class, is essentially acting like a namespace for ControlGroup. This makes it impossible to forward declare any of the internals. It also globs a bunch of classes together which is kind of a pain to manage. This splits ControlGroup and the classes it contains into their own source files and situates them all within a namespace, which gets them out of global scope. Since this allows forward declarations for the once-internal classes, it now requires significantly less files to be rebuilt if anything is changed in the ControllerEmu portion of code. It does not split out the settings classes yet, however, as it would be preferable to make a settings base class that all settings derive from, but this would be a functional change -- this commit only intends to move around existing code. Extracting the settings class will be done in another commit.
This commit is contained in:
parent
1385a012d9
commit
6a75ea5653
69 changed files with 1807 additions and 971 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue