add joysick support and state feedback
This commit is contained in:
parent
840cec975d
commit
1f36522492
479
src/QJoysticks.cpp
Normal file
479
src/QJoysticks.cpp
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include "QJoysticks.h"
|
||||
#include "jsbackend/SDL_Joysticks.h"
|
||||
#include "jsbackend/VirtualJoystick.h"
|
||||
|
||||
QJoysticks::QJoysticks()
|
||||
{
|
||||
/* Initialize input methods */
|
||||
m_sdlJoysticks = new SDL_Joysticks(this);
|
||||
m_virtualJoystick = new VirtualJoystick(this);
|
||||
|
||||
/* Configure SDL joysticks */
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::POVEvent, this, &QJoysticks::POVEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::axisEvent, this, &QJoysticks::axisEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::buttonEvent, this, &QJoysticks::buttonEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::countChanged, this, &QJoysticks::updateInterfaces);
|
||||
|
||||
/* Configure virtual joysticks */
|
||||
connect(virtualJoystick(), &VirtualJoystick::povEvent, this, &QJoysticks::POVEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::axisEvent, this, &QJoysticks::axisEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::buttonEvent, this, &QJoysticks::buttonEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::enabledChanged, this, &QJoysticks::updateInterfaces);
|
||||
|
||||
/* React to own signals to create QML signals */
|
||||
connect(this, &QJoysticks::POVEvent, this, &QJoysticks::onPOVEvent);
|
||||
connect(this, &QJoysticks::axisEvent, this, &QJoysticks::onAxisEvent);
|
||||
connect(this, &QJoysticks::buttonEvent, this, &QJoysticks::onButtonEvent);
|
||||
|
||||
/* Configure the settings */
|
||||
m_sortJoyticks = 0;
|
||||
m_settings = new QSettings(qApp->organizationName(), qApp->applicationName());
|
||||
m_settings->beginGroup("Blacklisted Joysticks");
|
||||
}
|
||||
|
||||
QJoysticks::~QJoysticks()
|
||||
{
|
||||
delete m_settings;
|
||||
delete m_sdlJoysticks;
|
||||
delete m_virtualJoystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only instance of this class
|
||||
*/
|
||||
QJoysticks *QJoysticks::getInstance()
|
||||
{
|
||||
static QJoysticks joysticks;
|
||||
return &joysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of joysticks that are attached to the computer and/or
|
||||
* registered with the \c QJoysticks system.
|
||||
*
|
||||
* \note This count also includes the virtual joystick (if its enabled)
|
||||
*/
|
||||
int QJoysticks::count() const
|
||||
{
|
||||
return inputDevices().count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of joysticks that are not blacklisted.
|
||||
* This can be considered the "effective" number of joysticks.
|
||||
*/
|
||||
int QJoysticks::nonBlacklistedCount()
|
||||
{
|
||||
int cnt = count();
|
||||
|
||||
for (int i = 0; i < count(); ++i)
|
||||
if (isBlacklisted(i))
|
||||
--cnt;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list with the names of all registered joystick.
|
||||
*
|
||||
* \note This list also includes the blacklisted joysticks
|
||||
* \note This list also includes the virtual joystick (if its enabled)
|
||||
*/
|
||||
QStringList QJoysticks::deviceNames() const
|
||||
{
|
||||
QStringList names;
|
||||
|
||||
foreach (QJoystickDevice *joystick, inputDevices())
|
||||
names.append(joystick->name);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the POV value for the given joystick \a index and \a pov ID
|
||||
*/
|
||||
int QJoysticks::getPOV(const int index, const int pov)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->povs.at(pov);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis value for the given joystick \a index and \a axis ID
|
||||
*/
|
||||
double QJoysticks::getAxis(const int index, const int axis)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->axes.at(axis);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the button value for the given joystick \a index and \a button ID
|
||||
*/
|
||||
bool QJoysticks::getButton(const int index, const int button)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->buttons.at(button);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of axes that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumAxes(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->axes.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of POVs that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumPOVs(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->povs.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of buttons that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumButtons(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->buttons.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the joystick at the given \a index is blacklisted.
|
||||
*/
|
||||
bool QJoysticks::isBlacklisted(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return inputDevices().at(index)->blacklisted;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the joystick at the given \a index is valid, otherwise,
|
||||
* the function returns \c false and warns the user through the console.
|
||||
*/
|
||||
bool QJoysticks::joystickExists(const int index)
|
||||
{
|
||||
return (index >= 0) && (count() > index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the given joystick
|
||||
*/
|
||||
QString QJoysticks::getName(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return m_devices.at(index)->name;
|
||||
|
||||
return "Invalid Joystick";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the SDL joysticks system.
|
||||
* This can be used if you need to get more information regarding the joysticks
|
||||
* registered and managed with SDL.
|
||||
*/
|
||||
SDL_Joysticks *QJoysticks::sdlJoysticks() const
|
||||
{
|
||||
return m_sdlJoysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the virtual joystick system.
|
||||
* This can be used if you need to get more information regarding the virtual
|
||||
* joystick or want to change its properties directly.
|
||||
*
|
||||
* \note You can also change the properties of the virtual joysticks using the
|
||||
* functions of the \c QJoysticks system class
|
||||
*/
|
||||
VirtualJoystick *QJoysticks::virtualJoystick() const
|
||||
{
|
||||
return m_virtualJoystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the device at the given \a index.
|
||||
*/
|
||||
QJoystickDevice *QJoysticks::getInputDevice(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return inputDevices().at(index);
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to a list containing all registered joysticks.
|
||||
* This can be used for advanced hacks or just to get all properties of each
|
||||
* joystick.
|
||||
*/
|
||||
QList<QJoystickDevice *> QJoysticks::inputDevices() const
|
||||
{
|
||||
return m_devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* If \a sort is set to true, then the device list will put all blacklisted
|
||||
* joysticks at the end of the list
|
||||
*/
|
||||
void QJoysticks::setSortJoysticksByBlacklistState(bool sort)
|
||||
{
|
||||
if (m_sortJoyticks != sort)
|
||||
{
|
||||
m_sortJoyticks = sort;
|
||||
updateInterfaces();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blacklists or whitelists the joystick at the given \a index.
|
||||
*
|
||||
* \note This function does not have effect if the given joystick does not exist
|
||||
* \note Once the joystick is blacklisted, the joystick list will be updated
|
||||
*/
|
||||
void QJoysticks::setBlacklisted(const int index, bool blacklisted)
|
||||
{
|
||||
Q_ASSERT(joystickExists(index));
|
||||
|
||||
/* Netrualize the joystick */
|
||||
if (blacklisted)
|
||||
{
|
||||
for (int i = 0; i < getNumAxes(index); ++i)
|
||||
emit axisChanged(index, i, 0);
|
||||
|
||||
for (int i = 0; i < getNumButtons(index); ++i)
|
||||
emit buttonChanged(index, i, false);
|
||||
|
||||
for (int i = 0; i < getNumPOVs(index); ++i)
|
||||
emit povChanged(index, i, 0);
|
||||
}
|
||||
|
||||
/* See if blacklist value was actually changed */
|
||||
bool changed = m_devices.at(index)->blacklisted != blacklisted;
|
||||
|
||||
/* Save settings */
|
||||
m_devices.at(index)->blacklisted = blacklisted;
|
||||
m_settings->setValue(getName(index), blacklisted);
|
||||
|
||||
/* Re-scan joysticks if blacklist value has changed */
|
||||
if (changed)
|
||||
updateInterfaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Rescans' for new/removed joysticks and registers them again.
|
||||
*/
|
||||
void QJoysticks::updateInterfaces()
|
||||
{
|
||||
m_devices.clear();
|
||||
|
||||
/* Put blacklisted joysticks at the bottom of the list */
|
||||
if (m_sortJoyticks)
|
||||
{
|
||||
/* Register non-blacklisted SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
if (!joystick->blacklisted)
|
||||
addInputDevice(joystick);
|
||||
}
|
||||
|
||||
/* Register the virtual joystick (if its not blacklisted) */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
if (!joystick->blacklisted)
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register blacklisted SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
if (joystick->blacklisted)
|
||||
addInputDevice(joystick);
|
||||
}
|
||||
|
||||
/* Register the virtual joystick (if its blacklisted) */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
if (joystick->blacklisted)
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort normally */
|
||||
else
|
||||
{
|
||||
/* Register SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
}
|
||||
|
||||
/* Register virtual joystick */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the axis value range of the virtual joystick.
|
||||
*
|
||||
* Take into account that maximum axis values supported by the \c QJoysticks
|
||||
* system is from \c -1 to \c 1.
|
||||
*/
|
||||
void QJoysticks::setVirtualJoystickRange(qreal range)
|
||||
{
|
||||
virtualJoystick()->setAxisRange(range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the virtual joystick
|
||||
*/
|
||||
void QJoysticks::setVirtualJoystickEnabled(bool enabled)
|
||||
{
|
||||
virtualJoystick()->setJoystickEnabled(enabled);
|
||||
}
|
||||
|
||||
void QJoysticks::setVirtualJoystickAxisSensibility(qreal sensibility)
|
||||
{
|
||||
virtualJoystick()->setAxisSensibility(sensibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the registered joysticks and emits appropriate signals.
|
||||
*/
|
||||
void QJoysticks::resetJoysticks()
|
||||
{
|
||||
m_devices.clear();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given \a device to the \c QJoysticks system
|
||||
*/
|
||||
void QJoysticks::addInputDevice(QJoystickDevice *device)
|
||||
{
|
||||
Q_ASSERT(device);
|
||||
m_devices.append(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onPOVEvent(const QJoystickPOVEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.pov < getInputDevice(e.joystick->id)->povs.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->povs[e.pov] = e.angle;
|
||||
emit povChanged(e.joystick->id, e.pov, e.angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onAxisEvent(const QJoystickAxisEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.axis < getInputDevice(e.joystick->id)->axes.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->axes[e.axis] = e.value;
|
||||
emit axisChanged(e.joystick->id, e.axis, e.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onButtonEvent(const QJoystickButtonEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.button < getInputDevice(e.joystick->id)->buttons.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->buttons[e.button] = e.pressed;
|
||||
emit buttonChanged(e.joystick->id, e.button, e.pressed);
|
||||
}
|
||||
}
|
||||
}
|
122
src/QJoysticks.h
Normal file
122
src/QJoysticks.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_MAIN_H
|
||||
#define _QJOYSTICKS_MAIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include "jsbackend/JoysticksCommon.h"
|
||||
|
||||
class QSettings;
|
||||
class SDL_Joysticks;
|
||||
class VirtualJoystick;
|
||||
|
||||
/**
|
||||
* \brief Manages the input systems and communicates them with the application
|
||||
*
|
||||
* The \c QJoysticks class is the "god-object" of this system. It manages every
|
||||
* input system used by the application (e.g. SDL for real joysticks and
|
||||
* keyboard for virtual joystick) and communicates every module/input system
|
||||
* with the rest of the application through standarized types.
|
||||
*
|
||||
* The joysticks are assigned a numerical ID, which the \c QJoysticks can use to
|
||||
* identify them. The ID's start with \c 0 (as with a QList). The ID's are
|
||||
* refreshed when a joystick is attached or removed. The first joystick that
|
||||
* has been connected to the computer will have \c 0 as an ID, the second
|
||||
* joystick will have \c 1 as an ID, and so on...
|
||||
*
|
||||
* \note the virtual joystick will ALWAYS be the last joystick to be registered,
|
||||
* even if it has been enabled before any SDL joystick has been attached.
|
||||
*/
|
||||
class QJoysticks : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(int nonBlacklistedCount READ nonBlacklistedCount NOTIFY countChanged)
|
||||
Q_PROPERTY(QStringList deviceNames READ deviceNames NOTIFY countChanged)
|
||||
|
||||
friend class Test_QJoysticks;
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void enabledChanged(const bool enabled);
|
||||
void POVEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
void povChanged(const int js, const int pov, const int angle);
|
||||
void axisChanged(const int js, const int axis, const qreal value);
|
||||
void buttonChanged(const int js, const int button, const bool pressed);
|
||||
|
||||
public:
|
||||
static QJoysticks *getInstance();
|
||||
|
||||
int count() const;
|
||||
int nonBlacklistedCount();
|
||||
QStringList deviceNames() const;
|
||||
|
||||
Q_INVOKABLE int getPOV(const int index, const int pov);
|
||||
Q_INVOKABLE double getAxis(const int index, const int axis);
|
||||
Q_INVOKABLE bool getButton(const int index, const int button);
|
||||
|
||||
Q_INVOKABLE int getNumAxes(const int index);
|
||||
Q_INVOKABLE int getNumPOVs(const int index);
|
||||
Q_INVOKABLE int getNumButtons(const int index);
|
||||
Q_INVOKABLE bool isBlacklisted(const int index);
|
||||
Q_INVOKABLE bool joystickExists(const int index);
|
||||
Q_INVOKABLE QString getName(const int index);
|
||||
|
||||
SDL_Joysticks *sdlJoysticks() const;
|
||||
VirtualJoystick *virtualJoystick() const;
|
||||
QJoystickDevice *getInputDevice(const int index);
|
||||
QList<QJoystickDevice *> inputDevices() const;
|
||||
|
||||
public slots:
|
||||
void updateInterfaces();
|
||||
void setVirtualJoystickRange(qreal range);
|
||||
void setVirtualJoystickEnabled(bool enabled);
|
||||
void setVirtualJoystickAxisSensibility(qreal sensibility);
|
||||
void setSortJoysticksByBlacklistState(bool sort);
|
||||
void setBlacklisted(int index, bool blacklisted);
|
||||
|
||||
protected:
|
||||
explicit QJoysticks();
|
||||
~QJoysticks();
|
||||
|
||||
private slots:
|
||||
void resetJoysticks();
|
||||
void addInputDevice(QJoystickDevice *device);
|
||||
void onPOVEvent(const QJoystickPOVEvent &e);
|
||||
void onAxisEvent(const QJoystickAxisEvent &e);
|
||||
void onButtonEvent(const QJoystickButtonEvent &e);
|
||||
|
||||
private:
|
||||
bool m_sortJoyticks;
|
||||
|
||||
QSettings *m_settings;
|
||||
SDL_Joysticks *m_sdlJoysticks;
|
||||
VirtualJoystick *m_virtualJoystick;
|
||||
|
||||
QList<QJoystickDevice *> m_devices;
|
||||
};
|
||||
|
||||
#endif
|
@ -7,6 +7,11 @@ ItemStore::ItemStore(QObject *parent): QObject(parent)
|
||||
|
||||
void ItemStore::addItem(std::shared_ptr<Item> item)
|
||||
{
|
||||
if(!item)
|
||||
{
|
||||
qWarning()<<"invalid item";
|
||||
return;
|
||||
}
|
||||
bool mached = false;
|
||||
for(unsigned i = 0; i < items_.size(); i++ )
|
||||
if(*items_[i] == *item) mached = true;
|
||||
|
112
src/jsbackend/JoysticksCommon.h
Normal file
112
src/jsbackend/JoysticksCommon.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_COMMON_H
|
||||
#define _QJOYSTICKS_COMMON_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
/**
|
||||
* @brief Represents a joystick and its properties
|
||||
*
|
||||
* This structure contains:
|
||||
* - The numerical ID of the joystick
|
||||
* - The sdl instance id of the joystick
|
||||
* - The joystick display name
|
||||
* - The number of axes operated by the joystick
|
||||
* - The number of buttons operated by the joystick
|
||||
* - The number of POVs operated by the joystick
|
||||
* - A boolean value blacklisting or whitelisting the joystick
|
||||
*/
|
||||
struct QJoystickDevice
|
||||
{
|
||||
int id; /**< Holds the ID of the joystick */
|
||||
int instanceID; /**< Holds the sdl instance id of the joystick */
|
||||
QString name; /**< Holds the name/title of the joystick */
|
||||
QList<int> povs; /**< Holds the values for each POV */
|
||||
QList<double> axes; /**< Holds the values for each axis */
|
||||
QList<bool> buttons; /**< Holds the values for each button */
|
||||
bool blacklisted; /**< Holds \c true if the joystick is disabled */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a joystick rumble request
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that should be rumbled
|
||||
* - The length (in milliseconds) of the rumble effect.
|
||||
* - The strength of the effect (from 0 to 1)
|
||||
*/
|
||||
struct QJoystickRumble
|
||||
{
|
||||
uint length; /**< The duration of the effect */
|
||||
qreal strength; /**< Strength of the effect (0 to 1) */
|
||||
QJoystickDevice *joystick; /**< The pointer to the target joystick */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an POV event that can be triggered by a joystick
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that triggered the event
|
||||
* - The POV number/ID
|
||||
* - The current POV angle
|
||||
*/
|
||||
struct QJoystickPOVEvent
|
||||
{
|
||||
int pov; /**< The numerical ID of the POV */
|
||||
int angle; /**< The current angle of the POV */
|
||||
QJoystickDevice *joystick; /**< Pointer to the device that caused the event */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an axis event that can be triggered by a joystick
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that caused the event
|
||||
* - The axis number/ID
|
||||
* - The current axis value
|
||||
*/
|
||||
struct QJoystickAxisEvent
|
||||
{
|
||||
int axis; /**< The numerical ID of the axis */
|
||||
qreal value; /**< The value (from -1 to 1) of the axis */
|
||||
QJoystickDevice *joystick; /**< Pointer to the device that caused the event */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a button event that can be triggered by a joystick
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that caused the event
|
||||
* - The button number/ID
|
||||
* - The current button state (pressed or not pressed)
|
||||
*/
|
||||
struct QJoystickButtonEvent
|
||||
{
|
||||
int button; /**< The numerical ID of the button */
|
||||
bool pressed; /**< Set to \c true if the button is pressed */
|
||||
QJoystickDevice *joystick; /**< Pointer to the device that caused the event */
|
||||
};
|
||||
|
||||
#endif
|
111
src/jsbackend/JoysticksCommon.h.orig
Normal file
111
src/jsbackend/JoysticksCommon.h.orig
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_COMMON_H
|
||||
#define _QJOYSTICKS_COMMON_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* @brief Represents a joystick and its properties
|
||||
*
|
||||
* This structure contains:
|
||||
* - The numerical ID of the joystick
|
||||
* - The sdl instance id of the joystick
|
||||
* - The joystick display name
|
||||
* - The number of axes operated by the joystick
|
||||
* - The number of buttons operated by the joystick
|
||||
* - The number of POVs operated by the joystick
|
||||
* - A boolean value blacklisting or whitelisting the joystick
|
||||
*/
|
||||
struct QJoystickDevice
|
||||
{
|
||||
int id; /**< Holds the ID of the joystick */
|
||||
int instanceID; /**< Holds the sdl instance id of the joystick */
|
||||
QString name; /**< Holds the name/title of the joystick */
|
||||
QList<int> povs; /**< Holds the values for each POV */
|
||||
QList<double> axes; /**< Holds the values for each axis */
|
||||
QList<bool> buttons; /**< Holds the values for each button */
|
||||
bool blacklisted; /**< Holds \c true if the joystick is disabled */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a joystick rumble request
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that should be rumbled
|
||||
* - The length (in milliseconds) of the rumble effect.
|
||||
* - The strength of the effect (from 0 to 1)
|
||||
*/
|
||||
struct QJoystickRumble
|
||||
{
|
||||
uint length; /**< The duration of the effect */
|
||||
qreal strength; /**< Strength of the effect (0 to 1) */
|
||||
QJoystickDevice *joystick; /**< The pointer to the target joystick */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an POV event that can be triggered by a joystick
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that triggered the event
|
||||
* - The POV number/ID
|
||||
* - The current POV angle
|
||||
*/
|
||||
struct QJoystickPOVEvent
|
||||
{
|
||||
int pov; /**< The numerical ID of the POV */
|
||||
int angle; /**< The current angle of the POV */
|
||||
QJoystickDevice *joystick; /**< Pointer to the device that caused the event */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents an axis event that can be triggered by a joystick
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that caused the event
|
||||
* - The axis number/ID
|
||||
* - The current axis value
|
||||
*/
|
||||
struct QJoystickAxisEvent
|
||||
{
|
||||
int axis; /**< The numerical ID of the axis */
|
||||
qreal value; /**< The value (from -1 to 1) of the axis */
|
||||
QJoystickDevice *joystick; /**< Pointer to the device that caused the event */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Represents a button event that can be triggered by a joystick
|
||||
*
|
||||
* This structure contains:
|
||||
* - A pointer to the joystick that caused the event
|
||||
* - The button number/ID
|
||||
* - The current button state (pressed or not pressed)
|
||||
*/
|
||||
struct QJoystickButtonEvent
|
||||
{
|
||||
int button; /**< The numerical ID of the button */
|
||||
bool pressed; /**< Set to \c true if the button is pressed */
|
||||
QJoystickDevice *joystick; /**< Pointer to the device that caused the event */
|
||||
};
|
||||
|
||||
#endif
|
309
src/jsbackend/SDL_Joysticks.cpp
Normal file
309
src/jsbackend/SDL_Joysticks.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QApplication>
|
||||
#include "SDL_Joysticks.h"
|
||||
|
||||
SDL_Joysticks::SDL_Joysticks(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER))
|
||||
{
|
||||
qDebug() << "Cannot initialize SDL:" << SDL_GetError();
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
int count = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
configureJoystick(i);
|
||||
|
||||
QTimer::singleShot(100, Qt::PreciseTimer, this, SLOT(update()));
|
||||
}
|
||||
|
||||
SDL_Joysticks::~SDL_Joysticks()
|
||||
{
|
||||
for (QMap<int, QJoystickDevice *>::iterator i = m_joysticks.begin();
|
||||
i != m_joysticks.end(); ++i)
|
||||
{
|
||||
delete i.value();
|
||||
}
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list with all the registered joystick devices
|
||||
*/
|
||||
QMap<int, QJoystickDevice *> SDL_Joysticks::joysticks()
|
||||
{
|
||||
int index = 0;
|
||||
QMap<int, QJoystickDevice *> joysticks;
|
||||
for (QMap<int, QJoystickDevice *>::iterator it = m_joysticks.begin();
|
||||
it != m_joysticks.end(); ++it)
|
||||
{
|
||||
it.value()->id = index;
|
||||
joysticks[index++] = it.value();
|
||||
}
|
||||
|
||||
return joysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the data contained in the \a request, this function will instruct
|
||||
* the appropriate joystick to rumble for
|
||||
*/
|
||||
void SDL_Joysticks::rumble(const QJoystickRumble &request)
|
||||
{
|
||||
SDL_Haptic *haptic = SDL_HapticOpen(request.joystick->id);
|
||||
|
||||
if (haptic)
|
||||
{
|
||||
SDL_HapticRumbleInit(haptic);
|
||||
SDL_HapticRumblePlay(haptic, request.strength, request.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls for new SDL events and reacts to each event accordingly.
|
||||
*/
|
||||
void SDL_Joysticks::update()
|
||||
{
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_JOYDEVICEADDED:
|
||||
configureJoystick(&event);
|
||||
break;
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
{
|
||||
SDL_Joystick *js = SDL_JoystickFromInstanceID(event.jdevice.which);
|
||||
if (js)
|
||||
{
|
||||
SDL_JoystickClose(js);
|
||||
}
|
||||
|
||||
SDL_GameController *gc = SDL_GameControllerFromInstanceID(
|
||||
event.cdevice.which);
|
||||
if (gc)
|
||||
{
|
||||
SDL_GameControllerClose(gc);
|
||||
}
|
||||
}
|
||||
|
||||
delete m_joysticks[event.jdevice.which];
|
||||
m_joysticks.remove(event.jdevice.which);
|
||||
|
||||
emit countChanged();
|
||||
break;
|
||||
case SDL_JOYAXISMOTION:
|
||||
emit axisEvent(getAxisEvent(&event));
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
emit axisEvent(getAxisEvent(&event));
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
emit buttonEvent(getButtonEvent(&event));
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
emit buttonEvent(getButtonEvent(&event));
|
||||
break;
|
||||
case SDL_JOYHATMOTION:
|
||||
emit POVEvent(getPOVEvent(&event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QTimer::singleShot(10, Qt::PreciseTimer, this, SLOT(update()));
|
||||
}
|
||||
|
||||
void SDL_Joysticks::configureJoystick(const SDL_Event *event)
|
||||
{
|
||||
configureJoystick(event->jdevice.which);
|
||||
}
|
||||
|
||||
void SDL_Joysticks::configureJoystick(int id)
|
||||
{
|
||||
QJoystickDevice *joystick = getJoystick(id);
|
||||
|
||||
if (!SDL_IsGameController(id))
|
||||
{
|
||||
SDL_Joystick *js = SDL_JoystickFromInstanceID(joystick->instanceID);
|
||||
if (js)
|
||||
{
|
||||
char guid[1024];
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(js), guid,
|
||||
sizeof(guid));
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GameControllerOpen(id);
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the josytick device registered with the given \a id.
|
||||
* If no joystick with the given \a id is found, then the function will warn
|
||||
* the user through the console.
|
||||
*/
|
||||
QJoystickDevice *SDL_Joysticks::getJoystick(int id)
|
||||
{
|
||||
QJoystickDevice *joystick = new QJoystickDevice;
|
||||
SDL_Joystick *sdl_joystick = SDL_JoystickOpen(id);
|
||||
|
||||
if (sdl_joystick)
|
||||
{
|
||||
joystick->id = id;
|
||||
joystick->instanceID = SDL_JoystickInstanceID(sdl_joystick);
|
||||
joystick->blacklisted = false;
|
||||
joystick->name = SDL_JoystickName(sdl_joystick);
|
||||
|
||||
/* Get joystick properties */
|
||||
int povs = SDL_JoystickNumHats(sdl_joystick);
|
||||
int axes = SDL_JoystickNumAxes(sdl_joystick);
|
||||
int buttons = SDL_JoystickNumButtons(sdl_joystick);
|
||||
|
||||
/* Initialize POVs */
|
||||
for (int i = 0; i < povs; ++i)
|
||||
joystick->povs.append(0);
|
||||
|
||||
/* Initialize axes */
|
||||
for (int i = 0; i < axes; ++i)
|
||||
joystick->axes.append(0);
|
||||
|
||||
/* Initialize buttons */
|
||||
for (int i = 0; i < buttons; ++i)
|
||||
joystick->buttons.append(false);
|
||||
|
||||
m_joysticks[joystick->instanceID] = joystick;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "Cannot find joystick with id:" << id;
|
||||
}
|
||||
|
||||
return joystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given \a event and constructs a new
|
||||
* \c QJoystickPOVEvent to be used with the \c QJoysticks system.
|
||||
*/
|
||||
QJoystickPOVEvent SDL_Joysticks::getPOVEvent(const SDL_Event
|
||||
*sdl_event)
|
||||
{
|
||||
QJoystickPOVEvent event;
|
||||
|
||||
if (!m_joysticks.contains(sdl_event->jdevice.which))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
event.pov = sdl_event->jhat.hat;
|
||||
event.joystick = m_joysticks[sdl_event->jdevice.which];
|
||||
|
||||
switch (sdl_event->jhat.value)
|
||||
{
|
||||
case SDL_HAT_RIGHTUP:
|
||||
event.angle = 45;
|
||||
break;
|
||||
case SDL_HAT_RIGHTDOWN:
|
||||
event.angle = 135;
|
||||
break;
|
||||
case SDL_HAT_LEFTDOWN:
|
||||
event.angle = 225;
|
||||
break;
|
||||
case SDL_HAT_LEFTUP:
|
||||
event.angle = 315;
|
||||
break;
|
||||
case SDL_HAT_UP:
|
||||
event.angle = 0;
|
||||
break;
|
||||
case SDL_HAT_RIGHT:
|
||||
event.angle = 90;
|
||||
break;
|
||||
case SDL_HAT_DOWN:
|
||||
event.angle = 180;
|
||||
break;
|
||||
case SDL_HAT_LEFT:
|
||||
event.angle = 270;
|
||||
break;
|
||||
default:
|
||||
event.angle = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given \a event and constructs a new
|
||||
* \c QJoystickAxisEvent to be used with the \c QJoysticks system.
|
||||
*/
|
||||
QJoystickAxisEvent SDL_Joysticks::getAxisEvent(const SDL_Event
|
||||
*sdl_event)
|
||||
{
|
||||
QJoystickAxisEvent event;
|
||||
|
||||
if (!m_joysticks.contains(sdl_event->cdevice.which))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
event.axis = sdl_event->caxis.axis;
|
||||
event.value = static_cast<qreal>(sdl_event->caxis.value) / 32767;
|
||||
event.joystick = m_joysticks[sdl_event->cdevice.which];
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given \a event and constructs a new
|
||||
* \c QJoystickButtonEvent to be used with the \c QJoysticks system.
|
||||
*/
|
||||
QJoystickButtonEvent SDL_Joysticks::getButtonEvent(
|
||||
const SDL_Event *sdl_event)
|
||||
{
|
||||
QJoystickButtonEvent event;
|
||||
|
||||
if (!m_joysticks.contains(sdl_event->jdevice.which))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
event.button = sdl_event->jbutton.button;
|
||||
event.pressed = sdl_event->jbutton.state == SDL_PRESSED;
|
||||
event.joystick = m_joysticks[sdl_event->jdevice.which];
|
||||
event.joystick->buttons[event.button] = event.pressed;
|
||||
|
||||
return event;
|
||||
}
|
345
src/jsbackend/SDL_Joysticks.cpp.orig
Normal file
345
src/jsbackend/SDL_Joysticks.cpp.orig
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QApplication>
|
||||
#include "SDL_Joysticks.h"
|
||||
|
||||
SDL_Joysticks::SDL_Joysticks(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
#ifdef SDL_SUPPORTED
|
||||
if (SDL_Init(SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER))
|
||||
{
|
||||
qDebug() << "Cannot initialize SDL:" << SDL_GetError();
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
||||
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
int count = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
configureJoystick(i);
|
||||
|
||||
QTimer::singleShot(100, Qt::PreciseTimer, this, SLOT(update()));
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_Joysticks::~SDL_Joysticks()
|
||||
{
|
||||
for (QMap<int, QJoystickDevice *>::iterator i = m_joysticks.begin();
|
||||
i != m_joysticks.end(); ++i)
|
||||
{
|
||||
delete i.value();
|
||||
}
|
||||
|
||||
#ifdef SDL_SUPPORTED
|
||||
SDL_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list with all the registered joystick devices
|
||||
*/
|
||||
QMap<int, QJoystickDevice *> SDL_Joysticks::joysticks()
|
||||
{
|
||||
#ifdef SDL_SUPPORTED
|
||||
int index = 0;
|
||||
QMap<int, QJoystickDevice *> joysticks;
|
||||
for (QMap<int, QJoystickDevice *>::iterator it = m_joysticks.begin();
|
||||
it != m_joysticks.end(); ++it)
|
||||
{
|
||||
it.value()->id = index;
|
||||
joysticks[index++] = it.value();
|
||||
}
|
||||
|
||||
return joysticks;
|
||||
#endif
|
||||
return QMap<int, QJoystickDevice *>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the data contained in the \a request, this function will instruct
|
||||
* the appropriate joystick to rumble for
|
||||
*/
|
||||
void SDL_Joysticks::rumble(const QJoystickRumble &request)
|
||||
{
|
||||
#ifdef SDL_SUPPORTED
|
||||
SDL_Haptic *haptic = SDL_HapticOpen(request.joystick->id);
|
||||
|
||||
if (haptic)
|
||||
{
|
||||
SDL_HapticRumbleInit(haptic);
|
||||
SDL_HapticRumblePlay(haptic, request.strength, request.length);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(request);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls for new SDL events and reacts to each event accordingly.
|
||||
*/
|
||||
void SDL_Joysticks::update()
|
||||
{
|
||||
#ifdef SDL_SUPPORTED
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_JOYDEVICEADDED:
|
||||
configureJoystick(&event);
|
||||
break;
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
{
|
||||
SDL_Joystick *js = SDL_JoystickFromInstanceID(event.jdevice.which);
|
||||
if (js)
|
||||
{
|
||||
SDL_JoystickClose(js);
|
||||
}
|
||||
|
||||
SDL_GameController *gc = SDL_GameControllerFromInstanceID(
|
||||
event.cdevice.which);
|
||||
if (gc)
|
||||
{
|
||||
SDL_GameControllerClose(gc);
|
||||
}
|
||||
}
|
||||
|
||||
delete m_joysticks[event.jdevice.which];
|
||||
m_joysticks.remove(event.jdevice.which);
|
||||
|
||||
emit countChanged();
|
||||
break;
|
||||
case SDL_JOYAXISMOTION:
|
||||
emit axisEvent(getAxisEvent(&event));
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
emit axisEvent(getAxisEvent(&event));
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
emit buttonEvent(getButtonEvent(&event));
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
emit buttonEvent(getButtonEvent(&event));
|
||||
break;
|
||||
case SDL_JOYHATMOTION:
|
||||
emit POVEvent(getPOVEvent(&event));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QTimer::singleShot(10, Qt::PreciseTimer, this, SLOT(update()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDL_Joysticks::configureJoystick(const SDL_Event *event)
|
||||
{
|
||||
configureJoystick(event->jdevice.which);
|
||||
}
|
||||
|
||||
void SDL_Joysticks::configureJoystick(int id)
|
||||
{
|
||||
#ifdef SDL_SUPPORTED
|
||||
QJoystickDevice *joystick = getJoystick(id);
|
||||
|
||||
if (!SDL_IsGameController(id))
|
||||
{
|
||||
SDL_Joystick *js = SDL_JoystickFromInstanceID(joystick->instanceID);
|
||||
if (js)
|
||||
{
|
||||
char guid[1024];
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(js), guid,
|
||||
sizeof(guid));
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GameControllerOpen(id);
|
||||
|
||||
emit countChanged();
|
||||
#else
|
||||
Q_UNUSED(event);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the josytick device registered with the given \a id.
|
||||
* If no joystick with the given \a id is found, then the function will warn
|
||||
* the user through the console.
|
||||
*/
|
||||
QJoystickDevice *SDL_Joysticks::getJoystick(int id)
|
||||
{
|
||||
#ifdef SDL_SUPPORTED
|
||||
QJoystickDevice *joystick = new QJoystickDevice;
|
||||
SDL_Joystick *sdl_joystick = SDL_JoystickOpen(id);
|
||||
|
||||
if (sdl_joystick)
|
||||
{
|
||||
joystick->id = id;
|
||||
joystick->instanceID = SDL_JoystickInstanceID(sdl_joystick);
|
||||
joystick->blacklisted = false;
|
||||
joystick->name = SDL_JoystickName(sdl_joystick);
|
||||
|
||||
/* Get joystick properties */
|
||||
int povs = SDL_JoystickNumHats(sdl_joystick);
|
||||
int axes = SDL_JoystickNumAxes(sdl_joystick);
|
||||
int buttons = SDL_JoystickNumButtons(sdl_joystick);
|
||||
|
||||
/* Initialize POVs */
|
||||
for (int i = 0; i < povs; ++i)
|
||||
joystick->povs.append(0);
|
||||
|
||||
/* Initialize axes */
|
||||
for (int i = 0; i < axes; ++i)
|
||||
joystick->axes.append(0);
|
||||
|
||||
/* Initialize buttons */
|
||||
for (int i = 0; i < buttons; ++i)
|
||||
joystick->buttons.append(false);
|
||||
|
||||
m_joysticks[joystick->instanceID] = joystick;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "Cannot find joystick with id:" << id;
|
||||
}
|
||||
|
||||
return joystick;
|
||||
#else
|
||||
Q_UNUSED(id);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given \a event and constructs a new
|
||||
* \c QJoystickPOVEvent to be used with the \c QJoysticks system.
|
||||
*/
|
||||
QJoystickPOVEvent SDL_Joysticks::getPOVEvent(const SDL_Event
|
||||
*sdl_event)
|
||||
{
|
||||
QJoystickPOVEvent event;
|
||||
|
||||
if (!m_joysticks.contains(sdl_event->jdevice.which))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
#ifdef SDL_SUPPORTED
|
||||
event.pov = sdl_event->jhat.hat;
|
||||
event.joystick = m_joysticks[sdl_event->jdevice.which];
|
||||
|
||||
switch (sdl_event->jhat.value)
|
||||
{
|
||||
case SDL_HAT_RIGHTUP:
|
||||
event.angle = 45;
|
||||
break;
|
||||
case SDL_HAT_RIGHTDOWN:
|
||||
event.angle = 135;
|
||||
break;
|
||||
case SDL_HAT_LEFTDOWN:
|
||||
event.angle = 225;
|
||||
break;
|
||||
case SDL_HAT_LEFTUP:
|
||||
event.angle = 315;
|
||||
break;
|
||||
case SDL_HAT_UP:
|
||||
event.angle = 0;
|
||||
break;
|
||||
case SDL_HAT_RIGHT:
|
||||
event.angle = 90;
|
||||
break;
|
||||
case SDL_HAT_DOWN:
|
||||
event.angle = 180;
|
||||
break;
|
||||
case SDL_HAT_LEFT:
|
||||
event.angle = 270;
|
||||
break;
|
||||
default:
|
||||
event.angle = -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(sdl_event);
|
||||
#endif
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given \a event and constructs a new
|
||||
* \c QJoystickAxisEvent to be used with the \c QJoysticks system.
|
||||
*/
|
||||
QJoystickAxisEvent SDL_Joysticks::getAxisEvent(const SDL_Event
|
||||
*sdl_event)
|
||||
{
|
||||
QJoystickAxisEvent event;
|
||||
|
||||
if (!m_joysticks.contains(sdl_event->cdevice.which))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
#ifdef SDL_SUPPORTED
|
||||
event.axis = sdl_event->caxis.axis;
|
||||
event.value = static_cast<qreal>(sdl_event->caxis.value) / 32767;
|
||||
event.joystick = m_joysticks[sdl_event->cdevice.which];
|
||||
#else
|
||||
Q_UNUSED(sdl_event);
|
||||
#endif
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given \a event and constructs a new
|
||||
* \c QJoystickButtonEvent to be used with the \c QJoysticks system.
|
||||
*/
|
||||
QJoystickButtonEvent SDL_Joysticks::getButtonEvent(
|
||||
const SDL_Event *sdl_event)
|
||||
{
|
||||
QJoystickButtonEvent event;
|
||||
|
||||
if (!m_joysticks.contains(sdl_event->jdevice.which))
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
#ifdef SDL_SUPPORTED
|
||||
event.button = sdl_event->jbutton.button;
|
||||
event.pressed = sdl_event->jbutton.state == SDL_PRESSED;
|
||||
event.joystick = m_joysticks[sdl_event->jdevice.which];
|
||||
event.joystick->buttons[event.button] = event.pressed;
|
||||
#else
|
||||
Q_UNUSED(sdl_event);
|
||||
#endif
|
||||
|
||||
return event;
|
||||
}
|
76
src/jsbackend/SDL_Joysticks.h
Normal file
76
src/jsbackend/SDL_Joysticks.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_SDL_JOYSTICK_H
|
||||
#define _QJOYSTICKS_SDL_JOYSTICK_H
|
||||
|
||||
#include <SDL.h>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include "JoysticksCommon.h"
|
||||
|
||||
/**
|
||||
* \brief Translates SDL events into \c QJoysticks events
|
||||
*
|
||||
* This class is in charge of managing and operating real joysticks through the
|
||||
* SDL API. The implementation procedure is the same for every operating system.
|
||||
*
|
||||
* The only thing that differs from each operating system is the backup mapping
|
||||
* applied in the case that we do not know what mapping to apply to a joystick.
|
||||
*
|
||||
* \note The joystick values are refreshed every 20 milliseconds through a
|
||||
* simple event loop.
|
||||
*/
|
||||
class SDL_Joysticks : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void POVEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
|
||||
public:
|
||||
SDL_Joysticks(QObject *parent = Q_NULLPTR);
|
||||
~SDL_Joysticks();
|
||||
|
||||
QMap<int, QJoystickDevice *> joysticks();
|
||||
|
||||
public slots:
|
||||
void rumble(const QJoystickRumble &request);
|
||||
|
||||
private slots:
|
||||
void update();
|
||||
void configureJoystick(const SDL_Event *event);
|
||||
void configureJoystick(int id);
|
||||
|
||||
private:
|
||||
QJoystickDevice *getJoystick(int id);
|
||||
QJoystickPOVEvent getPOVEvent(const SDL_Event *sdl_event);
|
||||
QJoystickAxisEvent getAxisEvent(const SDL_Event *sdl_event);
|
||||
QJoystickButtonEvent getButtonEvent(const SDL_Event *sdl_event);
|
||||
|
||||
QMap<int, QJoystickDevice *> m_joysticks;
|
||||
};
|
||||
|
||||
#endif
|
76
src/jsbackend/SDL_Joysticks.h.orig
Normal file
76
src/jsbackend/SDL_Joysticks.h.orig
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_SDL_JOYSTICK_H
|
||||
#define _QJOYSTICKS_SDL_JOYSTICK_H
|
||||
|
||||
#include <SDL.h>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include "JoysticksCommon.h"
|
||||
|
||||
/**
|
||||
* \brief Translates SDL events into \c QJoysticks events
|
||||
*
|
||||
* This class is in charge of managing and operating real joysticks through the
|
||||
* SDL API. The implementation procedure is the same for every operating system.
|
||||
*
|
||||
* The only thing that differs from each operating system is the backup mapping
|
||||
* applied in the case that we do not know what mapping to apply to a joystick.
|
||||
*
|
||||
* \note The joystick values are refreshed every 20 milliseconds through a
|
||||
* simple event loop.
|
||||
*/
|
||||
class SDL_Joysticks : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void POVEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
|
||||
public:
|
||||
SDL_Joysticks(QObject *parent = Q_NULLPTR);
|
||||
~SDL_Joysticks();
|
||||
|
||||
QMap<int, QJoystickDevice *> joysticks();
|
||||
|
||||
public slots:
|
||||
void rumble(const QJoystickRumble &request);
|
||||
|
||||
private slots:
|
||||
void update();
|
||||
void configureJoystick(const SDL_Event *event);
|
||||
void configureJoystick(int id);
|
||||
|
||||
private:
|
||||
QJoystickDevice *getJoystick(int id);
|
||||
QJoystickPOVEvent getPOVEvent(const SDL_Event *sdl_event);
|
||||
QJoystickAxisEvent getAxisEvent(const SDL_Event *sdl_event);
|
||||
QJoystickButtonEvent getButtonEvent(const SDL_Event *sdl_event);
|
||||
|
||||
QMap<int, QJoystickDevice *> m_joysticks;
|
||||
};
|
||||
|
||||
#endif
|
424
src/jsbackend/VirtualJoystick.cpp
Normal file
424
src/jsbackend/VirtualJoystick.cpp
Normal file
@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "VirtualJoystick.h"
|
||||
|
||||
VirtualJoystick::VirtualJoystick(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_axisRange = 1;
|
||||
m_joystickEnabled = false;
|
||||
m_joystick.blacklisted = false;
|
||||
m_joystick.name = tr("Virtual Joystick");
|
||||
|
||||
/* Initialize POVs */
|
||||
m_joystick.povs.append(0);
|
||||
|
||||
/* Initialize axes */
|
||||
m_axisStatus = QVector<AxisState>(NUMBER_OF_AXES, AxisState::STILL);
|
||||
m_axisValue = QVector<qint16>(NUMBER_OF_AXES, 0);
|
||||
for (int i = 0; i < NUMBER_OF_AXES; ++i)
|
||||
{
|
||||
m_joystick.axes.append(0);
|
||||
}
|
||||
|
||||
/* Initialize buttons */
|
||||
for (int i = 0; i < NUMBER_OF_BUTTONS; ++i)
|
||||
m_joystick.buttons.append(false);
|
||||
|
||||
m_timerUpdateAxis.reset(new QTimer());
|
||||
connect(m_timerUpdateAxis.get(), &QTimer::timeout, this, &VirtualJoystick::updateAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current axis range of the joystick.
|
||||
* The axis range is an absolute value that represents the maximum value that
|
||||
* the joystick can have.
|
||||
*
|
||||
* For example, the \c QJoystick system supports an axis range of 1 (-1 to 1).
|
||||
* If you set an axis range of 0.8 to the virtual joystick, then it will report
|
||||
* values ranging from -0.8 to 0.8.
|
||||
*/
|
||||
qreal VirtualJoystick::axisRange() const
|
||||
{
|
||||
return m_axisRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the virtual joystick is enabled.
|
||||
*/
|
||||
bool VirtualJoystick::joystickEnabled() const
|
||||
{
|
||||
return m_joystickEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the virtual josytick device. This can be used if you
|
||||
* need to customize the virtual joystick (e.g. add new axes or buttons).
|
||||
*/
|
||||
QJoystickDevice *VirtualJoystick::joystick()
|
||||
{
|
||||
return &m_joystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID of the virtual joystick device. The \c QJoysticks will
|
||||
* automatically change the \a ID of the virtual joystick when it scans for
|
||||
* new joysticks.
|
||||
*
|
||||
* The virtual joystick will ALWAYS be the last joystick to be registered.
|
||||
*/
|
||||
void VirtualJoystick::setJoystickID(int id)
|
||||
{
|
||||
m_joystick.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the axis range that the joystick can use. For example, if you set
|
||||
* an axis range of 0.8, then axis values will be reported from -0.8 to 0.8.
|
||||
*
|
||||
* If you set an axis range of 1 (maximum), then the joystick will report axis
|
||||
* values ranging from -1 to 1.
|
||||
*/
|
||||
void VirtualJoystick::setAxisRange(qreal range)
|
||||
{
|
||||
range = fabs(range);
|
||||
|
||||
if (range > 1)
|
||||
range = 1;
|
||||
|
||||
m_axisRange = range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::setJoystickEnabled(bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
// That means that the axes will be updated each 10 ms
|
||||
m_timerUpdateAxis->start(10);
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
m_timerUpdateAxis->stop();
|
||||
// Removing the event filter since the joystick is no longer active
|
||||
qApp->removeEventFilter(this);
|
||||
}
|
||||
|
||||
m_joystickEnabled = enabled;
|
||||
emit enabledChanged();
|
||||
}
|
||||
|
||||
void VirtualJoystick::setAxisSensibility(qreal sensibility)
|
||||
{
|
||||
if (sensibility > 1 || sensibility < 0)
|
||||
{
|
||||
qFatal("Fatal: VirtualJoystick Axis sensibility must be a value between 0 and 1");
|
||||
}
|
||||
|
||||
const qint16 stepMinimum = 50;
|
||||
const qint16 stepMaximum = 1000;
|
||||
|
||||
m_axisStep = static_cast<qint16>((-stepMaximum + stepMinimum) * sensibility) + stepMaximum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the keyboard events and if required, reports a change in the axis
|
||||
* values of the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::readAxes(int key, bool pressed)
|
||||
{
|
||||
|
||||
/* Horizontal axis on thumb 1 */
|
||||
if (key == Qt::Key_A)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_AD] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_AD] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_D)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_AD] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_AD] = STILL;
|
||||
}
|
||||
|
||||
/* Vertical axis on thumb 1 */
|
||||
if (key == Qt::Key_S)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_SW] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_SW] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_W)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_SW] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_SW] = STILL;
|
||||
}
|
||||
|
||||
/* Trigger 1 */
|
||||
if (key == Qt::Key_Q)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_QE] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_QE] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_E)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_QE] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_QE] = STILL;
|
||||
}
|
||||
|
||||
/* Trigger 2 */
|
||||
if (key == Qt::Key_U)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_UO] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_UO] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_O)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_UO] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_UO] = STILL;
|
||||
}
|
||||
|
||||
/* Horizontal axis on thumb 2 */
|
||||
if (key == Qt::Key_J)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_JL] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_JL] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_L)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_JL] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_JL] = STILL;
|
||||
}
|
||||
|
||||
/* Vertical axis on thumb 2 */
|
||||
if (key == Qt::Key_K)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_KI] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_KI] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_I)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_KI] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_KI] = STILL;
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualJoystick::updateAxis()
|
||||
{
|
||||
for (quint8 i = 0; i < NUMBER_OF_AXES; i++)
|
||||
{
|
||||
changeAxisValue(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the keyboard events and if required, reports a change in the POV/hat
|
||||
* values of the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::readPOVs(int key, bool pressed)
|
||||
{
|
||||
int angle = 0;
|
||||
|
||||
if (key == Qt::Key_Up)
|
||||
angle = 360;
|
||||
else if (key == Qt::Key_Right)
|
||||
angle = 90;
|
||||
else if (key == Qt::Key_Left)
|
||||
angle = 270;
|
||||
else if (key == Qt::Key_Down)
|
||||
angle = 180;
|
||||
|
||||
if (!pressed)
|
||||
angle = 0;
|
||||
|
||||
if (joystickEnabled())
|
||||
{
|
||||
QJoystickPOVEvent event;
|
||||
event.pov = 0;
|
||||
event.angle = angle;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit povEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the keyboard events and if required, reports a change in the button
|
||||
* values of the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::readButtons(int key, bool pressed)
|
||||
{
|
||||
int button = -1;
|
||||
|
||||
if (key == Qt::Key_0)
|
||||
{
|
||||
// Special key that reset all axes
|
||||
button = 0;
|
||||
resetAllAxes();
|
||||
}
|
||||
else if (key == Qt::Key_1)
|
||||
button = 1;
|
||||
else if (key == Qt::Key_2)
|
||||
button = 2;
|
||||
else if (key == Qt::Key_3)
|
||||
button = 3;
|
||||
else if (key == Qt::Key_4)
|
||||
button = 4;
|
||||
else if (key == Qt::Key_5)
|
||||
button = 5;
|
||||
else if (key == Qt::Key_6)
|
||||
button = 6;
|
||||
else if (key == Qt::Key_7)
|
||||
button = 7;
|
||||
else if (key == Qt::Key_8)
|
||||
button = 8;
|
||||
else if (key == Qt::Key_9)
|
||||
button = 9;
|
||||
|
||||
if (button != -1 && joystickEnabled())
|
||||
{
|
||||
QJoystickButtonEvent event;
|
||||
event.button = button;
|
||||
event.pressed = pressed;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit buttonEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the event filter detects a keyboard event.
|
||||
*
|
||||
* This function prompts the joystick to update its axis, button and POV values
|
||||
* based on the keys that have been pressed or released.
|
||||
*/
|
||||
void VirtualJoystick::processKeyEvent(QKeyEvent *event, bool pressed)
|
||||
{
|
||||
if (joystickEnabled())
|
||||
{
|
||||
readPOVs(event->key(), pressed);
|
||||
readAxes(event->key(), pressed);
|
||||
readButtons(event->key(), pressed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Listens" for keyboard presses or releases while any window or widget of the
|
||||
* application is focused.
|
||||
*
|
||||
* \note This function may or may not detect keyboard events when the
|
||||
* application is not focused. This depends on the operating system and
|
||||
* the window manager that is being used.
|
||||
*/
|
||||
bool VirtualJoystick::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(object);
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
processKeyEvent(static_cast<QKeyEvent *>(event), true);
|
||||
break;
|
||||
case QEvent::KeyRelease:
|
||||
processKeyEvent(static_cast<QKeyEvent *>(event), false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VirtualJoystick::changeAxisValue(quint8 axis)
|
||||
{
|
||||
switch (m_axisStatus[axis])
|
||||
{
|
||||
case STILL:
|
||||
return;
|
||||
|
||||
case INCREASE:
|
||||
if (m_axisValue[axis] > AXIS_MAXIMUM_VIRTUAL_JOYSTICK - m_axisStep)
|
||||
m_axisValue[axis] = AXIS_MAXIMUM_VIRTUAL_JOYSTICK;
|
||||
else
|
||||
m_axisValue[axis] += m_axisStep;
|
||||
break;
|
||||
|
||||
case DECREASE:
|
||||
if (m_axisValue[axis] < AXIS_MINIMUM_VIRTUAL_JOYSTICK + m_axisStep)
|
||||
m_axisValue[axis] = AXIS_MINIMUM_VIRTUAL_JOYSTICK;
|
||||
else
|
||||
m_axisValue[axis] -= m_axisStep;
|
||||
break;
|
||||
}
|
||||
|
||||
QJoystickAxisEvent event;
|
||||
|
||||
event.axis = axis;
|
||||
event.value = m_axisRange * static_cast<qreal>(m_axisValue[axis]) / AXIS_MAXIMUM_VIRTUAL_JOYSTICK;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit axisEvent(event);
|
||||
}
|
||||
|
||||
void VirtualJoystick::resetAllAxes()
|
||||
{
|
||||
for (quint8 i = 0; i < NUMBER_OF_AXES; i++)
|
||||
{
|
||||
m_axisValue[i] = 0;
|
||||
|
||||
QJoystickAxisEvent event;
|
||||
|
||||
event.axis = i;
|
||||
event.value = 0;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit axisEvent(event);
|
||||
}
|
||||
}
|
423
src/jsbackend/VirtualJoystick.cpp.orig
Normal file
423
src/jsbackend/VirtualJoystick.cpp.orig
Normal file
@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "VirtualJoystick.h"
|
||||
|
||||
VirtualJoystick::VirtualJoystick(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_axisRange = 1;
|
||||
m_joystickEnabled = false;
|
||||
m_joystick.blacklisted = false;
|
||||
m_joystick.name = tr("Virtual Joystick");
|
||||
|
||||
/* Initialize POVs */
|
||||
m_joystick.povs.append(0);
|
||||
|
||||
/* Initialize axes */
|
||||
m_axisStatus = QVector<AxisState>(NUMBER_OF_AXES, AxisState::STILL);
|
||||
m_axisValue = QVector<qint16>(NUMBER_OF_AXES, 0);
|
||||
for (int i = 0; i < NUMBER_OF_AXES; ++i)
|
||||
{
|
||||
m_joystick.axes.append(0);
|
||||
}
|
||||
|
||||
/* Initialize buttons */
|
||||
for (int i = 0; i < NUMBER_OF_BUTTONS; ++i)
|
||||
m_joystick.buttons.append(false);
|
||||
|
||||
m_timerUpdateAxis.reset(new QTimer());
|
||||
connect(m_timerUpdateAxis.get(), &QTimer::timeout, this, &VirtualJoystick::updateAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current axis range of the joystick.
|
||||
* The axis range is an absolute value that represents the maximum value that
|
||||
* the joystick can have.
|
||||
*
|
||||
* For example, the \c QJoystick system supports an axis range of 1 (-1 to 1).
|
||||
* If you set an axis range of 0.8 to the virtual joystick, then it will report
|
||||
* values ranging from -0.8 to 0.8.
|
||||
*/
|
||||
qreal VirtualJoystick::axisRange() const
|
||||
{
|
||||
return m_axisRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the virtual joystick is enabled.
|
||||
*/
|
||||
bool VirtualJoystick::joystickEnabled() const
|
||||
{
|
||||
return m_joystickEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the virtual josytick device. This can be used if you
|
||||
* need to customize the virtual joystick (e.g. add new axes or buttons).
|
||||
*/
|
||||
QJoystickDevice *VirtualJoystick::joystick()
|
||||
{
|
||||
return &m_joystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID of the virtual joystick device. The \c QJoysticks will
|
||||
* automatically change the \a ID of the virtual joystick when it scans for
|
||||
* new joysticks.
|
||||
*
|
||||
* The virtual joystick will ALWAYS be the last joystick to be registered.
|
||||
*/
|
||||
void VirtualJoystick::setJoystickID(int id)
|
||||
{
|
||||
m_joystick.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the axis range that the joystick can use. For example, if you set
|
||||
* an axis range of 0.8, then axis values will be reported from -0.8 to 0.8.
|
||||
*
|
||||
* If you set an axis range of 1 (maximum), then the joystick will report axis
|
||||
* values ranging from -1 to 1.
|
||||
*/
|
||||
void VirtualJoystick::setAxisRange(qreal range)
|
||||
{
|
||||
range = fabs(range);
|
||||
|
||||
if (range > 1)
|
||||
range = 1;
|
||||
|
||||
m_axisRange = range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::setJoystickEnabled(bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
// That means that the axes will be updated each 10 ms
|
||||
m_timerUpdateAxis->start(10);
|
||||
qApp->installEventFilter(this);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
m_timerUpdateAxis->stop();
|
||||
// Removing the event filter since the joystick is no longer active
|
||||
qApp->removeEventFilter(this);
|
||||
}
|
||||
|
||||
m_joystickEnabled = enabled;
|
||||
emit enabledChanged();
|
||||
}
|
||||
|
||||
void VirtualJoystick::setAxisSensibility(qreal sensibility)
|
||||
{
|
||||
if (sensibility > 1 || sensibility < 0)
|
||||
{
|
||||
qFatal("Fatal: VirtualJoystick Axis sensibility must be a value between 0 and 1");
|
||||
}
|
||||
|
||||
const qint16 stepMinimum = 50;
|
||||
const qint16 stepMaximum = 1000;
|
||||
|
||||
m_axisStep = static_cast<qint16>((-stepMaximum + stepMinimum) * sensibility) + stepMaximum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the keyboard events and if required, reports a change in the axis
|
||||
* values of the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::readAxes(int key, bool pressed)
|
||||
{
|
||||
|
||||
/* Horizontal axis on thumb 1 */
|
||||
if (key == Qt::Key_A)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_AD] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_AD] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_D)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_AD] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_AD] = STILL;
|
||||
}
|
||||
|
||||
/* Vertical axis on thumb 1 */
|
||||
if (key == Qt::Key_S)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_SW] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_SW] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_W)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_SW] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_SW] = STILL;
|
||||
}
|
||||
|
||||
/* Trigger 1 */
|
||||
if (key == Qt::Key_Q)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_QE] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_QE] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_E)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_QE] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_QE] = STILL;
|
||||
}
|
||||
|
||||
/* Trigger 2 */
|
||||
if (key == Qt::Key_U)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_UO] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_UO] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_O)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_UO] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_UO] = STILL;
|
||||
}
|
||||
|
||||
/* Horizontal axis on thumb 2 */
|
||||
if (key == Qt::Key_J)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_JL] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_JL] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_L)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_JL] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_JL] = STILL;
|
||||
}
|
||||
|
||||
/* Vertical axis on thumb 2 */
|
||||
if (key == Qt::Key_K)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_KI] = DECREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_KI] = STILL;
|
||||
}
|
||||
else if (key == Qt::Key_I)
|
||||
{
|
||||
if (pressed)
|
||||
m_axisStatus[AXIS_KI] = INCREASE;
|
||||
else
|
||||
m_axisStatus[AXIS_KI] = STILL;
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualJoystick::updateAxis()
|
||||
{
|
||||
for (quint8 i = 0; i < NUMBER_OF_AXES; i++)
|
||||
{
|
||||
changeAxisValue(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the keyboard events and if required, reports a change in the POV/hat
|
||||
* values of the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::readPOVs(int key, bool pressed)
|
||||
{
|
||||
int angle = 0;
|
||||
|
||||
if (key == Qt::Key_Up)
|
||||
angle = 360;
|
||||
else if (key == Qt::Key_Right)
|
||||
angle = 90;
|
||||
else if (key == Qt::Key_Left)
|
||||
angle = 270;
|
||||
else if (key == Qt::Key_Down)
|
||||
angle = 180;
|
||||
|
||||
if (!pressed)
|
||||
angle = 0;
|
||||
|
||||
if (joystickEnabled())
|
||||
{
|
||||
QJoystickPOVEvent event;
|
||||
event.pov = 0;
|
||||
event.angle = angle;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit povEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the keyboard events and if required, reports a change in the button
|
||||
* values of the virtual joystick device.
|
||||
*/
|
||||
void VirtualJoystick::readButtons(int key, bool pressed)
|
||||
{
|
||||
int button = -1;
|
||||
|
||||
if (key == Qt::Key_0)
|
||||
{ // Special key that reset all axes
|
||||
button = 0;
|
||||
resetAllAxes();
|
||||
}
|
||||
else if (key == Qt::Key_1)
|
||||
button = 1;
|
||||
else if (key == Qt::Key_2)
|
||||
button = 2;
|
||||
else if (key == Qt::Key_3)
|
||||
button = 3;
|
||||
else if (key == Qt::Key_4)
|
||||
button = 4;
|
||||
else if (key == Qt::Key_5)
|
||||
button = 5;
|
||||
else if (key == Qt::Key_6)
|
||||
button = 6;
|
||||
else if (key == Qt::Key_7)
|
||||
button = 7;
|
||||
else if (key == Qt::Key_8)
|
||||
button = 8;
|
||||
else if (key == Qt::Key_9)
|
||||
button = 9;
|
||||
|
||||
if (button != -1 && joystickEnabled())
|
||||
{
|
||||
QJoystickButtonEvent event;
|
||||
event.button = button;
|
||||
event.pressed = pressed;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit buttonEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the event filter detects a keyboard event.
|
||||
*
|
||||
* This function prompts the joystick to update its axis, button and POV values
|
||||
* based on the keys that have been pressed or released.
|
||||
*/
|
||||
void VirtualJoystick::processKeyEvent(QKeyEvent *event, bool pressed)
|
||||
{
|
||||
if (joystickEnabled())
|
||||
{
|
||||
readPOVs(event->key(), pressed);
|
||||
readAxes(event->key(), pressed);
|
||||
readButtons(event->key(), pressed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Listens" for keyboard presses or releases while any window or widget of the
|
||||
* application is focused.
|
||||
*
|
||||
* \note This function may or may not detect keyboard events when the
|
||||
* application is not focused. This depends on the operating system and
|
||||
* the window manager that is being used.
|
||||
*/
|
||||
bool VirtualJoystick::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(object);
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
processKeyEvent(static_cast<QKeyEvent *>(event), true);
|
||||
break;
|
||||
case QEvent::KeyRelease:
|
||||
processKeyEvent(static_cast<QKeyEvent *>(event), false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VirtualJoystick::changeAxisValue(quint8 axis)
|
||||
{
|
||||
switch (m_axisStatus[axis])
|
||||
{
|
||||
case STILL:
|
||||
return;
|
||||
|
||||
case INCREASE:
|
||||
if (m_axisValue[axis] > AXIS_MAXIMUM_VIRTUAL_JOYSTICK - m_axisStep)
|
||||
m_axisValue[axis] = AXIS_MAXIMUM_VIRTUAL_JOYSTICK;
|
||||
else
|
||||
m_axisValue[axis] += m_axisStep;
|
||||
break;
|
||||
|
||||
case DECREASE:
|
||||
if (m_axisValue[axis] < AXIS_MINIMUM_VIRTUAL_JOYSTICK + m_axisStep)
|
||||
m_axisValue[axis] = AXIS_MINIMUM_VIRTUAL_JOYSTICK;
|
||||
else
|
||||
m_axisValue[axis] -= m_axisStep;
|
||||
break;
|
||||
}
|
||||
|
||||
QJoystickAxisEvent event;
|
||||
|
||||
event.axis = axis;
|
||||
event.value = m_axisRange * static_cast<qreal>(m_axisValue[axis]) / AXIS_MAXIMUM_VIRTUAL_JOYSTICK;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit axisEvent(event);
|
||||
}
|
||||
|
||||
void VirtualJoystick::resetAllAxes()
|
||||
{
|
||||
for (quint8 i = 0; i < NUMBER_OF_AXES; i++)
|
||||
{
|
||||
m_axisValue[i] = 0;
|
||||
|
||||
QJoystickAxisEvent event;
|
||||
|
||||
event.axis = i;
|
||||
event.value = 0;
|
||||
event.joystick = joystick();
|
||||
|
||||
emit axisEvent(event);
|
||||
}
|
||||
}
|
112
src/jsbackend/VirtualJoystick.h
Normal file
112
src/jsbackend/VirtualJoystick.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_JOYSTICK_H
|
||||
#define _QJOYSTICKS_JOYSTICK_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QKeyEvent>
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include "JoysticksCommon.h"
|
||||
|
||||
#define AXIS_AD 0
|
||||
#define AXIS_SW 1
|
||||
#define AXIS_QE 2
|
||||
#define AXIS_UO 3
|
||||
#define AXIS_JL 4
|
||||
#define AXIS_KI 5
|
||||
|
||||
enum AxisState : qint8
|
||||
{
|
||||
|
||||
INCREASE = -1,
|
||||
STILL = 0,
|
||||
DECREASE = 1
|
||||
|
||||
};
|
||||
|
||||
const qint16 AXIS_MINIMUM_VIRTUAL_JOYSTICK { -32767 };
|
||||
const qint16 AXIS_MAXIMUM_VIRTUAL_JOYSTICK { 32767 };
|
||||
|
||||
const int NUMBER_OF_AXES { 6 };
|
||||
const int NUMBER_OF_BUTTONS { 10 };
|
||||
|
||||
/**
|
||||
* \brief Translates keyboard input to joystick input
|
||||
*
|
||||
* This class implements a virtual joystick device that uses the computer's
|
||||
* keyboard as means to get the axis, button and POV values of the joystick.
|
||||
*/
|
||||
class VirtualJoystick : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void enabledChanged();
|
||||
void povEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
|
||||
public:
|
||||
VirtualJoystick(QObject *parent = Q_NULLPTR);
|
||||
|
||||
qreal axisRange() const;
|
||||
bool joystickEnabled() const;
|
||||
QJoystickDevice *joystick();
|
||||
|
||||
public slots:
|
||||
void setJoystickID(int id);
|
||||
void setAxisRange(qreal range);
|
||||
void setJoystickEnabled(bool enabled);
|
||||
|
||||
void setAxisSensibility(qreal sensibility);
|
||||
|
||||
private slots:
|
||||
void readAxes(int key, bool pressed);
|
||||
void updateAxis();
|
||||
void readPOVs(int key, bool pressed);
|
||||
void readButtons(int key, bool pressed);
|
||||
void processKeyEvent(QKeyEvent *event, bool pressed);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
|
||||
private:
|
||||
qreal m_axisRange;
|
||||
bool m_joystickEnabled;
|
||||
QJoystickDevice m_joystick;
|
||||
|
||||
qint16 m_axisStep;
|
||||
|
||||
QVector<AxisState> m_axisStatus;
|
||||
QVector<qint16> m_axisValue;
|
||||
|
||||
QScopedPointer<QTimer> m_timerUpdateAxis;
|
||||
|
||||
void changeAxisValue(quint8 axis);
|
||||
void resetAllAxes();
|
||||
};
|
||||
|
||||
#endif
|
112
src/jsbackend/VirtualJoystick.h.orig
Normal file
112
src/jsbackend/VirtualJoystick.h.orig
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _QJOYSTICKS_JOYSTICK_H
|
||||
#define _QJOYSTICKS_JOYSTICK_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QKeyEvent>
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include "JoysticksCommon.h"
|
||||
|
||||
#define AXIS_AD 0
|
||||
#define AXIS_SW 1
|
||||
#define AXIS_QE 2
|
||||
#define AXIS_UO 3
|
||||
#define AXIS_JL 4
|
||||
#define AXIS_KI 5
|
||||
|
||||
enum AxisState : qint8
|
||||
{
|
||||
|
||||
INCREASE = -1,
|
||||
STILL = 0,
|
||||
DECREASE = 1
|
||||
|
||||
};
|
||||
|
||||
const qint16 AXIS_MINIMUM_VIRTUAL_JOYSTICK { -32767 };
|
||||
const qint16 AXIS_MAXIMUM_VIRTUAL_JOYSTICK { 32767 };
|
||||
|
||||
const int NUMBER_OF_AXES { 6 };
|
||||
const int NUMBER_OF_BUTTONS { 10 };
|
||||
|
||||
/**
|
||||
* \brief Translates keyboard input to joystick input
|
||||
*
|
||||
* This class implements a virtual joystick device that uses the computer's
|
||||
* keyboard as means to get the axis, button and POV values of the joystick.
|
||||
*/
|
||||
class VirtualJoystick : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void enabledChanged();
|
||||
void povEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
|
||||
public:
|
||||
VirtualJoystick(QObject *parent = Q_NULLPTR);
|
||||
|
||||
qreal axisRange() const;
|
||||
bool joystickEnabled() const;
|
||||
QJoystickDevice *joystick();
|
||||
|
||||
public slots:
|
||||
void setJoystickID(int id);
|
||||
void setAxisRange(qreal range);
|
||||
void setJoystickEnabled(bool enabled);
|
||||
|
||||
void setAxisSensibility(qreal sensibility);
|
||||
|
||||
private slots:
|
||||
void readAxes(int key, bool pressed);
|
||||
void updateAxis();
|
||||
void readPOVs(int key, bool pressed);
|
||||
void readButtons(int key, bool pressed);
|
||||
void processKeyEvent(QKeyEvent *event, bool pressed);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
|
||||
private:
|
||||
qreal m_axisRange;
|
||||
bool m_joystickEnabled;
|
||||
QJoystickDevice m_joystick;
|
||||
|
||||
qint16 m_axisStep;
|
||||
|
||||
QVector<AxisState> m_axisStatus;
|
||||
QVector<qint16> m_axisValue;
|
||||
|
||||
QScopedPointer<QTimer> m_timerUpdateAxis;
|
||||
|
||||
void changeAxisValue(quint8 axis);
|
||||
void resetAllAxes();
|
||||
};
|
||||
|
||||
#endif
|
@ -8,6 +8,7 @@
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include "microcontroller.h"
|
||||
#include "trainjs.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "items/itemstore.h"
|
||||
#include "items/train.h"
|
||||
@ -86,6 +87,8 @@ int main(int argc, char *argv[])
|
||||
Microcontroller micro(masterIODevice);
|
||||
micro.setPower(true);
|
||||
|
||||
TrainJs::init();
|
||||
|
||||
Train::micro = µ
|
||||
Turnout::micro = µ
|
||||
ItemStore items;
|
||||
|
@ -50,9 +50,9 @@ void Microcontroller::write(const QByteArray& buffer)
|
||||
if(_port != nullptr)
|
||||
{
|
||||
_port->write(buffer);
|
||||
_port->waitForBytesWritten(1000);
|
||||
_port->waitForBytesWritten(1000);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
}
|
||||
|
||||
void Microcontroller::write(char* buffer, const size_t length)
|
||||
@ -61,9 +61,9 @@ void Microcontroller::write(char* buffer, const size_t length)
|
||||
if(_port != nullptr)
|
||||
{
|
||||
_port->write(buffer, length);
|
||||
_port->waitForBytesWritten(1000);
|
||||
//_port->waitForBytesWritten(1000);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
}
|
||||
|
||||
bool Microcontroller::connected()
|
||||
@ -103,20 +103,19 @@ void Microcontroller::setIODevice(QIODevice *port)
|
||||
std::shared_ptr<Item> Microcontroller::processTrainLine(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 13 && buffer.startsWith("NUMBER:"))
|
||||
if(bufferList.size() >= 14 && buffer.startsWith("TRAIN NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Train(bufferList[1].toInt(), bufferList[3].toInt(), bufferList[12].toInt()));
|
||||
return std::shared_ptr<Item>(new Train(bufferList[2].toInt(), bufferList[4].toInt(), bufferList[13].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Item> Microcontroller::processTurnoutLine(const QString& buffer)
|
||||
{
|
||||
qDebug()<<__func__<<" :"<<buffer;
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 6 && buffer.startsWith("NUMBER:"))
|
||||
if(bufferList.size() >= 7 && buffer.startsWith("TURNOUT NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Turnout(bufferList[1].toInt(), bufferList[1].toInt(), bufferList[5].toInt()));
|
||||
return std::shared_ptr<Item>(new Turnout(bufferList[2].toInt(), bufferList[2].toInt(), bufferList[6].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -125,12 +124,15 @@ void Microcontroller::processList(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
qDebug()<<__func__<<" :"<<buffer<<" list mode: "<<listMode;
|
||||
if(bufferList.size() >= 10 && buffer.startsWith("NUMBER:"))
|
||||
if(bufferList.size() >= 10 && buffer.contains("NUMBER:"))
|
||||
{
|
||||
std::shared_ptr<Item> item;
|
||||
if(listMode == TRAIN_LIST)
|
||||
itemList.push_back(processTrainLine(buffer));
|
||||
item = processTrainLine(buffer);
|
||||
else if(listMode == TURNOUT_LIST)
|
||||
itemList.push_back(processTurnoutLine(buffer));
|
||||
item = processTurnoutLine(buffer);
|
||||
if(item)
|
||||
itemList.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -146,7 +148,10 @@ void Microcontroller::processList(const QString& buffer)
|
||||
|
||||
void Microcontroller::processItemState(const QString& buffer)
|
||||
{
|
||||
itemChanged(static_cast<ItemData>(*processTrainLine(buffer)));
|
||||
if(_buffer.startsWith("TRAIN NUMBER:"))
|
||||
itemChanged(static_cast<ItemData>(*processTrainLine(buffer)));
|
||||
else if(_buffer.startsWith("TRAIN NUMBER:"))
|
||||
itemChanged(static_cast<ItemData>(*processTurnoutLine(buffer)));
|
||||
}
|
||||
|
||||
|
||||
@ -165,10 +170,10 @@ void Microcontroller::processMicroReturn()
|
||||
{
|
||||
listMode = TURNOUT_LIST;
|
||||
}
|
||||
else if(_buffer.startsWith("NUMBER:"))
|
||||
else if(_buffer.startsWith("TRAIN NUMBER:") || _buffer.startsWith("TRAIN NUMBER:"))
|
||||
{
|
||||
processItemState(_buffer);
|
||||
}
|
||||
}
|
||||
else if(_buffer.startsWith("TrainController"))
|
||||
{
|
||||
requestState();
|
||||
|
116
src/trainjs.cpp
Normal file
116
src/trainjs.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "trainjs.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "items/train.h"
|
||||
|
||||
TrainJs::TrainJs(int id, int axis): id_(id), axis_(axis)
|
||||
{
|
||||
longpressTimer_.setSingleShot(true);
|
||||
longpressTimer_.setInterval(LONGPRESS_TIME);
|
||||
|
||||
QJoysticks* jsmanager = QJoysticks::getInstance();
|
||||
connect(jsmanager, &QJoysticks::axisChanged, this, &TrainJs::axisChanged);
|
||||
connect(jsmanager, &QJoysticks::buttonChanged, this, &TrainJs::buttonChanged);
|
||||
connect(&longpressTimer_, &QTimer::timeout, this, &TrainJs::longpressTimeout);
|
||||
}
|
||||
|
||||
TrainJs::~TrainJs()
|
||||
{
|
||||
}
|
||||
|
||||
void TrainJs::init()
|
||||
{
|
||||
QJoysticks* jsmanager = QJoysticks::getInstance();
|
||||
jsmanager->updateInterfaces();
|
||||
const QList<QJoystickDevice*> joysticks = jsmanager->inputDevices();
|
||||
|
||||
qDebug()<<"loading joysticks number attached: "<<jsmanager->count();
|
||||
|
||||
for(int id = 0; id < joysticks.count(); ++id)
|
||||
{
|
||||
QJoystickDevice *joystick = joysticks[id];
|
||||
if(joystick->name == JOYSTICK_NAME)
|
||||
{
|
||||
for(int axis = 0; axis < joystick->axes.count(); ++axis)
|
||||
{
|
||||
js_.push_back(std::shared_ptr<TrainJs>(new TrainJs(id, axis)));
|
||||
qDebug()<<"matched joystick: "<<joystick->name<<" axis "<<axis;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<TrainJs>> TrainJs::getJsDevices()
|
||||
{
|
||||
return js_;
|
||||
}
|
||||
|
||||
std::weak_ptr<Item> TrainJs::getItem()
|
||||
{
|
||||
return item_;
|
||||
}
|
||||
void TrainJs::setItem(std::weak_ptr<Item> item)
|
||||
{
|
||||
item_ = item;
|
||||
}
|
||||
|
||||
bool TrainJs::itemIsSet()
|
||||
{
|
||||
return !item_.expired();
|
||||
}
|
||||
|
||||
void TrainJs::axisChanged(const int id, const int axis, const qreal value)
|
||||
{
|
||||
if(id == id_ && axis == axis_)
|
||||
{
|
||||
if(std::shared_ptr<Item> workitem = item_.lock())
|
||||
{
|
||||
uint8_t newValue = (value+1)*7;
|
||||
if(newValue != workitem->getValue())
|
||||
workitem->setValue(newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
reqNewItem();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TrainJs::buttonChanged(const int id, const int button, const bool pressed)
|
||||
{
|
||||
if(id == id_ && button == axis_)
|
||||
{
|
||||
if(pressed)
|
||||
{
|
||||
handleRelease = true;
|
||||
longpressTimer_.start();
|
||||
}
|
||||
else if(handleRelease)
|
||||
{
|
||||
longpressTimer_.stop();
|
||||
if(std::shared_ptr<Item> workitem = item_.lock())
|
||||
{
|
||||
if(Train* train = dynamic_cast<Train*>(workitem.get()))
|
||||
{
|
||||
if(train->getValue() == 0)
|
||||
train->reverse();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reqNewItem();
|
||||
}
|
||||
handleRelease = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrainJs::longpressTimeout()
|
||||
{
|
||||
reqNewItem();
|
||||
handleRelease = false;
|
||||
}
|
||||
|
||||
|
47
src/trainjs.h
Normal file
47
src/trainjs.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef TRAINJS_H
|
||||
#define TRAINJS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "items/item.h"
|
||||
#include "QJoysticks.h"
|
||||
|
||||
class TrainJs: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
static constexpr char JOYSTICK_NAME[] = "UVOS UsbJoy";
|
||||
static constexpr int LONGPRESS_TIME = 500;
|
||||
|
||||
inline static std::vector<std::shared_ptr<TrainJs>> js_;
|
||||
|
||||
int id_ = -1;
|
||||
int axis_ = -1;
|
||||
|
||||
QTimer longpressTimer_;
|
||||
bool handleRelease = false;
|
||||
|
||||
std::weak_ptr<Item> item_;
|
||||
TrainJs(int id, int axis);
|
||||
TrainJs() = default;
|
||||
|
||||
private slots:
|
||||
void axisChanged(const int id, const int axis, const qreal value);
|
||||
void buttonChanged(const int id, const int button, const bool pressed);
|
||||
void longpressTimeout();
|
||||
|
||||
signals:
|
||||
void reqNewItem();
|
||||
|
||||
public:
|
||||
~TrainJs();
|
||||
static std::vector<std::shared_ptr<TrainJs>> getJsDevices();
|
||||
static void init();
|
||||
std::weak_ptr<Item> getItem();
|
||||
void setItem(std::weak_ptr<Item>);
|
||||
bool itemIsSet();
|
||||
};
|
||||
|
||||
#endif // TRAINJS_H
|
@ -3,6 +3,7 @@
|
||||
#include "ui_relayscrollbox.h"
|
||||
#include "../items/train.h"
|
||||
#include "../items/turnout.h"
|
||||
#include "../trainjs.h"
|
||||
|
||||
ItemScrollBox::ItemScrollBox(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
@ -37,6 +38,16 @@ void ItemScrollBox::addItem(std::weak_ptr<Item> item)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_R), QKeySequence(Qt::Key_F), QKeySequence(Qt::Key_V));
|
||||
else if(train->getTrainId() == 4)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_T), QKeySequence(Qt::Key_G), QKeySequence(Qt::Key_B));
|
||||
|
||||
std::vector<std::shared_ptr<TrainJs>> joysticks = TrainJs::getJsDevices();
|
||||
for(auto joystick: joysticks)
|
||||
{
|
||||
if(!joystick->itemIsSet())
|
||||
{
|
||||
joystick->setItem(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(turnout)
|
||||
{
|
||||
|
@ -14,21 +14,23 @@ ItemWidget::ItemWidget(std::weak_ptr<Item> item, QWidget *parent) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if(auto workingRelay = item_.lock())
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
ui->label->setText(workingRelay->getName());
|
||||
ui->label->setText(workingItem->getName());
|
||||
|
||||
connect(ui->slider, &QSlider::valueChanged, this, &ItemWidget::moveToValue);
|
||||
connect(ui->slider, &QSlider::valueChanged, this, &ItemWidget::setValue);
|
||||
connect(ui->checkBox_f1, &QCheckBox::stateChanged, this, &ItemWidget::f1);
|
||||
connect(ui->checkBox_f2, &QCheckBox::stateChanged, this, &ItemWidget::f2);
|
||||
connect(ui->checkBox_f3, &QCheckBox::stateChanged, this, &ItemWidget::f3);
|
||||
connect(ui->checkBox_f4, &QCheckBox::stateChanged, this, &ItemWidget::f4);
|
||||
connect(ui->pushButton_reverse, &QPushButton::clicked, this, &ItemWidget::reverse);
|
||||
connect(ui->radioButton_left, &QRadioButton::clicked, this, [this](){moveToValue(0);});
|
||||
connect(ui->radioButton_right, &QRadioButton::clicked, this, [this](){moveToValue(1);});
|
||||
connect(ui->radioButton_left, &QRadioButton::clicked, this, [this](){setValue(0);});
|
||||
connect(ui->radioButton_right, &QRadioButton::clicked, this, [this](){setValue(1);});
|
||||
|
||||
Train* train = dynamic_cast<Train*>(workingRelay.get());
|
||||
Turnout* turnout = dynamic_cast<Turnout*>(workingRelay.get());
|
||||
connect(workingItem.get(), &Item::valueChanged, this, &ItemWidget::moveToValue);
|
||||
|
||||
Train* train = dynamic_cast<Train*>(workingItem.get());
|
||||
Turnout* turnout = dynamic_cast<Turnout*>(workingItem.get());
|
||||
|
||||
if(turnout)
|
||||
{
|
||||
@ -69,7 +71,16 @@ void ItemWidget::deleteItem()
|
||||
}
|
||||
}
|
||||
|
||||
void ItemWidget::moveToValue(int value)
|
||||
void ItemWidget::setValue(uint8_t value)
|
||||
{
|
||||
moveToValue(value);
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setValue(value);
|
||||
else
|
||||
disable();
|
||||
}
|
||||
|
||||
void ItemWidget::moveToValue(uint8_t value)
|
||||
{
|
||||
ui->slider->blockSignals(true);
|
||||
ui->radioButton_left->blockSignals(true);
|
||||
@ -79,9 +90,6 @@ void ItemWidget::moveToValue(int value)
|
||||
ui->slider->setValue(value);
|
||||
ui->radioButton_left->setChecked(!value);
|
||||
ui->radioButton_right->setChecked(value);
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setValue(value);
|
||||
else disable();
|
||||
|
||||
ui->slider->blockSignals(false);
|
||||
ui->radioButton_left->blockSignals(false);
|
||||
@ -127,7 +135,7 @@ void ItemWidget::reverse()
|
||||
else
|
||||
{
|
||||
qDebug()<<"!((bool)workingItem->getValue()) "<<!((bool)workingItem->getValue());
|
||||
moveToValue(!((bool)workingItem->getValue()));
|
||||
setValue(!((bool)workingItem->getValue()));
|
||||
}
|
||||
}
|
||||
else disable();
|
||||
@ -158,17 +166,17 @@ bool ItemWidget::controles(const ItemData& relay)
|
||||
|
||||
void ItemWidget::stepUp()
|
||||
{
|
||||
moveToValue(ui->slider->value()+1);
|
||||
setValue(ui->slider->value()+1);
|
||||
}
|
||||
|
||||
void ItemWidget::stepDown()
|
||||
{
|
||||
if(ui->slider->value() == 0)
|
||||
{
|
||||
moveToValue(0);
|
||||
setValue(0);
|
||||
return;
|
||||
}
|
||||
moveToValue(ui->slider->value()-1);
|
||||
setValue(ui->slider->value()-1);
|
||||
}
|
||||
|
||||
void ItemWidget::setShortcuts(QKeySequence up, QKeySequence down, QKeySequence rev)
|
||||
|
@ -26,7 +26,8 @@ signals:
|
||||
void deleteRequest(const ItemData& item);
|
||||
|
||||
private slots:
|
||||
void moveToValue(int value);
|
||||
void setValue(uint8_t value);
|
||||
void moveToValue(uint8_t value);
|
||||
void deleteItem();
|
||||
|
||||
void stepUp();
|
||||
|
@ -10,14 +10,16 @@ TARGET = traincontrollerui
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += /usr/include/libnl3/
|
||||
INCLUDEPATH += /usr/include/SDL2/
|
||||
|
||||
LIBS += -lnl-3 -lnl-genl-3
|
||||
LIBS += -lnl-3 -lnl-genl-3 -lSDL2
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
DEFINES += SDL_SUPPORTED
|
||||
|
||||
QMAKE_CXXFLAGS += -std=c++17 -O2
|
||||
|
||||
@ -25,6 +27,10 @@ SOURCES += \
|
||||
src/items/train.cpp \
|
||||
src/items/turnout.cpp \
|
||||
src/mainobject.cpp \
|
||||
src/trainjs.cpp \
|
||||
src/QJoysticks.cpp \
|
||||
src/jsbackend/SDL_Joysticks.cpp \
|
||||
src/jsbackend/VirtualJoystick.cpp \
|
||||
src/ui/itemwidget.cpp \
|
||||
src/ui/itemscrollbox.cpp \
|
||||
src/ui/mainwindow.cpp \
|
||||
@ -37,6 +43,11 @@ HEADERS += \
|
||||
src/items/train.h \
|
||||
src/items/turnout.h \
|
||||
src/mainobject.h \
|
||||
src/trainjs.h \
|
||||
src/QJoysticks.h \
|
||||
src/jsbackend/SDL_Joysticks.h \
|
||||
src/jsbackend/VirtualJoystick.h \
|
||||
src/jsbackend/JoysticksCommon.h \
|
||||
src/ui/itemwidget.h \
|
||||
src/ui/itemscrollbox.h \
|
||||
src/ui/mainwindow.h \
|
||||
|
Loading…
x
Reference in New Issue
Block a user