diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e3c3032..9e3b769c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,7 +193,9 @@ set(antimicrox_SOURCES src/joydpad.cpp src/joygyroscopesensor.cpp src/joysensor.cpp + src/joysensorbuttonpushbutton.cpp src/joysensorfactory.cpp + src/joysensorpushbutton.cpp src/joystick.cpp src/keyboard/virtualkeyboardmousewidget.cpp src/keyboard/virtualkeypushbutton.cpp @@ -213,6 +215,7 @@ set(antimicrox_SOURCES src/pt1filter.cpp src/qtkeymapperbase.cpp src/sdleventreader.cpp + src/sensorpushbuttongroup.cpp src/setjoystick.cpp src/simplekeygrabberbutton.cpp src/statisticsestimator.cpp @@ -314,8 +317,10 @@ set(antimicrox_HEADERS src/joydpad.h src/joygyroscopesensor.h src/joysensor.h + src/joysensorbuttonpushbutton.h src/joysensordirection.h src/joysensorfactory.h + src/joysensorpushbutton.h src/joysensortype.h src/joystick.h src/keyboard/virtualkeyboardmousewidget.h @@ -336,6 +341,7 @@ set(antimicrox_HEADERS src/pt1filter.h src/qtkeymapperbase.h src/sdleventreader.h + src/sensorpushbuttongroup.h src/setjoystick.h src/simplekeygrabberbutton.h src/statisticsestimator.h diff --git a/src/gui/joytabwidget.cpp b/src/gui/joytabwidget.cpp index 98f3aafe..855fbb00 100644 --- a/src/gui/joytabwidget.cpp +++ b/src/gui/joytabwidget.cpp @@ -30,11 +30,14 @@ #include "joyaxiswidget.h" #include "joybuttontypes/joycontrolstickbutton.h" #include "joybuttontypes/joydpadbutton.h" +#include "joybuttontypes/joysensorbutton.h" #include "joybuttonwidget.h" #include "joycontrolstick.h" #include "joydpad.h" +#include "joysensor.h" #include "joystick.h" #include "quicksetdialog.h" +#include "sensorpushbuttongroup.h" #include "setnamesdialog.h" #include "stickpushbuttongroup.h" #include "vdpad.h" @@ -1766,6 +1769,18 @@ void JoyTabWidget::checkStickDisplay() } } +void JoyTabWidget::checkSensorDisplay() +{ + JoySensorButton *button = qobject_cast(sender()); + JoySensor *sensor = button->getSensor(); + if ((sensor != nullptr) && sensor->hasSlotsAssigned()) + { + SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); + removeSetButtons(currentSet); + fillSetButtons(currentSet); + } +} + void JoyTabWidget::checkDPadButtonDisplay() { JoyDPadButton *button = qobject_cast(sender()); // static_cast @@ -1815,6 +1830,18 @@ void JoyTabWidget::checkStickEmptyDisplay() } } +void JoyTabWidget::checkSensorEmptyDisplay() +{ + SensorPushButtonGroup *group = qobject_cast(sender()); + JoySensor *sensor = group->getSensor(); + if ((sensor != nullptr) && !sensor->hasSlotsAssigned()) + { + SetJoystick *currentSet = m_joystick->getActiveSetJoystick(); + removeSetButtons(currentSet); + fillSetButtons(currentSet); + } +} + void JoyTabWidget::checkDPadButtonEmptyDisplay() { DPadPushButtonGroup *group = qobject_cast(sender()); // static_cast @@ -1979,6 +2006,75 @@ void JoyTabWidget::fillSetButtons(SetJoystick *set) column = 0; + QGridLayout *sensorGrid = nullptr; + QGroupBox *sensorGroup = nullptr; + int sensorGridColumn = 0; + int sensorGridRow = 0; + + for (size_t i = 0; i < SENSOR_COUNT; ++i) + { + JoySensorType type = static_cast(i); + if (!m_joystick->hasSensor(type)) + continue; + + JoySensor *sensor = currentSet->getSensor(type); + sensor->establishPropertyUpdatedConnection(); + QHash *sensorButtons = sensor->getButtons(); + + if (!hideEmptyButtons || sensor->hasSlotsAssigned()) + { + if (sensorGroup == nullptr) + sensorGroup = new QGroupBox(tr("Sensors"), this); + + if (sensorGrid == nullptr) + { + sensorGrid = new QGridLayout(); + sensorGridColumn = 0; + sensorGridRow = 0; + } + + QWidget *groupContainer = new QWidget(sensorGroup); + SensorPushButtonGroup *sensorButtonGroup = + new SensorPushButtonGroup(sensor, isKeypadUnlocked(), displayingNames, groupContainer); + if (hideEmptyButtons) + { + connect(sensorButtonGroup, &SensorPushButtonGroup::buttonSlotChanged, this, + &JoyTabWidget::checkSensorEmptyDisplay); + } + + connect(namesPushButton, &QPushButton::clicked, sensorButtonGroup, &SensorPushButtonGroup::toggleNameDisplay); + + if (sensorGridColumn > 1) + { + sensorGridColumn = 0; + sensorGridRow++; + } + + groupContainer->setLayout(sensorButtonGroup); + sensorGrid->addWidget(groupContainer, sensorGridRow, sensorGridColumn); + sensorGridColumn++; + } else + { + for (auto iter = sensorButtons->cbegin(); iter != sensorButtons->cend(); ++iter) + { + JoySensorButton *button = iter.value(); + button->establishPropertyUpdatedConnections(); + connect(button, &JoySensorButton::slotsChanged, this, &JoyTabWidget::checkSensorDisplay); + } + } + } + + if (sensorGroup != nullptr) + { + QSpacerItem *tempspacer = new QSpacerItem(10, 4, QSizePolicy::Minimum, QSizePolicy::Fixed); + QVBoxLayout *tempvbox = new QVBoxLayout; + tempvbox->addLayout(sensorGrid); + tempvbox->addItem(tempspacer); + sensorGroup->setLayout(tempvbox); + current_layout->addWidget(sensorGroup, row, column, 1, 2, Qt::AlignTop); + row++; + } + QGridLayout *hatGrid = nullptr; QGroupBox *hatGroup = nullptr; int hatGridColumn = 0; diff --git a/src/gui/joytabwidget.h b/src/gui/joytabwidget.h index d3dd3df5..28fbeb85 100644 --- a/src/gui/joytabwidget.h +++ b/src/gui/joytabwidget.h @@ -130,11 +130,13 @@ class JoyTabWidget : public QWidget void checkForUnsavedProfile(int newindex = -1); void checkStickDisplay(); + void checkSensorDisplay(); void checkDPadButtonDisplay(); void checkAxisButtonDisplay(); void checkButtonDisplay(); void checkStickEmptyDisplay(); + void checkSensorEmptyDisplay(); void checkDPadButtonEmptyDisplay(); void checkAxisButtonEmptyDisplay(); void checkButtonEmptyDisplay(); diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 6ce965cc..b0703bea 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -36,6 +36,7 @@ #include "joycontrolstickbuttonpushbutton.h" #include "joycontrolstickpushbutton.h" #include "joydpadbuttonwidget.h" +#include "joysensorpushbutton.h" #include "joystick.h" #include "joystickstatuswindow.h" #include "joytabwidget.h" @@ -846,6 +847,13 @@ void MainWindow::enableFlashActions() stickWidget->tryFlash(); } + QList sensors = ui->tabWidget->widget(i)->findChildren(); + for (const auto &sensorWidget : sensors) + { + sensorWidget->enableFlashes(); + sensorWidget->tryFlash(); + } + QList list4 = ui->tabWidget->widget(i)->findChildren(); QListIterator iter4(list4); while (iter4.hasNext()) diff --git a/src/inputdevice.cpp b/src/inputdevice.cpp index 7d2d21eb..3e5c1922 100644 --- a/src/inputdevice.cpp +++ b/src/inputdevice.cpp @@ -568,6 +568,12 @@ int InputDevice::getNumberHats() { return getActiveSetJoystick()->getNumberHats( int InputDevice::getNumberSticks() { return getActiveSetJoystick()->getNumberSticks(); } +/** + * @brief Checks if this input device has a sensor of given type + * @returns True if sensor is present, false otherwise + */ +bool InputDevice::hasSensor(JoySensorType type) { return getActiveSetJoystick()->hasSensor(type); } + int InputDevice::getNumberVDPads() { return getActiveSetJoystick()->getNumberVDPads(); } SetJoystick *InputDevice::getSetJoystick(int index) { return getJoystick_sets().value(index); } @@ -1226,8 +1232,8 @@ QString InputDevice::getDescription() QObject::tr("# of Axes: %1").arg(getNumberRawAxes()) + "\n " + QObject::tr("# of Buttons: %1").arg(getNumberRawButtons()) + "\n " + QObject::tr("# of Hats: %1").arg(getNumberHats()) + "\n " + - QObject::tr("Accelerometer: %1").arg(hasRawSensor(ACCELEROMETER)) + "\n " + - QObject::tr("Gyroscope: %1").arg(hasRawSensor(GYROSCOPE)) + "\n"; + QObject::tr("Accelerometer: %1").arg(hasSensor(ACCELEROMETER)) + "\n " + + QObject::tr("Gyroscope: %1").arg(hasSensor(GYROSCOPE)) + "\n"; return full_desc; } diff --git a/src/inputdevice.h b/src/inputdevice.h index 18c881c9..bca6730e 100644 --- a/src/inputdevice.h +++ b/src/inputdevice.h @@ -45,6 +45,7 @@ class InputDevice : public QObject virtual int getNumberAxes(); virtual int getNumberHats(); virtual int getNumberSticks(); + virtual bool hasSensor(JoySensorType type); virtual int getNumberVDPads(); int getJoyNumber(); diff --git a/src/joyaccelerometersensor.cpp b/src/joyaccelerometersensor.cpp index b18900a6..fc6b23a8 100644 --- a/src/joyaccelerometersensor.cpp +++ b/src/joyaccelerometersensor.cpp @@ -16,10 +16,12 @@ */ #include "joyaccelerometersensor.h" +#include "joybuttontypes/joyaccelerometerbutton.h" JoyAccelerometerSensor::JoyAccelerometerSensor(double rate, int originset, SetJoystick *parent_set, QObject *parent) : JoySensor(ACCELEROMETER, originset, parent_set, parent) { + populateButtons(); } JoyAccelerometerSensor::~JoyAccelerometerSensor() {} @@ -47,3 +49,25 @@ float JoyAccelerometerSensor::getZCoordinate() const { return m_current_value[2] * @returns Translated sensor type name */ QString JoyAccelerometerSensor::sensorTypeName() const { return tr("Accelerometer"); } + +/** + * @brief Initializes the JoySensorButton objects for this sensor. + */ +void JoyAccelerometerSensor::populateButtons() +{ + JoySensorButton *button = nullptr; + button = new JoyAccelerometerButton(this, SENSOR_LEFT, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_LEFT, button); + + button = new JoyAccelerometerButton(this, SENSOR_RIGHT, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_RIGHT, button); + + button = new JoyAccelerometerButton(this, SENSOR_UP, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_UP, button); + + button = new JoyAccelerometerButton(this, SENSOR_DOWN, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_DOWN, button); + + button = new JoyAccelerometerButton(this, SENSOR_BWD, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_BWD, button); +} diff --git a/src/joyaccelerometersensor.h b/src/joyaccelerometersensor.h index 1cbc96df..24c45b34 100644 --- a/src/joyaccelerometersensor.h +++ b/src/joyaccelerometersensor.h @@ -34,4 +34,7 @@ class JoyAccelerometerSensor : public JoySensor virtual float getYCoordinate() const override; virtual float getZCoordinate() const override; virtual QString sensorTypeName() const override; + + protected: + virtual void populateButtons() override; }; diff --git a/src/joybutton.cpp b/src/joybutton.cpp index cca602a0..326fc6da 100644 --- a/src/joybutton.cpp +++ b/src/joybutton.cpp @@ -2463,6 +2463,10 @@ void JoyButton::setChangeSetCondition(SetChangeCondition condition, bool passive JoyButton::SetChangeCondition JoyButton::getChangeSetCondition() { return setSelectionCondition; } +/** + * @brief Checks if this button is currently active + * @returns True if the button is pressed, false otherwise + */ bool JoyButton::getButtonState() { return isButtonPressed; } int JoyButton::getOriginSet() { return m_originset; } diff --git a/src/joygyroscopesensor.cpp b/src/joygyroscopesensor.cpp index 612628da..66a88814 100644 --- a/src/joygyroscopesensor.cpp +++ b/src/joygyroscopesensor.cpp @@ -16,10 +16,12 @@ */ #include "joygyroscopesensor.h" +#include "joybuttontypes/joygyroscopebutton.h" JoyGyroscopeSensor::JoyGyroscopeSensor(int originset, SetJoystick *parent_set, QObject *parent) : JoySensor(GYROSCOPE, originset, parent_set, parent) { + populateButtons(); } JoyGyroscopeSensor::~JoyGyroscopeSensor() {} @@ -47,3 +49,28 @@ float JoyGyroscopeSensor::getZCoordinate() const { return radToDeg(m_current_val * @returns Translated sensor type name */ QString JoyGyroscopeSensor::sensorTypeName() const { return tr("Gyroscope"); } + +/** + * @brief Initializes the JoySensorButton objects for this sensor. + */ +void JoyGyroscopeSensor::populateButtons() +{ + JoySensorButton *button = nullptr; + button = new JoyGyroscopeButton(this, SENSOR_LEFT, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_LEFT, button); + + button = new JoyGyroscopeButton(this, SENSOR_RIGHT, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_RIGHT, button); + + button = new JoyGyroscopeButton(this, SENSOR_UP, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_UP, button); + + button = new JoyGyroscopeButton(this, SENSOR_DOWN, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_DOWN, button); + + button = new JoyGyroscopeButton(this, SENSOR_FWD, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_FWD, button); + + button = new JoyGyroscopeButton(this, SENSOR_BWD, m_originset, getParentSet(), this); + m_buttons.insert(SENSOR_BWD, button); +} diff --git a/src/joygyroscopesensor.h b/src/joygyroscopesensor.h index c9ae3586..fb0d2c1f 100644 --- a/src/joygyroscopesensor.h +++ b/src/joygyroscopesensor.h @@ -34,4 +34,7 @@ class JoyGyroscopeSensor : public JoySensor virtual float getYCoordinate() const override; virtual float getZCoordinate() const override; virtual QString sensorTypeName() const override; + + protected: + virtual void populateButtons(); }; diff --git a/src/joysensor.cpp b/src/joysensor.cpp index 5229749c..dbb4eac2 100644 --- a/src/joysensor.cpp +++ b/src/joysensor.cpp @@ -18,6 +18,9 @@ #define _USE_MATH_DEFINES #include "joysensor.h" +#include "inputdevice.h" +#include "joybuttontypes/joysensorbutton.h" +#include "xml/joybuttonxml.h" #include @@ -87,6 +90,23 @@ void JoySensor::clearPendingEvent() m_pending_ignore_sets = false; } +/** + * @brief Check if any direction is mapped to a keyboard or mouse event + * @returns True if a mapping exists, false otherwise + */ +bool JoySensor::hasSlotsAssigned() const +{ + for (const auto &button : m_buttons) + { + if (button != nullptr) + { + if (button->getAssignedSlots()->count() > 0) + return true; + } + } + return false; +} + /** * @brief Get the name of this sensor * @returns Sensor name @@ -111,11 +131,21 @@ QString JoySensor::getPartialName(bool forceFullFormat, bool displayNames) const return label; } +/** + * @brief Returns the sensor name + */ +QString JoySensor::getSensorName() const { return m_sensor_name; } + /** * @brief Returns the sensor type */ JoySensorType JoySensor::getType() const { return m_type; } +/** + * @brief Returns the current sensor direction + */ +JoySensorDirection JoySensor::getCurrentDirection() const { return m_current_direction; } + bool JoySensor::inDeadZone(float *values) const { return false; } double JoySensor::calculateDirectionalDistance(JoySensorDirection direction) const { return 0; } @@ -130,6 +160,12 @@ double JoySensor::radToDeg(double value) { return value * 180 / M_PI; } */ double JoySensor::degToRad(double value) { return value * M_PI / 180; } +/** + * @brief Returns a QHash which maps the SensorDirection to + * the corresponding JoySensorButton. + */ +QHash *JoySensor::getButtons() { return &m_buttons; } + bool JoySensor::isDefault() const { return false; } /** @@ -144,3 +180,14 @@ void JoySensor::setSensorName(QString tempName) emit sensorNameChanged(); } } + +void JoySensor::establishPropertyUpdatedConnection() +{ + connect(this, &JoySensor::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); +} + +/** + * @brief Get pointer to the set that a sensor belongs to. + * @return Pointer to the set that a sensor belongs to. + */ +SetJoystick *JoySensor::getParentSet() const { return m_parent_set; } diff --git a/src/joysensor.h b/src/joysensor.h index fbc7672c..264dbd6d 100644 --- a/src/joysensor.h +++ b/src/joysensor.h @@ -17,12 +17,14 @@ #pragma once +#include #include #include "joysensordirection.h" #include "joysensortype.h" class SetJoystick; +class JoySensorButton; /** * @brief Represents one sensor in a SetJoystick and its connections to @@ -44,9 +46,13 @@ class JoySensor : public QObject bool hasPendingEvent() const; void clearPendingEvent(); + bool hasSlotsAssigned() const; + QString getPartialName(bool forceFullFormat = false, bool displayNames = false) const; + QString getSensorName() const; JoySensorType getType() const; + JoySensorDirection getCurrentDirection() const; virtual float getXCoordinate() const = 0; virtual float getYCoordinate() const = 0; virtual float getZCoordinate() const = 0; @@ -58,16 +64,26 @@ class JoySensor : public QObject static double radToDeg(double value); static double degToRad(double value); + QHash *getButtons(); + bool isDefault() const; + SetJoystick *getParentSet() const; + signals: void moved(float xaxis, float yaxis, float zaxis); + void active(float xaxis, float yaxis, float zaxis); + void released(float xaxis, float yaxis, float zaxis); void sensorNameChanged(); + void propertyUpdated(); public slots: void setSensorName(QString tempName); + void establishPropertyUpdatedConnection(); protected: + virtual void populateButtons() = 0; + JoySensorType m_type; float m_current_value[3]; @@ -78,5 +94,7 @@ class JoySensor : public QObject QString m_sensor_name; + JoySensorDirection m_current_direction; SetJoystick *m_parent_set; + QHash m_buttons; }; diff --git a/src/joysensorbuttonpushbutton.cpp b/src/joysensorbuttonpushbutton.cpp new file mode 100644 index 00000000..edbb69fe --- /dev/null +++ b/src/joysensorbuttonpushbutton.cpp @@ -0,0 +1,108 @@ +/* antimicrox Gamepad to KB+M event mapper + * Copyright (C) 2022 Max Maisel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "joysensorbuttonpushbutton.h" + +#include "joybuttoncontextmenu.h" +#include "joybuttontypes/joysensorbutton.h" +#include "joysensor.h" + +#include +#include +#include + +JoySensorButtonPushButton::JoySensorButtonPushButton(JoySensorButton *button, bool displayNames, QWidget *parent) + : FlashButtonWidget(displayNames, parent) + , m_button(button) +{ + refreshLabel(); + enableFlashes(); + + tryFlash(); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &JoySensorButtonPushButton::customContextMenuRequested, this, &JoySensorButtonPushButton::showContextMenu); + connect(m_button, &JoySensorButton::propertyUpdated, this, &JoySensorButtonPushButton::refreshLabel); + connect(m_button, &JoySensorButton::activeZoneChanged, this, &JoySensorButtonPushButton::refreshLabel); +} + +/** + * @brief Get the JoySensorButton for this mapping + */ +JoySensorButton *JoySensorButtonPushButton::getButton() { return m_button; } + +/** + * @brief Disables highlight when the sensor axis is moved + */ +void JoySensorButtonPushButton::disableFlashes() +{ + if (m_button != nullptr) + { + disconnect(m_button, &JoySensorButton::clicked, this, &JoySensorButtonPushButton::flash); + disconnect(m_button, &JoySensorButton::released, this, &JoySensorButtonPushButton::unflash); + } + unflash(); +} + +/** + * @brief Enables highlight when the sensor axis is moved + */ +void JoySensorButtonPushButton::enableFlashes() +{ + if (m_button != nullptr) + { + connect(m_button, &JoySensorButton::clicked, this, &JoySensorButtonPushButton::flash, Qt::QueuedConnection); + connect(m_button, &JoySensorButton::released, this, &JoySensorButtonPushButton::unflash, Qt::QueuedConnection); + } +} + +/** + * @brief Generate the string that will be displayed on the button + * @return Display string + */ +QString JoySensorButtonPushButton::generateLabel() +{ + QString temp = QString(); + if (m_button != nullptr) + { + if (!m_button->getActionName().isEmpty() && ifDisplayNames()) + { + qDebug() << "Action name was not empty"; + temp = m_button->getActionName().replace("&", "&&"); + + } else + { + qDebug() << "Action name was empty"; + temp = m_button->getCalculatedActiveZoneSummary().replace("&", "&&"); + } + } + + qDebug() << "Here is name of action for pushed sensor button: " << temp; + + return temp; +} + +void JoySensorButtonPushButton::showContextMenu(const QPoint &point) {} + +/** + * @brief Highlights the button when mapped button is active + */ +void JoySensorButtonPushButton::tryFlash() +{ + if (m_button != nullptr && m_button->getButtonState()) + flash(); +} diff --git a/src/joysensorbuttonpushbutton.h b/src/joysensorbuttonpushbutton.h new file mode 100644 index 00000000..49e315df --- /dev/null +++ b/src/joysensorbuttonpushbutton.h @@ -0,0 +1,50 @@ +/* antimicrox Gamepad to KB+M event mapper + * Copyright (C) 2022 Max Maisel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include "flashbuttonwidget.h" + +class JoySensorButton; +class QWidget; + +/** + * @brief A direction button in the SensorPushButtonGroup + */ +class JoySensorButtonPushButton : public FlashButtonWidget +{ + Q_OBJECT + Q_PROPERTY(bool isflashing READ isButtonFlashing) + + public: + explicit JoySensorButtonPushButton(JoySensorButton *button, bool displayNames, QWidget *parent = nullptr); + + JoySensorButton *getButton(); + void tryFlash(); + + protected: + virtual QString generateLabel() override; + + public slots: + void disableFlashes() override; + void enableFlashes() override; + + private slots: + void showContextMenu(const QPoint &point); + + private: + JoySensorButton *m_button; +}; diff --git a/src/joysensorpushbutton.cpp b/src/joysensorpushbutton.cpp new file mode 100644 index 00000000..ec8bc5a0 --- /dev/null +++ b/src/joysensorpushbutton.cpp @@ -0,0 +1,90 @@ +/* antimicrox Gamepad to KB+M event mapper + * Copyright (C) 2022 Max Maisel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "joysensorpushbutton.h" + +#include "joysensor.h" + +#include + +JoySensorPushButton::JoySensorPushButton(JoySensor *sensor, bool displayNames, QWidget *parent) + : FlashButtonWidget(displayNames, parent) + , m_sensor(sensor) +{ + refreshLabel(); + + tryFlash(); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &JoySensorPushButton::customContextMenuRequested, this, &JoySensorPushButton::showContextMenu); + + connect(m_sensor, &JoySensor::active, this, &JoySensorPushButton::flash, Qt::QueuedConnection); + connect(m_sensor, &JoySensor::released, this, &JoySensorPushButton::unflash, Qt::QueuedConnection); + connect(m_sensor, &JoySensor::sensorNameChanged, this, &JoySensorPushButton::refreshLabel); +} + +/** + * @brief Get the underlying JoySensor object. + */ +JoySensor *JoySensorPushButton::getSensor() const { return m_sensor; } + +/** + * @brief Generate the string that will be displayed on the button + * @return Display string + */ +QString JoySensorPushButton::generateLabel() +{ + QString temp = QString(); + if (!m_sensor->getSensorName().isEmpty() && ifDisplayNames()) + temp.append(m_sensor->getPartialName(false, true)); + else + temp.append(m_sensor->getPartialName(false)); + + qDebug() << "Name of joy sensor push button: " << temp; + + return temp; +} + +/** + * @brief Disables highlight when the sensor axis is moved + */ +void JoySensorPushButton::disableFlashes() +{ + disconnect(m_sensor, &JoySensor::active, this, &JoySensorPushButton::flash); + disconnect(m_sensor, &JoySensor::released, this, &JoySensorPushButton::unflash); + unflash(); +} + +/** + * @brief Enables highlight when the sensor axis is moved + */ +void JoySensorPushButton::enableFlashes() +{ + connect(m_sensor, &JoySensor::active, this, &JoySensorPushButton::flash, Qt::QueuedConnection); + connect(m_sensor, &JoySensor::released, this, &JoySensorPushButton::unflash, Qt::QueuedConnection); +} + +void JoySensorPushButton::showContextMenu(const QPoint &point) {} + +/** + * @brief Highlights the button when sensor is not centered + */ +void JoySensorPushButton::tryFlash() +{ + if (m_sensor->getCurrentDirection() != JoySensorDirection::SENSOR_CENTERED) + flash(); +} diff --git a/src/joysensorpushbutton.h b/src/joysensorpushbutton.h new file mode 100644 index 00000000..28a62255 --- /dev/null +++ b/src/joysensorpushbutton.h @@ -0,0 +1,49 @@ +/* antimicrox Gamepad to KB+M event mapper + * Copyright (C) 2022 Max Maisel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include "flashbuttonwidget.h" + +class JoySensor; +class QWidget; + +/** + * @brief The central button in a SensorPushButtonGroup + */ +class JoySensorPushButton : public FlashButtonWidget +{ + Q_OBJECT + + public: + explicit JoySensorPushButton(JoySensor *sensor, bool displayNames, QWidget *parent = nullptr); + + JoySensor *getSensor() const; + void tryFlash(); + + protected: + virtual QString generateLabel() override; + + public slots: + void disableFlashes() override; + void enableFlashes() override; + + private slots: + void showContextMenu(const QPoint &point); + + private: + JoySensor *m_sensor; +}; diff --git a/src/sensorpushbuttongroup.cpp b/src/sensorpushbuttongroup.cpp new file mode 100644 index 00000000..765c123a --- /dev/null +++ b/src/sensorpushbuttongroup.cpp @@ -0,0 +1,110 @@ +/* antimicrox Gamepad to KB+M event mapper + * Copyright (C) 2022 Max Maisel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sensorpushbuttongroup.h" + +#include "buttoneditdialog.h" +#include "inputdevice.h" +#include "joybuttontypes/joysensorbutton.h" +#include "joysensor.h" +#include "joysensorbuttonpushbutton.h" +#include "joysensorpushbutton.h" + +#include +#include +#include + +SensorPushButtonGroup::SensorPushButtonGroup(JoySensor *sensor, bool keypadUnlocked, bool displayNames, QWidget *parent) + : QGridLayout(parent) + , m_sensor(sensor) + , m_display_names(displayNames) + , m_keypad_unlocked(keypadUnlocked) +{ + m_left_button = generateBtnToGrid(SENSOR_LEFT, 1, 0); + m_right_button = generateBtnToGrid(SENSOR_RIGHT, 1, 2); + m_up_button = generateBtnToGrid(SENSOR_UP, 0, 1); + m_down_button = generateBtnToGrid(SENSOR_DOWN, 2, 1); + m_bwd_button = generateBtnToGrid(SENSOR_BWD, 0, 2); + + if (m_sensor->getType() == GYROSCOPE) + m_fwd_button = generateBtnToGrid(SENSOR_FWD, 2, 0); + else + m_fwd_button = nullptr; + + m_sensor_widget = new JoySensorPushButton(m_sensor, m_display_names, parentWidget()); + m_sensor_widget->setIcon( + QIcon::fromTheme(QString::fromUtf8("games_config_options"), QIcon(":/images/actions/games_config_options.png"))); + + connect(m_sensor_widget, &JoySensorPushButton::clicked, this, &SensorPushButtonGroup::showSensorDialog); + + addWidget(m_sensor_widget, 1, 1); +} + +/** + * @brief Generates a new push button at the given grid coordinates + * @returns Newly created push button + */ +JoySensorButtonPushButton *SensorPushButtonGroup::generateBtnToGrid(JoySensorDirection sensorDir, int gridRow, int gridCol) +{ + JoySensorButton *button = m_sensor->getButtons()->value(sensorDir); + JoySensorButtonPushButton *pushbutton = new JoySensorButtonPushButton(button, m_display_names, parentWidget()); + + connect(pushbutton, &JoySensorButtonPushButton::clicked, this, + [this, pushbutton] { openSensorButtonDialog(pushbutton); }); + + button->establishPropertyUpdatedConnections(); + connect(button, &JoySensorButton::slotsChanged, this, &SensorPushButtonGroup::propagateSlotsChanged); + + addWidget(pushbutton, gridRow, gridCol); + return pushbutton; +} + +void SensorPushButtonGroup::propagateSlotsChanged() { emit buttonSlotChanged(); } + +/** + * @brief Get the underlying JoySensor object. + */ +JoySensor *SensorPushButtonGroup::getSensor() const { return m_sensor; } + +/** + * @brief Shows the button mapping dialog for the given direction button + */ +void SensorPushButtonGroup::openSensorButtonDialog(JoySensorButtonPushButton *pushbutton) +{ + ButtonEditDialog *dialog = new ButtonEditDialog(pushbutton->getButton(), m_sensor->getParentSet()->getInputDevice(), + m_keypad_unlocked, parentWidget()); + dialog->show(); +} + +void SensorPushButtonGroup::showSensorDialog() {} + +void SensorPushButtonGroup::toggleNameDisplay() +{ + m_display_names = !m_display_names; + + m_up_button->toggleNameDisplay(); + m_down_button->toggleNameDisplay(); + m_left_button->toggleNameDisplay(); + m_right_button->toggleNameDisplay(); + m_bwd_button->toggleNameDisplay(); + if (m_fwd_button != nullptr) + m_fwd_button->toggleNameDisplay(); + + m_sensor_widget->toggleNameDisplay(); +} + +bool SensorPushButtonGroup::ifDisplayNames() const { return m_display_names; } diff --git a/src/sensorpushbuttongroup.h b/src/sensorpushbuttongroup.h new file mode 100644 index 00000000..ca7afe90 --- /dev/null +++ b/src/sensorpushbuttongroup.h @@ -0,0 +1,70 @@ +/* antimicrox Gamepad to KB+M event mapper + * Copyright (C) 2022 Max Maisel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once + +#include "joysensordirection.h" + +#include + +class JoySensor; +class QWidget; +class JoySensorButtonPushButton; +class JoySensorPushButton; + +/** + * @brief The sensor button mapping widget in the main window. + * The layout is based on a isometric 3D view with the regular + * XY axes and a diagonal Z axis. + */ +class SensorPushButtonGroup : public QGridLayout +{ + Q_OBJECT + + public: + explicit SensorPushButtonGroup(JoySensor *sensor, bool keypadUnlocked, bool displayNames = false, + QWidget *parent = nullptr); + JoySensor *getSensor() const; + + bool ifDisplayNames() const; + + signals: + void buttonSlotChanged(); + + public slots: + void toggleNameDisplay(); + + private slots: + void propagateSlotsChanged(); + void openSensorButtonDialog(JoySensorButtonPushButton *pushbutton); + void showSensorDialog(); + + private: + JoySensor *m_sensor; + bool m_display_names; + bool m_keypad_unlocked; + + JoySensorButtonPushButton *m_up_button; + JoySensorButtonPushButton *m_down_button; + JoySensorButtonPushButton *m_left_button; + JoySensorButtonPushButton *m_right_button; + JoySensorButtonPushButton *m_fwd_button; + JoySensorButtonPushButton *m_bwd_button; + + JoySensorPushButton *m_sensor_widget; + + JoySensorButtonPushButton *generateBtnToGrid(JoySensorDirection sensorDir, int gridRow, int gridCol); +};