HostInterface: Support per-controller-type settings

This commit is contained in:
Connor McLaughlin
2020-07-01 00:33:45 +10:00
parent f3b2953e40
commit 4dc9e10777
17 changed files with 247 additions and 7 deletions

View File

@ -1,6 +1,7 @@
#include "analog_controller.h"
#include "common/log.h"
#include "common/state_wrapper.h"
#include "common/string_util.h"
#include "host_interface.h"
#include "system.h"
Log_SetChannel(AnalogController);
@ -23,6 +24,9 @@ void AnalogController::Reset()
m_rumble_unlocked = false;
m_configuration_mode = false;
m_command_param = 0;
if (m_auto_enable_analog)
SetAnalogMode(true);
}
bool AnalogController::DoState(StateWrapper& sw)
@ -474,3 +478,18 @@ u32 AnalogController::StaticGetVibrationMotorCount()
{
return NUM_MOTORS;
}
Controller::SettingList AnalogController::StaticGetSettings()
{
static constexpr std::array<SettingInfo, 1> settings = {
{{SettingInfo::Type::Boolean, "AutoEnableAnalog", "Enable Analog Mode on Reset",
"Automatically enables analog mode when the console is reset/powered on.", "false"}}};
return SettingList(settings.begin(), settings.end());
}
void AnalogController::LoadSettings(HostInterface* host_interface, const char* section)
{
Controller::LoadSettings(host_interface, section);
m_auto_enable_analog = host_interface->GetBooleanSettingValue(section, "AutoEnableAnalog", false);
}

View File

@ -50,6 +50,7 @@ public:
static AxisList StaticGetAxisNames();
static ButtonList StaticGetButtonNames();
static u32 StaticGetVibrationMotorCount();
static SettingList StaticGetSettings();
ControllerType GetType() const override;
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
@ -70,6 +71,8 @@ public:
u32 GetVibrationMotorCount() const override;
float GetVibrationMotorStrength(u32 motor) override;
void LoadSettings(HostInterface* host_interface, const char* section) override;
private:
using MotorState = std::array<u8, NUM_MOTORS>;
@ -132,6 +135,8 @@ private:
System* m_system;
u32 m_index;
bool m_auto_enable_analog = false;
bool m_analog_mode = false;
bool m_analog_locked = false;
bool m_rumble_unlocked = false;

View File

@ -3,8 +3,8 @@
#include "common/state_wrapper.h"
#include "digital_controller.h"
#include "namco_guncon.h"
#include "playstation_mouse.h"
#include "negcon.h"
#include "playstation_mouse.h"
Controller::Controller() = default;
@ -39,6 +39,8 @@ float Controller::GetVibrationMotorStrength(u32 motor)
return 0.0f;
}
void Controller::LoadSettings(HostInterface* host_interface, const char* section) {}
std::unique_ptr<Controller> Controller::Create(System* system, ControllerType type, u32 index)
{
switch (type)
@ -198,3 +200,15 @@ std::optional<s32> Controller::GetButtonCodeByName(ControllerType type, std::str
return std::nullopt;
}
}
Controller::SettingList Controller::GetSettings(ControllerType type)
{
switch (type)
{
case ControllerType::AnalogController:
return AnalogController::StaticGetSettings();
default:
return {};
}
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "settings.h"
#include "types.h"
#include <memory>
#include <optional>
@ -8,12 +9,14 @@
class StateWrapper;
class System;
class HostInterface;
class Controller
{
public:
using ButtonList = std::vector<std::pair<std::string, s32>>;
using AxisList = std::vector<std::pair<std::string, s32>>;
using SettingList = std::vector<SettingInfo>;
Controller();
virtual ~Controller();
@ -48,6 +51,9 @@ public:
/// Queries the state of the specified vibration motor. Values are normalized from 0..1.
virtual float GetVibrationMotorStrength(u32 motor);
/// Loads/refreshes any per-controller settings.
virtual void LoadSettings(HostInterface* host_interface, const char* section);
/// Creates a new controller of the specified type.
static std::unique_ptr<Controller> Create(System* system, ControllerType type, u32 index);
@ -65,4 +71,7 @@ public:
/// Returns the number of vibration motors.
static u32 GetVibrationMotorCount(ControllerType type);
/// Returns settings for the controller.
static SettingList GetSettings(ControllerType type);
};

View File

@ -480,6 +480,9 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings)
OnControllerTypeChanged(i);
}
if (m_system && !controllers_updated)
m_system->UpdateControllerSettings();
}
if (m_display && m_settings.display_linear_filtering != old_settings.display_linear_filtering)
@ -566,6 +569,36 @@ std::string HostInterface::GetGameMemoryCardPath(const char* game_code, u32 slot
return GetUserDirectoryRelativePath("memcards/%s_%d.mcd", game_code, slot + 1);
}
bool HostInterface::GetBooleanSettingValue(const char* section, const char* key, bool default_value /*= false*/)
{
std::string value = GetSettingValue(section, key, "");
if (value.empty())
return default_value;
std::optional<bool> bool_value = StringUtil::FromChars<bool>(value);
return bool_value.value_or(default_value);
}
bool HostInterface::GetIntegerSettingValue(const char* section, const char* key, s32 default_value /*= 0*/)
{
std::string value = GetSettingValue(section, key, "");
if (value.empty())
return default_value;
std::optional<s32> int_value = StringUtil::FromChars<s32>(value);
return int_value.value_or(default_value);
}
bool HostInterface::GetFloatSettingValue(const char* section, const char* key, float default_value /*= 0.0f*/)
{
std::string value = GetSettingValue(section, key, "");
if (value.empty())
return default_value;
std::optional<float> float_value = StringUtil::FromChars<float>(value);
return float_value.value_or(default_value);
}
void HostInterface::ToggleSoftwareRendering()
{
if (!m_system || m_settings.gpu_renderer == GPURenderer::Software)

View File

@ -91,7 +91,8 @@ public:
/// Displays a loading screen with the logo, rendered with ImGui. Use when executing possibly-time-consuming tasks
/// such as compiling shaders when starting up.
virtual void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1, int progress_value = -1);
virtual void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1,
int progress_value = -1);
/// Retrieves information about specified game from game list.
virtual void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title);
@ -102,7 +103,20 @@ public:
/// Returns the default path to a memory card for a specific game.
virtual std::string GetGameMemoryCardPath(const char* game_code, u32 slot) const;
/// Enables the software cursor. Can be called multiple times, but must be matched by a call to DisableSoftwareCursor().
/// Returns a setting value from the configuration.
virtual std::string GetSettingValue(const char* section, const char* key, const char* default_value = "") = 0;
/// Returns a boolean setting from the configuration.
bool GetBooleanSettingValue(const char* section, const char* key, bool default_value = false);
/// Returns an integer setting from the configuration.
bool GetIntegerSettingValue(const char* section, const char* key, s32 default_value = 0);
/// Returns a float setting from the configuration.
bool GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f);
/// Enables the software cursor. Can be called multiple times, but must be matched by a call to
/// DisableSoftwareCursor().
void EnableSoftwareCursor();
/// Disables the software cursor, preventing it from being renderered.

