// 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 #include 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