Add all the files

This commit is contained in:
Exzap 2022-08-22 22:21:23 +02:00
parent e3db07a16a
commit d60742f52b
1445 changed files with 430238 additions and 0 deletions

View file

@ -0,0 +1,151 @@
#include "input/api/XInput/XInputController.h"
XInputController::XInputController(uint32 index)
: base_type(fmt::format("{}", index), fmt::format("Controller {}", index + 1))
{
if (index >= XUSER_MAX_COUNT)
throw std::runtime_error(fmt::format("invalid xinput index {} (must be smaller than {})", index,
XUSER_MAX_COUNT));
m_index = index;
m_settings.axis.deadzone = m_settings.rotation.deadzone = m_settings.trigger.deadzone = 0.15f;
}
bool XInputController::connect()
{
if (m_connected)
return true;
m_has_battery = false;
XINPUT_CAPABILITIES caps{};
m_connected = m_provider->m_XInputGetCapabilities(m_index, XINPUT_FLAG_GAMEPAD, &caps) !=
ERROR_DEVICE_NOT_CONNECTED;
if (!m_connected) return false;
m_has_rumble = (caps.Vibration.wLeftMotorSpeed > 0) || (caps.Vibration.wRightMotorSpeed > 0);
if (m_provider->m_XInputGetBatteryInformation)
{
XINPUT_BATTERY_INFORMATION battery{};
if (m_provider->m_XInputGetBatteryInformation(m_index, BATTERY_DEVTYPE_GAMEPAD, &battery) == ERROR_SUCCESS)
{
m_has_battery = (battery.BatteryType == BATTERY_TYPE_ALKALINE || battery.BatteryType ==
BATTERY_TYPE_NIMH);
}
}
return m_connected;
}
bool XInputController::is_connected()
{
return m_connected;
}
void XInputController::start_rumble()
{
if (!has_rumble() || m_settings.rumble <= 0)
return;
XINPUT_VIBRATION vibration;
vibration.wLeftMotorSpeed = static_cast<WORD>(m_settings.rumble * std::numeric_limits<uint16>::max());
vibration.wRightMotorSpeed = static_cast<WORD>(m_settings.rumble * std::numeric_limits<uint16>::max());
m_provider->m_XInputSetState(m_index, &vibration);
}
void XInputController::stop_rumble()
{
if (!has_rumble())
return;
XINPUT_VIBRATION vibration{};
m_provider->m_XInputSetState(m_index, &vibration);
}
bool XInputController::has_low_battery()
{
if (!has_battery())
return false;
XINPUT_BATTERY_INFORMATION battery{};
if (m_provider->m_XInputGetBatteryInformation(m_index, BATTERY_DEVTYPE_GAMEPAD, &battery) == ERROR_SUCCESS)
{
return (battery.BatteryType == BATTERY_TYPE_ALKALINE || battery.BatteryType == BATTERY_TYPE_NIMH) && battery
.BatteryLevel <= BATTERY_LEVEL_LOW;
}
return false;
}
std::string XInputController::get_button_name(uint64 button) const
{
switch (1ULL << button)
{
case XINPUT_GAMEPAD_A: return "A";
case XINPUT_GAMEPAD_B: return "B";
case XINPUT_GAMEPAD_X: return "X";
case XINPUT_GAMEPAD_Y: return "Y";
case XINPUT_GAMEPAD_LEFT_SHOULDER: return "L";
case XINPUT_GAMEPAD_RIGHT_SHOULDER: return "R";
case XINPUT_GAMEPAD_START: return "Start";
case XINPUT_GAMEPAD_BACK: return "Select";
case XINPUT_GAMEPAD_LEFT_THUMB: return "L-Stick";
case XINPUT_GAMEPAD_RIGHT_THUMB: return "R-Stick";
case XINPUT_GAMEPAD_DPAD_UP: return "DPAD-Up";
case XINPUT_GAMEPAD_DPAD_DOWN: return "DPAD-Down";
case XINPUT_GAMEPAD_DPAD_LEFT: return "DPAD-Left";
case XINPUT_GAMEPAD_DPAD_RIGHT: return "DPAD-Right";
}
return Controller::get_button_name(button);
}
ControllerState XInputController::raw_state()
{
ControllerState result{};
if (!m_connected)
return result;
XINPUT_STATE state;
if (m_provider->m_XInputGetState(m_index, &state) != ERROR_SUCCESS)
{
m_connected = false;
return result;
}
// Buttons
result.buttons = state.Gamepad.wButtons;
if (state.Gamepad.sThumbLX > 0)
result.axis.x = (float)state.Gamepad.sThumbLX / std::numeric_limits<sint16>::max();
else if (state.Gamepad.sThumbLX < 0)
result.axis.x = (float)-state.Gamepad.sThumbLX / std::numeric_limits<sint16>::min();
if (state.Gamepad.sThumbLY > 0)
result.axis.y = (float)state.Gamepad.sThumbLY / std::numeric_limits<sint16>::max();
else if (state.Gamepad.sThumbLY < 0)
result.axis.y = (float)-state.Gamepad.sThumbLY / std::numeric_limits<sint16>::min();
// Right Stick
if (state.Gamepad.sThumbRX > 0)
result.rotation.x = (float)state.Gamepad.sThumbRX / std::numeric_limits<sint16>::max();
else if (state.Gamepad.sThumbRX < 0)
result.rotation.x = (float)-state.Gamepad.sThumbRX / std::numeric_limits<sint16>::min();
if (state.Gamepad.sThumbRY > 0)
result.rotation.y = (float)state.Gamepad.sThumbRY / std::numeric_limits<sint16>::max();
else if (state.Gamepad.sThumbRY < 0)
result.rotation.y = (float)-state.Gamepad.sThumbRY / std::numeric_limits<sint16>::min();
// Trigger
result.trigger.x = (float)state.Gamepad.bLeftTrigger / std::numeric_limits<uint8>::max();
result.trigger.y = (float)state.Gamepad.bRightTrigger / std::numeric_limits<uint8>::max();
return result;
}

