From 7c7920642a9436fb3f195bd59630c40d84474ad3 Mon Sep 17 00:00:00 2001 From: Max Maisel Date: Thu, 5 May 2022 18:29:17 +0200 Subject: [PATCH] Add sensor buttons to JoyTabWidget If a controller has sensors, add configuration buttons similar to a control stick to the main view. The layout is based on a isometric 3D view with the regular XY axes and a diagonal Z axis. Add a JoySensor button for every direction to the JoySensor object and connect them to the "flashing" events. Add dummy methods for required JoySensor interfaces. Make all the QT connections in JoyTabWidgets as for a JoyControlStick. But I'm not sure for what checkSensorDisplay and checkSensorEmptyDisplay are really used. The new buttons have no function yet. Even though it is possible to map buttons to the sensor directions, but no events will be generated yet. --- CMakeLists.txt | 6 ++ src/gui/joytabwidget.cpp | 96 ++++++++++++++++++++++++++ src/gui/joytabwidget.h | 2 + src/gui/mainwindow.cpp | 9 +++ src/inputdevice.cpp | 6 ++ src/inputdevice.h | 1 + src/joybutton.cpp | 4 ++ src/joysensor.cpp | 74 ++++++++++++++++++++ src/joysensor.h | 18 +++++ src/joysensorbuttonpushbutton.cpp | 108 ++++++++++++++++++++++++++++++ src/joysensorbuttonpushbutton.h | 50 ++++++++++++++ src/joysensorpushbutton.cpp | 90 +++++++++++++++++++++++++ src/joysensorpushbutton.h | 49 ++++++++++++++ src/sensorpushbuttongroup.cpp | 107 +++++++++++++++++++++++++++++ src/sensorpushbuttongroup.h | 70 +++++++++++++++++++ 15 files changed, 690 insertions(+) create mode 100644 src/joysensorbuttonpushbutton.cpp create mode 100644 src/joysensorbuttonpushbutton.h create mode 100644 src/joysensorpushbutton.cpp create mode 100644 src/joysensorpushbutton.h create mode 100644 src/sensorpushbuttongroup.cpp create mode 100644 src/sensorpushbuttongroup.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ed15ac529..066ad792b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,8 @@ set(antimicrox_SOURCES src/joycontrolstickstatusbox.cpp src/joydpad.cpp src/joysensor.cpp + src/joysensorbuttonpushbutton.cpp + src/joysensorpushbutton.cpp src/joystick.cpp src/keyboard/virtualkeyboardmousewidget.cpp src/keyboard/virtualkeypushbutton.cpp @@ -210,6 +212,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 @@ -310,6 +313,8 @@ set(antimicrox_HEADERS src/joydpad.h src/joysensor.h src/joysensordirection.h + src/joysensorbuttonpushbutton.h + src/joysensorpushbutton.h src/joysensortype.h src/joystick.h src/keyboard/virtualkeyboardmousewidget.h @@ -330,6 +335,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 98f3aafec..855fbb00a 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 d3dd3df50..28fbeb85d 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 6ce965cca..aeace03ae 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,14 @@ void MainWindow::enableFlashActions() stickWidget->tryFlash(); } + QList sensors = ui->tabWidget->widget(i)->findChildren(); + for (auto iter = sensors.cbegin(); iter != sensors.cend(); ++iter) + { + JoySensorPushButton *sensorWidget = *iter; + 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 d0680413b..e84eae9bf 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); } diff --git a/src/inputdevice.h b/src/inputdevice.h index 18c881c9c..bca6730eb 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/joybutton.cpp b/src/joybutton.cpp index cca602a05..326fc6da1 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/joysensor.cpp b/src/joysensor.cpp index 61839cefb..b6235bf87 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/joyaccelerometerbutton.h" +#include "joybuttontypes/joygyroscopebutton.h" #include @@ -28,6 +31,7 @@ JoySensor::JoySensor(JoySensorType type, double rate, int originset, SetJoystick , m_originset(originset) , m_parent_set(parent_set) { + populateButtons(); } JoySensor::~JoySensor() {} @@ -87,6 +91,8 @@ void JoySensor::clearPendingEvent() m_pending_ignore_sets = false; } +bool JoySensor::hasSlotsAssigned() const { return false; } + /** * @brief Get the name of this sensor * @returns Sensor name @@ -119,11 +125,18 @@ QString JoySensor::getPartialName(bool forceFullFormat, bool displayNames) const return label; } +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; } + /** * @brief Get the value for the corresponding X axis. * @return X axis value in m/s^2 for accelerometer or °/s for gyroscope. @@ -176,6 +189,12 @@ bool JoySensor::inDeadZone(float *values) const { return false; } double JoySensor::calculateDirectionalDistance(JoySensorDirection direction) const { return 0; } +/** + * @brief Returns a QHash which maps the SensorDirection to + * the corresponding JoySensorButton. + */ +QHash *JoySensor::getButtons() { return &m_buttons; } + bool JoySensor::isDefault() const { return false; } /** @@ -191,6 +210,61 @@ void JoySensor::setSensorName(QString tempName) } } +void JoySensor::establishPropertyUpdatedConnection() +{ + connect(this, &JoySensor::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited); +} + void JoySensor::setDefaultSensorName(QString tempname) { m_default_sensor_name = tempname; } QString JoySensor::getDefaultSensorName() const { return m_default_sensor_name; } + +/** + * @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; } + +/** + * @brief Initializes the JoySensorButton objects for this sensor. + */ +void JoySensor::populateButtons() +{ + JoySensorButton *button = nullptr; + if (m_type == ACCELEROMETER) + { + 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); + } else + { + 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/joysensor.h b/src/joysensor.h index 445aed49e..859bd482b 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; float getXCoordinate() const; float getYCoordinate() const; float getZCoordinate() const; @@ -55,18 +61,28 @@ class JoySensor : public QObject bool inDeadZone(float *values) const; double calculateDirectionalDistance(JoySensorDirection direction) const; + QHash *getButtons(); + bool isDefault() const; void setDefaultSensorName(QString tempname); QString getDefaultSensorName() 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: + void populateButtons(); + JoySensorType m_type; float m_current_value[3]; @@ -79,5 +95,7 @@ class JoySensor : public QObject QString m_default_sensor_name; private: + 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 000000000..edbb69fe2 --- /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 000000000..49e315dfd --- /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 000000000..ec8bc5a02 --- /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 000000000..28a62255e --- /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 000000000..056edb940 --- /dev/null +++ b/src/sensorpushbuttongroup.cpp @@ -0,0 +1,107 @@ +/* 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_fwd_button = generateBtnToGrid(SENSOR_BWD, 0, 2); + + if (m_sensor->getType() == GYROSCOPE) + m_bwd_button = generateBtnToGrid(SENSOR_FWD, 2, 0); + else + m_bwd_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; } + +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_fwd_button->toggleNameDisplay(); + if (m_bwd_button != nullptr) + m_bwd_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 000000000..ca7afe909 --- /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); +};