| /**************************************************************************** |
| ** |
| ** Copyright (C) 2015 The Qt Company Ltd. |
| ** Contact: http://www.qt.io/licensing/ |
| ** |
| ** This file is part of the Qt Gamepad module |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL3$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see http://www.qt.io/terms-conditions. For further |
| ** information use the contact form at http://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or later as published by the Free |
| ** Software Foundation and appearing in the file LICENSE.GPL included in |
| ** the packaging of this file. Please review the following information to |
| ** ensure the GNU General Public License version 2.0 requirements will be |
| ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qgamepadmouseitem.h" |
| #include <cmath> |
| |
| #include <QtGamepad/QGamepad> |
| #include <QtGui/QWindow> |
| #include <QtQuick/QQuickWindow> |
| #include <QtGui/QGuiApplication> |
| |
| QT_BEGIN_NAMESPACE |
| |
| QGamepadMouseItem::QGamepadMouseItem(QQuickItem *parent) |
| : QQuickItem(parent) |
| , m_active(false) |
| , m_gamepad(nullptr) |
| , m_joystick(QGamepadMouseItem::LeftStick) |
| , m_deadZoneSize(0.1) |
| { |
| m_updateTimer.setInterval(16); |
| connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateMousePostion())); |
| } |
| |
| bool QGamepadMouseItem::active() const |
| { |
| return m_active; |
| } |
| |
| QGamepad *QGamepadMouseItem::gamepad() const |
| { |
| return m_gamepad; |
| } |
| |
| QGamepadMouseItem::GamepadJoystick QGamepadMouseItem::joystick() const |
| { |
| return m_joystick; |
| } |
| |
| double QGamepadMouseItem::deadZoneSize() const |
| { |
| return m_deadZoneSize; |
| } |
| |
| QPointF QGamepadMouseItem::mousePosition() const |
| { |
| return m_mousePosition; |
| } |
| |
| void QGamepadMouseItem::setActive(bool arg) |
| { |
| if (m_active != arg) { |
| m_active = arg; |
| if (m_active) { |
| m_deltaTimer.start(); |
| m_updateTimer.start(); |
| } else { |
| m_updateTimer.stop(); |
| m_deltaTimer.invalidate(); |
| } |
| emit activeChanged(arg); |
| } |
| } |
| |
| void QGamepadMouseItem::setGamepad(QGamepad *gamepad) |
| { |
| if (m_gamepad != gamepad) { |
| m_gamepad = gamepad; |
| emit gamepadChanged(gamepad); |
| } |
| } |
| |
| void QGamepadMouseItem::setJoystick(QGamepadMouseItem::GamepadJoystick joystick) |
| { |
| if (m_joystick != joystick) { |
| m_joystick = joystick; |
| emit joystickChanged(joystick); |
| } |
| } |
| |
| void QGamepadMouseItem::setDeadZoneSize(double size) |
| { |
| if (m_deadZoneSize != size) { |
| m_deadZoneSize = size; |
| emit deadZoneSizeChanged(size); |
| } |
| } |
| |
| void QGamepadMouseItem::mouseButtonPressed(int button) |
| { |
| processMouseButtonEvent(true, (Qt::MouseButton)button); |
| } |
| |
| void QGamepadMouseItem::mouseButtonReleased(int button) |
| { |
| processMouseButtonEvent(false, (Qt::MouseButton)button); |
| } |
| |
| void QGamepadMouseItem::updateMousePostion() |
| { |
| //Get the delta from the last call |
| qint64 delta = m_deltaTimer.restart(); |
| |
| //Don't bother when there is not gamepad to read from |
| if (!m_gamepad || !m_gamepad->isConnected()) |
| return; |
| |
| double xVelocity = 0.0; |
| double yVelocity = 0.0; |
| |
| if (m_joystick == QGamepadMouseItem::LeftStick) { |
| xVelocity = m_gamepad->axisLeftX(); |
| yVelocity = m_gamepad->axisLeftY(); |
| } else if (m_joystick == QGamepadMouseItem::RightStick) { |
| xVelocity = m_gamepad->axisRightX(); |
| yVelocity = m_gamepad->axisRightY(); |
| } else { //The greatest of both |
| if (std::abs(m_gamepad->axisLeftX()) > std::abs(m_gamepad->axisRightX())) |
| xVelocity = m_gamepad->axisLeftX(); |
| else |
| xVelocity = m_gamepad->axisRightX(); |
| if (std::abs(m_gamepad->axisLeftY()) > std::abs(m_gamepad->axisRightY())) |
| yVelocity = m_gamepad->axisLeftY(); |
| else |
| yVelocity = m_gamepad->axisRightY(); |
| } |
| |
| //Check for deadzone limits] |
| if (std::abs(xVelocity) < m_deadZoneSize) |
| xVelocity = 0.0; |
| if (std::abs(yVelocity) < m_deadZoneSize) |
| yVelocity = 0.0; |
| if (xVelocity == 0.0 && yVelocity == 0.0) |
| return; |
| |
| double newXPosition = m_mousePosition.x() + xVelocity * delta; |
| double newYPosition = m_mousePosition.y() + yVelocity * delta; |
| //Check bounds |
| if (newXPosition < 0) |
| newXPosition = 0; |
| else if (newXPosition > width()) |
| newXPosition = width(); |
| |
| if (newYPosition < 0) |
| newYPosition = 0; |
| else if (newYPosition > height()) |
| newYPosition = height(); |
| |
| m_mousePosition = QPointF(newXPosition, newYPosition); |
| emit mousePositionChanged(m_mousePosition); |
| } |
| |
| void QGamepadMouseItem::processMouseMoveEvent(QPointF position) |
| { |
| QMouseEvent *mouseEvent = new QMouseEvent(QEvent::MouseMove, mapToScene(position), Qt::NoButton, m_mouseButtons, Qt::NoModifier); |
| sendGeneratedMouseEvent(mouseEvent); |
| } |
| |
| void QGamepadMouseItem::processMouseButtonEvent(bool isPressed, Qt::MouseButton button) |
| { |
| QMouseEvent *event; |
| if (isPressed) { |
| m_mouseButtons |= button; |
| event = new QMouseEvent(QEvent::MouseButtonPress, mapToScene(m_mousePosition), button, m_mouseButtons, Qt::NoModifier); |
| } else { |
| m_mouseButtons ^= button; |
| event = new QMouseEvent(QEvent::MouseButtonRelease, mapToScene(m_mousePosition), button, m_mouseButtons, Qt::NoModifier); |
| } |
| |
| sendGeneratedMouseEvent(event); |
| } |
| |
| void QGamepadMouseItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) |
| { |
| QQuickItem::geometryChanged(newGeometry, oldGeometry); |
| |
| m_mousePosition = newGeometry.center(); |
| } |
| |
| void QGamepadMouseItem::sendGeneratedMouseEvent(QMouseEvent *event) |
| { |
| if (!m_active || !this->window()) { |
| delete event; |
| return; |
| } |
| |
| QWindow *window = qobject_cast<QWindow*>(this->window()); |
| if (window) |
| QGuiApplication::sendEvent(window, event); |
| } |
| |
| QT_END_NAMESPACE |