#pragma once
#include "input_types.h"
#include "settings.h"
#include "types.h"
#include <array>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <tuple>
#include <vector>
class SettingsInterface;
class StateWrapper;
class Controller
{
public:
struct ControllerBindingInfo
{
const char* name;
const char* display_name;
const char* icon_name;
u32 bind_index;
InputBindingInfo::Type type;
GenericInputBinding generic_mapping;
};
struct ControllerInfo
{
ControllerType type;
const char* name;
const char* display_name;
const char* icon_name;
std::span<const ControllerBindingInfo> bindings;
std::span<const SettingInfo> settings;
std::string_view GetDisplayName() const;
std::string_view GetBindingDisplayName(const ControllerBindingInfo& bi) const;
};
static constexpr float DEFAULT_STICK_DEADZONE = 0.0f;
static constexpr float DEFAULT_STICK_SENSITIVITY = 1.33f;
static constexpr float DEFAULT_BUTTON_DEADZONE = 0.25f;
explicit Controller(u32 index);
virtual ~Controller();
virtual ControllerType GetType() const = 0;
virtual void Reset();
virtual bool DoState(StateWrapper& sw, bool apply_input_state);
virtual void ResetTransferState();
virtual bool Transfer(const u8 data_in, u8* data_out);
virtual float GetBindState(u32 index) const;
virtual void SetBindState(u32 index, float value);
virtual u32 GetButtonStateBits() const;
virtual float GetVibrationMotorState(u32 index) const;
virtual bool InAnalogMode() const;
virtual std::optional<u32> GetAnalogInputBytes() const;
virtual u32 GetInputOverlayIconColor() const;
virtual void LoadSettings(const SettingsInterface& si, const char* section, bool initial);
static std::unique_ptr<Controller> Create(ControllerType type, u32 index);
static const std::array<const ControllerInfo*, static_cast<size_t>(ControllerType::Count)>& GetControllerInfoList();
static const ControllerInfo& GetControllerInfo(ControllerType type);
static const ControllerInfo* GetControllerInfo(std::string_view name);
static float ApplyAnalogDeadzoneSensitivity(float deadzone, float sensitivity, float value)
{
return (value < deadzone) ? 0.0f : ((value - deadzone) / (1.0f - deadzone) * sensitivity);
}
static bool InCircularDeadzone(float deadzone, float pos_x, float pos_y);
static std::tuple<u32, u32> ConvertPadToPortAndSlot(u32 index);
static u32 ConvertPortAndSlotToPad(u32 port, u32 slot);
static bool PadIsMultitapSlot(u32 index);
static bool PortAndSlotIsMultitap(u32 port, u32 slot);
static std::string GetSettingsSection(u32 pad);
static const char* GetPortDisplayName(u32 port, u32 slot, bool mtap);
static const char* GetPortDisplayName(u32 index);
static const std::array<u32, NUM_CONTROLLER_AND_CARD_PORTS> PortDisplayOrder;
static bool CanStartInAnalogMode(ControllerType ctype);
protected:
u32 m_index;
};