View file

@ -0,0 +1,38 @@
#pragma once
#include "input/api/XInput/XInputControllerProvider.h"
#include "input/api/Controller.h"
class XInputController : public Controller<XInputControllerProvider>
{
public:
XInputController(uint32 index);
std::string_view api_name() const override
{
static_assert(to_string(InputAPI::XInput) == "XInput");
return to_string(InputAPI::XInput);
}
InputAPI::Type api() const override { return InputAPI::XInput; }
bool connect() override;
bool is_connected() override;
bool has_rumble() override { return m_has_rumble; }
bool has_battery() override { return m_has_battery; }
bool has_low_battery() override;
void start_rumble() override;
void stop_rumble() override;
std::string get_button_name(uint64 button) const override;
protected:
ControllerState raw_state() override;
private:
uint32 m_index;
bool m_connected = false;
bool m_has_battery = false;
bool m_has_rumble = false;
};

View file

@ -0,0 +1,57 @@
#include <Windows.h>
#include "input/api/XInput/XInputControllerProvider.h"
#include "input/api/XInput/XInputController.h"
XInputControllerProvider::XInputControllerProvider()
{
// try to load newest to oldest
m_module = LoadLibraryA("XInput1_4.DLL");
if (!m_module)
{
m_module = LoadLibraryA("XInput1_3.DLL");
if (!m_module)
{
m_module = LoadLibraryA("XInput9_1_0.dll");
if (!m_module)
throw std::runtime_error("can't load any xinput dll");
}
}
#define GET_XINPUT_PROC(__FUNC__) m_##__FUNC__ = (decltype(m_##__FUNC__))GetProcAddress(m_module, #__FUNC__)
GET_XINPUT_PROC(XInputGetCapabilities);
GET_XINPUT_PROC(XInputGetState);
GET_XINPUT_PROC(XInputSetState);
if (!m_XInputGetCapabilities || !m_XInputGetState || !m_XInputSetState)
{
FreeLibrary(m_module);
throw std::runtime_error("can't find necessary xinput functions");
}
// only available in XInput1_4 and XInput1_3
GET_XINPUT_PROC(XInputGetBatteryInformation);
#undef GET_XINPUT_PROC
}
XInputControllerProvider::~XInputControllerProvider()
{
if (m_module)
FreeLibrary(m_module);
}
std::vector<std::shared_ptr<ControllerBase>> XInputControllerProvider::get_controllers()
{
std::vector<std::shared_ptr<ControllerBase>> result;
for(DWORD i = 0; i < XUSER_MAX_COUNT; ++i)
{
XINPUT_CAPABILITIES caps;
if (m_XInputGetCapabilities(i, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS)
{
result.emplace_back(std::make_shared<XInputController>(i));
}
}
return result;
}

View file

@ -0,0 +1,32 @@
#pragma once
#if BOOST_OS_WINDOWS
#include "input/api/ControllerProvider.h"
#include <Xinput.h>
#ifndef HAS_XINPUT
#define HAS_XINPUT 1
#endif
class XInputControllerProvider : public ControllerProviderBase
{
friend class XInputController;
public:
XInputControllerProvider();
~XInputControllerProvider() override;
inline static InputAPI::Type kAPIType = InputAPI::XInput;
InputAPI::Type api() const override { return kAPIType; }
std::vector<std::shared_ptr<ControllerBase>> get_controllers() override;
private:
HMODULE m_module = nullptr;
decltype(&XInputGetBatteryInformation) m_XInputGetBatteryInformation;
decltype(&XInputGetCapabilities) m_XInputGetCapabilities;
decltype(&XInputSetState) m_XInputSetState;
decltype(&XInputGetState) m_XInputGetState;
};
#endif