mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 13:20:27 -06: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:
@ -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
|
||||
|
15
Source/Core/InputCommon/ControllerEmu/Control/Control.cpp
Normal file
15
Source/Core/InputCommon/ControllerEmu/Control/Control.cpp
Normal file
@ -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
|
25
Source/Core/InputCommon/ControllerEmu/Control/Control.h
Normal file
25
Source/Core/InputCommon/ControllerEmu/Control/Control.h
Normal file
@ -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
|
15
Source/Core/InputCommon/ControllerEmu/Control/Input.cpp
Normal file
15
Source/Core/InputCommon/ControllerEmu/Control/Input.cpp
Normal file
@ -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
|
17
Source/Core/InputCommon/ControllerEmu/Control/Input.h
Normal file
17
Source/Core/InputCommon/ControllerEmu/Control/Input.h
Normal file
@ -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
|
15
Source/Core/InputCommon/ControllerEmu/Control/Output.cpp
Normal file
15
Source/Core/InputCommon/ControllerEmu/Control/Output.cpp
Normal file
@ -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
|
17
Source/Core/InputCommon/ControllerEmu/Control/Output.h
Normal file
17
Source/Core/InputCommon/ControllerEmu/Control/Output.h
Normal file
@ -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
|
@ -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
|
@ -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
|
@ -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
|
33
Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h
Normal file
33
Source/Core/InputCommon/ControllerEmu/ControlGroup/Buttons.h
Normal file
@ -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
|
@ -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
|
@ -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
|
@ -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
|
29
Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h
Normal file
29
Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.h
Normal file
@ -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
|
@ -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
|
@ -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
|
51
Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp
Normal file
51
Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp
Normal file
@ -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
|
22
Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h
Normal file
22
Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h
Normal file
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
19
Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h
Normal file
19
Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.h
Normal file
@ -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
|
99
Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp
Normal file
99
Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.cpp
Normal file
@ -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
|
22
Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h
Normal file
22
Source/Core/InputCommon/ControllerEmu/ControlGroup/Tilt.h
Normal file
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SETTING_RADIUS,
|
||||
SETTING_DEADZONE,
|
||||
};
|
||||
|
||||
const char* const named_directions[] = {"Up", "Down", "Left", "Right"};
|
||||
|
||||
class ControllerEmu
|
||||
namespace ControllerEmu
|
||||
{
|
||||
class ControlGroup;
|
||||
|
||||
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
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user