View File

@ -4,6 +4,62 @@
#include <algorithm>
#include <array>
const char* SettingInfo::StringDefaultValue() const
{
return default_value ? default_value : "";
}
bool SettingInfo::BooleanDefaultValue() const
{
return default_value ? StringUtil::FromChars<bool>(default_value).value_or(false) : false;
}
s32 SettingInfo::IntegerDefaultValue() const
{
return default_value ? StringUtil::FromChars<s32>(default_value).value_or(0) : 0;
}
s32 SettingInfo::IntegerMinValue() const
{
static constexpr s32 fallback_value = std::numeric_limits<s32>::min();
return min_value ? StringUtil::FromChars<s32>(min_value).value_or(fallback_value) : fallback_value;
}
s32 SettingInfo::IntegerMaxValue() const
{
static constexpr s32 fallback_value = std::numeric_limits<s32>::max();
return max_value ? StringUtil::FromChars<s32>(max_value).value_or(fallback_value) : fallback_value;
}
s32 SettingInfo::IntegerStepValue() const
{
static constexpr s32 fallback_value = 1;
return step_value ? StringUtil::FromChars<s32>(step_value).value_or(fallback_value) : fallback_value;
}
float SettingInfo::FloatDefaultValue() const
{
return default_value ? StringUtil::FromChars<float>(default_value).value_or(0.0f) : 0.0f;
}
float SettingInfo::FloatMinValue() const
{
static constexpr float fallback_value = std::numeric_limits<float>::min();
return min_value ? StringUtil::FromChars<float>(min_value).value_or(fallback_value) : fallback_value;
}
float SettingInfo::FloatMaxValue() const
{
static constexpr float fallback_value = std::numeric_limits<float>::max();
return max_value ? StringUtil::FromChars<float>(max_value).value_or(fallback_value) : fallback_value;
}
float SettingInfo::FloatStepValue() const
{
static constexpr float fallback_value = 0.1f;
return step_value ? StringUtil::FromChars<float>(step_value).value_or(fallback_value) : fallback_value;
}
Settings::Settings() = default;
bool Settings::HasAnyPerGameMemoryCards() const

View File

@ -30,6 +30,38 @@ public:
virtual void DeleteValue(const char* section, const char* key) = 0;
};
struct SettingInfo
{
enum class Type
{
Boolean,
Integer,
Float,
String,
Path,
};
Type type;
const char* key;
const char* visible_name;
const char* description;
const char* default_value;
const char* min_value;
const char* max_value;
const char* step_value;
const char* StringDefaultValue() const;
bool BooleanDefaultValue() const;
s32 IntegerDefaultValue() const;
s32 IntegerMinValue() const;
s32 IntegerMaxValue() const;
s32 IntegerStepValue() const;
float FloatDefaultValue() const;
float FloatMinValue() const;
float FloatMaxValue() const;
float FloatStepValue() const;
};
struct Settings
{
Settings();

View File

@ -832,11 +832,24 @@ void System::UpdateControllers()
{
std::unique_ptr<Controller> controller = Controller::Create(this, type, i);
if (controller)
{
controller->LoadSettings(m_host_interface, TinyString::FromFormat("Controller%u", i + 1u));
m_pad->SetController(i, std::move(controller));
}
}
}
}
void System::UpdateControllerSettings()
{
for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
{
Controller* controller = m_pad->GetController(i);
if (controller)
controller->LoadSettings(m_host_interface, TinyString::FromFormat("Controller%u", i + 1u));
}
}
void System::UpdateMemoryCards()
{
const Settings& settings = m_host_interface->GetSettings();

View File

@ -139,6 +139,7 @@ public:
// Access controllers for simulating input.
Controller* GetController(u32 slot) const;
void UpdateControllers();
void UpdateControllerSettings();
void UpdateMemoryCards();
bool HasMedia() const;