a-la-karte/src/gamepadmanager.cpp

233 lines
5.3 KiB
C++
Raw Normal View History

// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2024 A-La-Karte Contributors
#include "gamepadmanager.h"
#if defined(ALAKARTE_HAVE_QT_GAMEPAD)
#include <QGamepad>
#include <QGamepadManager>
GamepadManager *GamepadManager::s_instance = nullptr;
GamepadManager::GamepadManager(QObject *parent)
: QObject(parent)
{
auto *manager = QGamepadManager::instance();
connect(manager, &QGamepadManager::gamepadConnected, this, &GamepadManager::onGamepadConnected);
connect(manager, &QGamepadManager::gamepadDisconnected, this, &GamepadManager::onGamepadDisconnected);
m_repeatTimer.setInterval(150);
connect(&m_repeatTimer, &QTimer::timeout, this, &GamepadManager::processInput);
const auto gamepads = manager->connectedGamepads();
if (!gamepads.isEmpty()) {
setupGamepad(gamepads.first());
}
}
GamepadManager *GamepadManager::instance()
{
if (!s_instance) {
s_instance = new GamepadManager();
}
return s_instance;
}
GamepadManager *GamepadManager::create(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
Q_UNUSED(scriptEngine)
return instance();
}
bool GamepadManager::connected() const
{
return m_connected;
}
bool GamepadManager::active() const
{
return m_active;
}
void GamepadManager::setActive(bool active)
{
if (m_active != active) {
m_active = active;
Q_EMIT activeChanged();
}
}
void GamepadManager::onGamepadConnected(int deviceId)
{
if (!m_gamepad) {
setupGamepad(deviceId);
}
}
void GamepadManager::onGamepadDisconnected(int deviceId)
{
if (m_gamepad && m_gamepad->deviceId() == deviceId) {
m_gamepad->deleteLater();
m_gamepad = nullptr;
m_connected = false;
m_repeatTimer.stop();
Q_EMIT connectedChanged();
const auto gamepads = QGamepadManager::instance()->connectedGamepads();
if (!gamepads.isEmpty()) {
setupGamepad(gamepads.first());
}
}
}
void GamepadManager::setupGamepad(int deviceId)
{
m_gamepad = new QGamepad(deviceId, this);
m_connected = true;
Q_EMIT connectedChanged();
connect(m_gamepad, &QGamepad::axisLeftYChanged, this, [this](double value) {
if (qAbs(value) > 0.5) {
setActive(true);
if (value < -0.5) {
Q_EMIT navigateUp();
} else {
Q_EMIT navigateDown();
}
m_repeatTimer.start();
} else {
m_repeatTimer.stop();
}
});
connect(m_gamepad, &QGamepad::axisLeftXChanged, this, [this](double value) {
if (qAbs(value) > 0.5) {
setActive(true);
if (value < -0.5) {
Q_EMIT navigateLeft();
} else {
Q_EMIT navigateRight();
}
m_repeatTimer.start();
} else {
m_repeatTimer.stop();
}
});
connect(m_gamepad, &QGamepad::buttonAChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT selectPressed();
}
});
connect(m_gamepad, &QGamepad::buttonBChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT backPressed();
}
});
connect(m_gamepad, &QGamepad::buttonStartChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT menuPressed();
}
});
connect(m_gamepad, &QGamepad::buttonYChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT searchPressed();
}
});
connect(m_gamepad, &QGamepad::buttonUpChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT navigateUp();
}
});
connect(m_gamepad, &QGamepad::buttonDownChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT navigateDown();
}
});
connect(m_gamepad, &QGamepad::buttonLeftChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT navigateLeft();
}
});
connect(m_gamepad, &QGamepad::buttonRightChanged, this, [this](bool pressed) {
if (pressed) {
setActive(true);
Q_EMIT navigateRight();
}
});
}
void GamepadManager::processInput()
{
if (!m_gamepad)
return;
double y = m_gamepad->axisLeftY();
double x = m_gamepad->axisLeftX();
if (y < -0.5) {
Q_EMIT navigateUp();
} else if (y > 0.5) {
Q_EMIT navigateDown();
}
if (x < -0.5) {
Q_EMIT navigateLeft();
} else if (x > 0.5) {
Q_EMIT navigateRight();
}
}
#else
GamepadManager *GamepadManager::s_instance = nullptr;
GamepadManager::GamepadManager(QObject *parent)
: QObject(parent)
{
}
GamepadManager *GamepadManager::instance()
{
if (!s_instance) {
s_instance = new GamepadManager();
}
return s_instance;
}
GamepadManager *GamepadManager::create(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)
Q_UNUSED(scriptEngine)
return instance();
}
bool GamepadManager::connected() const
{
return false;
}
bool GamepadManager::active() const
{
return false;
}
#endif