SPDX-FileCopyrightText: 2024 Arthur Kasimov <kodemeister@outlook.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "device.h"
#include "logging.h"
Device::Device(int deviceIndex, QObject *parent)
: QObject(parent)
, m_deviceIndex(deviceIndex)
{
}
Device::~Device()
{
close();
}
bool Device::open()
{
if (m_joystick != nullptr) {
return true;
}
m_joystick = SDL_JoystickOpen(m_deviceIndex);
m_controller = SDL_GameControllerOpen(m_deviceIndex);
if (!m_controller) {
m_leftTrigger = SDL_JoystickGetAxis(m_joystick, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
m_rightTrigger = SDL_JoystickGetAxis(m_joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
qCDebug(KCM_GAMECONTROLLER) << "Device" << m_deviceIndex << "is not a gamepad. using as joystick";
} else {
m_leftTrigger = SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT);
m_rightTrigger = SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT);
}
return m_joystick != nullptr;
}
void Device::close()
{
if (m_joystick == nullptr) {
return;
}
if (m_controller) {
SDL_GameControllerClose(m_controller);
m_controller = nullptr;
}
SDL_JoystickClose(m_joystick);
m_joystick = nullptr;
}
bool Device::isController() const
{
return m_controller != nullptr;
}
SDL_JoystickID Device::id() const
{
return SDL_JoystickInstanceID(m_joystick);
}
QString Device::name() const
{
return QString::fromLocal8Bit(SDL_JoystickName(m_joystick));
}
QString Device::path() const
{
return QString::fromLocal8Bit(SDL_JoystickPath(m_joystick));
}
bool Device::isVirtual() const
{
return SDL_JoystickIsVirtual(m_deviceIndex);
}
int Device::buttonCount() const
{
return SDL_JoystickNumButtons(m_joystick);
}
bool Device::buttonState(int index) const
{
if (m_controller) {
return SDL_GameControllerGetButton(m_controller, static_cast<SDL_GameControllerButton>(index)) != 0;
}
return SDL_JoystickGetButton(m_joystick, index) != 0;
}
int Device::axisCount() const
{
return SDL_JoystickNumAxes(m_joystick);
}
QVector2D Device::leftAxisValue() const
{
return m_leftAxis;
}
QVector2D Device::rightAxisValue() const
{
return m_rightAxis;
}
float Device::leftTriggerValue() const
{
return m_leftTrigger;
}
float Device::rightTriggerValue() const
{
return m_rightTrigger;
}
int Device::hatCount() const
{
return SDL_JoystickNumHats(m_joystick);
}
QVector2D Device::hatPosition(int index) const
{
const Uint8 hat = SDL_JoystickGetHat(m_joystick, index);
QVector2D position;
if ((hat & SDL_HAT_LEFT) != 0) {
position.setX(std::numeric_limits<Sint16>::min());
} else if ((hat & SDL_HAT_RIGHT) != 0) {
position.setX(std::numeric_limits<Sint16>::max());
}
if ((hat & SDL_HAT_UP) != 0) {
position.setY(std::numeric_limits<Sint16>::min());
} else if ((hat & SDL_HAT_DOWN) != 0) {
position.setY(std::numeric_limits<Sint16>::max());
}
return position;
}
void Device::onButtonEvent(const SDL_JoyButtonEvent &event)
{
Q_EMIT buttonStateChanged(event.button);
}
void Device::onControllerButtonEvent(const SDL_ControllerButtonEvent &event)
{
Q_EMIT buttonStateChanged(event.button);
}
void Device::onAxisEvent(const SDL_JoyAxisEvent &event)
{
const float value = static_cast<float>(event.value) / std::numeric_limits<Sint16>::max();
if (event.axis == SDL_CONTROLLER_AXIS_LEFTX) {
m_leftAxis.setX(value);
Q_EMIT leftAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_LEFTY) {
m_leftAxis.setY(value);
Q_EMIT leftAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTX) {
m_rightAxis.setX(value);
Q_EMIT rightAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTY) {
m_rightAxis.setY(value);
Q_EMIT rightAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) {
m_leftTrigger = value;
Q_EMIT leftTriggerChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
m_rightTrigger = value;
Q_EMIT rightTriggerChanged();
}
}
void Device::onControllerAxisEvent(const SDL_ControllerAxisEvent &event)
{
const float value = static_cast<float>(event.value) / std::numeric_limits<Sint16>::max();
if (event.axis == SDL_CONTROLLER_AXIS_LEFTX) {
m_leftAxis.setX(value);
Q_EMIT leftAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_LEFTY) {
m_leftAxis.setY(value);
Q_EMIT leftAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTX) {
m_rightAxis.setX(value);
Q_EMIT rightAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_RIGHTY) {
m_rightAxis.setY(value);
Q_EMIT rightAxisChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT) {
m_leftTrigger = value;
Q_EMIT leftTriggerChanged();
} else if (event.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
m_rightTrigger = value;
Q_EMIT rightTriggerChanged();
}
}
void Device::onHatEvent(const SDL_JoyHatEvent &event)
{
Q_EMIT hatPositionChanged(event.hat);
}
#include "moc_device.cpp"