[Simulator] Virtual joystick tweaks. (#4666)

* [Simulator] Create a reusable RadioTrimWidget; Move all trim-related enums to boards.h; Make sure aux trims are accounted for in SimulatorInterface; Trims now use toolbuttons with icons instead of pushbuttons with text.

* [Simulator] New buttons & icons for virtual joystick axis hold/fix toggles; Joystick ball is now slightly scaled to stick area.

* [Simulator] Virtual joystick now "follows" mouse clicks within the stick area (left-click on empty space will attract the control node).
This commit is contained in:
Max Paperno
2017-03-22 21:05:27 +01:00
committed by Bertrand Songis
parent 919e8eb962
commit d68778ec81
23 changed files with 556 additions and 254 deletions
+1
View File
@@ -51,6 +51,7 @@ set(simulation_HDRS
widgets/radiofaderwidget.h
widgets/radioknobwidget.h
widgets/radioswitchwidget.h
widgets/radiotrimwidget.h
widgets/sliderwidget.h
widgets/virtualjoystickwidget.h
)
@@ -57,7 +57,7 @@ class TxOutputs
struct Trims
{
int values[CPN_MAX_STICKS]; /* lh lv rv rh */
int values[CPN_MAX_STICKS + CPN_MAX_AUX_TRIMS]; /* lh lv rv rh t5 t6 */
bool extended;
};
+26 -37
View File
@@ -55,7 +55,7 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator
flags(flags),
lastPhase(-1),
buttonPressed(0),
trimPressed(TRIM_NONE),
trimPressed(255),
startupFromFile(false),
deleteTempRadioData(false),
saveTempRadioData(false),
@@ -113,13 +113,13 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface *simulator
vJoyRight = new VirtualJoystickWidget(this, 'R');
ui->rightStickLayout->addWidget(vJoyRight);
connect(vJoyLeft, SIGNAL(trimButtonPressed(int)), this, SLOT(onTrimPressed(int)));
connect(vJoyLeft, SIGNAL(trimButtonReleased()), this, SLOT(onTrimReleased()));
connect(vJoyLeft, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int)));
connect(vJoyLeft, &VirtualJoystickWidget::trimButtonPressed, this, &SimulatorWidget::onTrimPressed);
connect(vJoyLeft, &VirtualJoystickWidget::trimButtonReleased, this, &SimulatorWidget::onTrimReleased);
connect(vJoyLeft, &VirtualJoystickWidget::trimSliderMoved, this, &SimulatorWidget::onTrimSliderMoved);
connect(vJoyRight, SIGNAL(trimButtonPressed(int)), this, SLOT(onTrimPressed(int)));
connect(vJoyRight, SIGNAL(trimButtonReleased()), this, SLOT(onTrimReleased()));
connect(vJoyRight, SIGNAL(trimSliderMoved(int,int)), this, SLOT(onTrimSliderMoved(int,int)));
connect(vJoyRight, &VirtualJoystickWidget::trimButtonPressed, this, &SimulatorWidget::onTrimPressed);
connect(vJoyRight, &VirtualJoystickWidget::trimButtonReleased, this, &SimulatorWidget::onTrimReleased);
connect(vJoyRight, &VirtualJoystickWidget::trimSliderMoved, this, &SimulatorWidget::onTrimSliderMoved);
timer->setInterval(10);
connect(timer, SIGNAL(timeout()), this, SLOT(onTimerEvent()));
@@ -739,19 +739,19 @@ void SimulatorWidget::getValues()
// Read stick trim values from firmware simulator and set joystick widgets as needed.
void SimulatorWidget::setTrims()
{
typedef VirtualJoystickWidget VJW;
using namespace Board;
static Trims lastTrims;
Trims trims;
simulator->getTrims(trims);
if (trims.values[VJW::TRIM_AXIS_L_X] != lastTrims.values[VJW::TRIM_AXIS_L_X])
vJoyLeft->setTrimValue(VJW::TRIM_AXIS_L_X, trims.values[VJW::TRIM_AXIS_L_X]);
if (trims.values[VJW::TRIM_AXIS_L_Y] != lastTrims.values[VJW::TRIM_AXIS_L_Y])
vJoyLeft->setTrimValue(VJW::TRIM_AXIS_L_Y, trims.values[VJW::TRIM_AXIS_L_Y]);
if (trims.values[VJW::TRIM_AXIS_R_Y] != lastTrims.values[VJW::TRIM_AXIS_R_Y])
vJoyRight->setTrimValue(VJW::TRIM_AXIS_R_Y, trims.values[VJW::TRIM_AXIS_R_Y]);
if (trims.values[VJW::TRIM_AXIS_R_X] != lastTrims.values[VJW::TRIM_AXIS_R_X])
vJoyRight->setTrimValue(VJW::TRIM_AXIS_R_X, trims.values[VJW::TRIM_AXIS_R_X]);
if (trims.values[TRIM_AXIS_LH] != lastTrims.values[TRIM_AXIS_LH])
vJoyLeft->setTrimValue(TRIM_AXIS_LH, trims.values[TRIM_AXIS_LH]);
if (trims.values[TRIM_AXIS_LV] != lastTrims.values[TRIM_AXIS_LV])
vJoyLeft->setTrimValue(TRIM_AXIS_LV, trims.values[TRIM_AXIS_LV]);
if (trims.values[TRIM_AXIS_RV] != lastTrims.values[TRIM_AXIS_RV])
vJoyRight->setTrimValue(TRIM_AXIS_RV, trims.values[TRIM_AXIS_RV]);
if (trims.values[TRIM_AXIS_RH] != lastTrims.values[TRIM_AXIS_RH])
vJoyRight->setTrimValue(TRIM_AXIS_RH, trims.values[TRIM_AXIS_RH]);
if (trims.extended != lastTrims.extended) {
int trimMin = -125, trimMax = +125;
@@ -759,10 +759,10 @@ void SimulatorWidget::setTrims()
trimMin = -500;
trimMax = +500;
}
vJoyLeft->setTrimRange(VJW::TRIM_AXIS_L_X, trimMin, trimMax);
vJoyLeft->setTrimRange(VJW::TRIM_AXIS_L_Y, trimMin, trimMax);
vJoyRight->setTrimRange(VJW::TRIM_AXIS_R_Y, trimMin, trimMax);
vJoyRight->setTrimRange(VJW::TRIM_AXIS_R_X, trimMin, trimMax);
vJoyLeft->setTrimRange(TRIM_AXIS_LH, trimMin, trimMax);
vJoyLeft->setTrimRange(TRIM_AXIS_LV, trimMin, trimMax);
vJoyRight->setTrimRange(TRIM_AXIS_RV, trimMin, trimMax);
vJoyRight->setTrimRange(TRIM_AXIS_RH, trimMin, trimMax);
}
lastTrims = trims;
}
@@ -771,17 +771,6 @@ void SimulatorWidget::setTrims()
* Event handlers/private slots
*/
//void SimulatorDialog::showEvent(QShowEvent *)
//{
// if (firstShow && isVisible()) {
// firstShow = false;
// }
//}
//void SimulatorDialog::closeEvent(QCloseEvent *)
//{
//}
void SimulatorWidget::mousePressEvent(QMouseEvent *event)
{
if (radioUiWidget)
@@ -819,19 +808,19 @@ void SimulatorWidget::onTimerEvent()
}
}
void SimulatorWidget::onTrimPressed(int which)
void SimulatorWidget::onTrimPressed(int index)
{
trimPressed = which;
trimPressed = index;
}
void SimulatorWidget::onTrimReleased()
void SimulatorWidget::onTrimReleased(int)
{
trimPressed = TRIM_NONE;
trimPressed = 255;
}
void SimulatorWidget::onTrimSliderMoved(int which, int value)
void SimulatorWidget::onTrimSliderMoved(int index, int value)
{
simulator->setTrim(which, value);
simulator->setTrim(index, value);
}
void SimulatorWidget::centerSticks()
+3 -5
View File
@@ -140,16 +140,14 @@ class SimulatorWidget : public QWidget
#endif
private slots:
//virtual void showEvent(QShowEvent *);
//virtual void closeEvent(QCloseEvent *);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void wheelEvent(QWheelEvent *event);
void onTimerEvent();
void onTrimPressed(int which);
void onTrimReleased();
void onTrimSliderMoved(int which, int value);
void onTrimPressed(int index);
void onTrimReleased(int);
void onTrimSliderMoved(int index, int value);
void centerSticks();
void onjoystickAxisValueChanged(int axis, int value);
@@ -0,0 +1,134 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#ifndef _RADIOTRIMWIDGET_H_
#define _RADIOTRIMWIDGET_H_
#include "radiowidget.h"
#include "sliderwidget.h"
#include <QToolButton>
class RadioTrimWidget : public RadioWidget
{
Q_OBJECT
public:
explicit RadioTrimWidget(Qt::Orientation orientation = Qt::Vertical, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
RadioWidget(parent, f),
m_slider(NULL)
{
init(orientation);
}
explicit RadioTrimWidget(const QString & labelText, Qt::Orientation orientation = Qt::Vertical, int value = 0, QWidget * parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) :
RadioWidget(labelText, value, parent, f),
m_slider(NULL)
{
init(orientation);
}
void setIndices(int sliderIdx = -1, int decrBtnIdx = -1, int incrBtnIdx = -1)
{
setIndex(sliderIdx);
m_btnDecIndex = decrBtnIdx;
m_btnIncIndex = incrBtnIdx;
}
void setTrimRange(int min, int max)
{
if (m_slider)
m_slider->setRange(min, max);
}
signals:
void trimButtonPressed(int index);
void trimButtonReleased(int index);
void trimSliderMoved(int index, int value);
protected slots:
void init(Qt::Orientation orientation)
{
m_type = RADIO_WIDGET_TRIM;
m_slider = new SliderWidget(this);
m_slider->setOrientation(orientation);
setTrimRange(-125, 125);
setIndices();
QSize btnIcnSz(12, 12);
QWidget * trimWidget = new QWidget(this);
QBoxLayout * trimLayout = new QVBoxLayout(trimWidget);
trimLayout->setSpacing(5);
trimLayout->setContentsMargins(8, 8, 8, 8);
QToolButton * trimBtnInc = new QToolButton(trimWidget);
trimBtnInc->setIconSize(btnIcnSz);
QToolButton * trimBtnDec = new QToolButton(trimWidget);
trimBtnDec->setIconSize(btnIcnSz);
Qt::Alignment algn;
if (orientation == Qt::Horizontal) {
trimWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
trimLayout->setDirection(QBoxLayout::RightToLeft);
trimBtnInc->setArrowType(Qt::RightArrow);
trimBtnDec->setArrowType(Qt::LeftArrow);
algn = Qt::AlignVCenter;
}
else {
trimWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
trimLayout->setDirection(QBoxLayout::TopToBottom);
trimBtnInc->setArrowType(Qt::UpArrow);
trimBtnDec->setArrowType(Qt::DownArrow);
algn = Qt::AlignHCenter;
}
trimLayout->addWidget(trimBtnInc, 0, algn);
trimLayout->addWidget(m_slider, 1, algn);
trimLayout->addWidget(trimBtnDec, 0, algn);
setWidget(trimWidget, algn);
connect(m_slider, &SliderWidget::valueChanged, this, &RadioWidget::setValue);
connect(this, &RadioWidget::valueChanged, this, &RadioTrimWidget::onValueChanged);
connect(trimBtnInc, &QToolButton::pressed, [this]() { emit trimButtonPressed(m_btnIncIndex); });
connect(trimBtnInc, &QToolButton::released, [this]() { emit trimButtonReleased(m_btnIncIndex); });
connect(trimBtnDec, &QToolButton::pressed, [this]() { emit trimButtonPressed(m_btnDecIndex); });
connect(trimBtnDec, &QToolButton::released, [this]() { emit trimButtonReleased(m_btnDecIndex); });
}
void onValueChanged(int value)
{
m_slider->blockSignals(true);
m_slider->setValue(value);
m_slider->blockSignals(false);
emit trimSliderMoved(m_index, m_value);
}
protected:
SliderWidget * m_slider;
int m_btnDecIndex;
int m_btnIncIndex;
};
#endif // _RADIOTRIMWIDGET_H_
@@ -58,7 +58,7 @@ void RadioWidget::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(m_value);
emit valueChanged(value);
}
}
@@ -166,7 +166,7 @@ void RadioWidget::addLabel()
}
}
void RadioWidget::setWidget(QWidget * widget)
void RadioWidget::setWidget(QWidget * widget, Qt::Alignment align)
{
if (m_controlWidget) {
m_gridLayout->removeWidget(m_controlWidget);
@@ -174,7 +174,7 @@ void RadioWidget::setWidget(QWidget * widget)
}
m_controlWidget = widget;
if (widget) {
m_gridLayout->addWidget(widget, 0, 0, 1, 1, Qt::AlignHCenter);
m_gridLayout->addWidget(widget, 0, 0, 1, 1, align);
m_gridLayout->setRowStretch(0, 1);
}
}
@@ -41,6 +41,7 @@ class RadioWidget : public QWidget
RADIO_WIDGET_SWITCH,
RADIO_WIDGET_KNOB,
RADIO_WIDGET_FADER,
RADIO_WIDGET_TRIM,
RADIO_WIDGET_STICK // actually one axis of a stick
};
@@ -76,7 +77,6 @@ class RadioWidget : public QWidget
void setStateData(const QByteArray & data);
void changeVisibility(bool visible);
virtual int getValue() const;
int getIndex() const;
int getType() const;
@@ -87,7 +87,7 @@ class RadioWidget : public QWidget
void init();
void addLabel();
void setWidget(QWidget * widget = NULL);
void setWidget(QWidget * widget = NULL, Qt::Alignment align = Qt::AlignHCenter);
int m_value;
int m_index;
@@ -105,7 +105,7 @@ class RadioWidget : public QWidget
signals:
void valueChanged(int m_value);
void valueChanged(int value);
void flagsChanged(quint16 flags);
};
@@ -42,6 +42,7 @@ class SliderWidget : public QSlider
{
if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonDblClick) {
setValue(0);
emit sliderMoved(0);
event->accept();
}
QSlider::mousePressEvent(event);
@@ -18,27 +18,32 @@
* GNU General Public License for more details.
*/
#define GBALL_SIZE 20
#define RESX 1024
#define GBALL_SIZE 25
#define GBALL_SIZE_MN 20
#define GBALL_SIZE_MX 35
#include "virtualjoystickwidget.h"
#include "boards.h"
#include "constants.h"
#include "sliderwidget.h"
#include "modeledit/node.h"
#include "helpers.h"
#include "radiotrimwidget.h"
#include "simulator.h"
VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool showTrims, bool showBtns, bool showValues, QSize size) :
QWidget(parent),
stickSide(side),
prefSize(size),
hTrimSlider(NULL),
vTrimSlider(NULL),
hTrimWidget(NULL),
vTrimWidget(NULL),
btnHoldX(NULL),
btnHoldY(NULL),
btnFixX(NULL),
btnFixY(NULL),
nodeLabelX(NULL),
nodeLabelY(NULL)
nodeLabelY(NULL),
m_stickPressed(false)
{
ar = (float)size.width() / size.height();
extraSize = QSize(0, 0);
@@ -54,12 +59,11 @@ VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool s
gv = new QGraphicsView(this);
gv->setSizePolicy(sizePolicy);
gv->setMinimumSize(size);
// gv->setMaximumSize(size + size * 3);
// gv->setFixedSize(prefSize);
gv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
gv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
gv->setRenderHints(QPainter::Antialiasing);
scene = new QGraphicsScene(gv);
scene = new CustomGraphicsScene(gv);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
gv->setScene(scene);
@@ -83,14 +87,12 @@ VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool s
}
if (showTrims) {
QWidget * hTrimWidget = createTrimWidget('H');
QWidget * vTrimWidget = createTrimWidget('V');
hTrimWidget = createTrimWidget('H');
vTrimWidget = createTrimWidget('V');
layout->addWidget(vTrimWidget, 1, colvt, 1, 1);
layout->addWidget(hTrimWidget, 2, 2, 1, 1);
hTrimSlider = hTrimWidget->findChild<SliderWidget *>();
vTrimSlider = vTrimWidget->findChild<SliderWidget *>();
extraSize += QSize(vTrimWidget->sizeHint().width(), hTrimWidget->sizeHint().height());
}
else {
@@ -131,10 +133,12 @@ VirtualJoystickWidget::VirtualJoystickWidget(QWidget *parent, QChar side, bool s
layout->addItem(new QSpacerItem(0, 0), 1, 0, 2, 1); // r1-2 c0: left h spacer
layout->addWidget(gv, 1, 2, 1, 1); // r1 c2: stick widget
layout->addItem(new QSpacerItem(0, 0), 1, 4, 2, 1); // r1-2 c4: right h spacer
layout->addItem(new QSpacerItem(0, 0), 3, 0, 1, 5); // r3 c0-4: bot v spacer
layout->addItem(new QSpacerItem(0, 0), 3, 0, 1, 5); // r4 c0-4: bot v spacer
connect(node, SIGNAL(xChanged()), this, SLOT(updateNodeValueLabels()));
connect(node, SIGNAL(yChanged()), this, SLOT(updateNodeValueLabels()));
connect(node, &Node::xChanged, this, &VirtualJoystickWidget::updateNodeValueLabels);
connect(node, &Node::yChanged, this, &VirtualJoystickWidget::updateNodeValueLabels);
connect(scene, &CustomGraphicsScene::mouseEvent, this, &VirtualJoystickWidget::onGsMouseEvent);
setSize(prefSize, frameSize());
}
@@ -176,25 +180,25 @@ QPointF VirtualJoystickWidget::getStickPos()
void VirtualJoystickWidget::setTrimValue(int which, int value)
{
SliderWidget * slider = getTrimSlider(which);
if (slider) {
slider->setValue(value);
RadioTrimWidget * trim = getTrimWidget(which);
if (trim) {
trim->setValue(value);
}
}
void VirtualJoystickWidget::setTrimRange(int which, int min, int max)
{
SliderWidget * slider = getTrimSlider(which);
if (slider) {
slider->setRange(min, max);
RadioTrimWidget * trim = getTrimWidget(which);
if (trim) {
trim->setTrimRange(min, max);
}
}
int VirtualJoystickWidget::getTrimValue(int which)
{
SliderWidget * slider = getTrimSlider(which);
if (slider) {
return slider->value();
RadioTrimWidget * trim = getTrimWidget(which);
if (trim) {
return trim->getValue();
}
return 0;
}
@@ -269,13 +273,15 @@ void VirtualJoystickWidget::setSize(const QSize & size, const QSize &)
layout->setColumnStretch(2, newGvSz);
layout->setRowStretch(1, newGvSz);
//prefSize = QSize(newGvSz + extraSize.width(), newGvSz + extraSize.height());
gv->resize(newGvSz, newGvSz);
gv->updateGeometry();
int ballSize = (newGvSz * GBALL_SIZE * 0.005f);
ballSize = qMin(GBALL_SIZE_MX, qMax(ballSize, GBALL_SIZE_MN));
QRectF qr = (QRectF)gv->contentsRect();
qreal w = qr.width() - GBALL_SIZE;
qreal h = qr.height() - GBALL_SIZE;
qreal w = qr.width() - ballSize;
qreal h = qr.height() - ballSize;
qreal cx = qr.width() / 2;
qreal cy = qr.height() / 2;
qreal nodeX = node->getX();
@@ -283,120 +289,64 @@ void VirtualJoystickWidget::setSize(const QSize & size, const QSize &)
scene->setSceneRect(-cx,-cy,w,h);
node->setBallSize(ballSize);
node->setX(nodeX);
node->setY(nodeY);
//qDebug() << thisAspectRatio << size << newGvSz << spacerSz << extraSize << gv->geometry() << gv->contentsRect() << gv->frameRect() << getStickPos();
}
QWidget *VirtualJoystickWidget::createTrimWidget(QChar type)
RadioTrimWidget * VirtualJoystickWidget::createTrimWidget(QChar type)
{
QSizePolicy sp;
QString btnAlabel, btnBlabel;
RadioTrimWidget * trimWidget = new RadioTrimWidget(type == 'H' ? Qt::Horizontal : Qt::Vertical);
trimWidget->setIndices(getTrimSliderType(type), getTrimButtonType(type, 0), getTrimButtonType(type, 1));
QString btnAname = QString("%1TrimBtnA_%2").arg(type.toLower()).arg(stickSide);
QString btnBname = QString("%1TrimBtnB_%2").arg(type.toLower()).arg(stickSide);
QString sliderName = QString("%1TrimAdj_%2").arg(type.toLower()).arg(stickSide);
QWidget * trimWidget = new QWidget(this);
QBoxLayout * trimLayout = new QVBoxLayout(trimWidget);
SliderWidget * trimSlider = new SliderWidget(trimWidget);
QPushButton * trimBtnA = new QPushButton(trimWidget);
QPushButton * trimBtnB = new QPushButton(trimWidget);
if (type == 'H') {
sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
trimLayout->setDirection(QBoxLayout::LeftToRight);
trimSlider->setFixedHeight(23);
trimSlider->setOrientation(Qt::Horizontal);
trimBtnA->setText(ARROW_LEFT);
trimBtnB->setText(ARROW_RIGHT);
}
else {
sp = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
trimLayout->setDirection(QBoxLayout::TopToBottom);
trimSlider->setFixedWidth(23);
trimSlider->setOrientation(Qt::Vertical);
trimBtnA->setText(ARROW_UP);
trimBtnB->setText(ARROW_DOWN);
}
trimWidget->setSizePolicy(sp);
trimSlider->setObjectName(sliderName);
trimSlider->setProperty("trimType", getTrimSliderType(type));
trimSlider->setSizePolicy(sp);
trimSlider->setMinimum(-125);
trimSlider->setMaximum(125);
trimBtnA->setObjectName(btnAname);
trimBtnA->setProperty("btnType", getTrimButtonType(type, 0));
trimBtnA->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
trimBtnA->setMaximumSize(QSize(23, 23));
trimBtnA->setAutoDefault(false);
trimBtnB->setObjectName(btnBname);
trimBtnB->setProperty("btnType", getTrimButtonType(type, 1));
trimBtnB->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
trimBtnB->setMaximumSize(QSize(23, 23));
trimBtnB->setAutoDefault(false);
trimLayout->setSpacing(6);
trimLayout->setContentsMargins(8, 9, 8, 9);
trimLayout->addWidget(trimBtnA);
trimLayout->addWidget(trimSlider);
trimLayout->addWidget(trimBtnB);
connect(trimBtnA, SIGNAL(pressed()), SLOT(onTrimPressed()));
connect(trimBtnB, SIGNAL(pressed()), SLOT(onTrimPressed()));
connect(trimBtnA, SIGNAL(released()), SIGNAL(trimButtonReleased()));
connect(trimBtnB, SIGNAL(released()), SIGNAL(trimButtonReleased()));
connect(trimSlider, SIGNAL(valueChanged(int)), SLOT(onSliderChange(int)));
connect(trimWidget, &RadioTrimWidget::trimButtonPressed, this, &VirtualJoystickWidget::trimButtonPressed);
connect(trimWidget, &RadioTrimWidget::trimButtonReleased, this, &VirtualJoystickWidget::trimButtonReleased);
connect(trimWidget, &RadioTrimWidget::trimSliderMoved, this, &VirtualJoystickWidget::trimSliderMoved);
return trimWidget;
}
QPushButton * VirtualJoystickWidget::createButtonWidget(int type)
QToolButton * VirtualJoystickWidget::createButtonWidget(int type)
{
QString btnRole, btnLabel;
QString btnLabel, tooltip;
QIcon icon;
switch (type) {
case HOLD_Y:
btnLabel = tr("Hold Y");
btnLabel = tr("Hld Y");
tooltip = tr("Hold Vertical stick position.");
icon = Simulator::SimulatorIcon("hold_y");
break;
case FIX_Y:
btnLabel = tr("Fix Y");
tooltip = tr("Prevent Vertical movement of stick.");
icon = Simulator::SimulatorIcon("fixed_y");
break;
case FIX_X:
btnLabel = tr("Fix X");
tooltip = tr("Prevent Horizontal movement of stick.");
icon = Simulator::SimulatorIcon("fixed_x");
break;
case HOLD_X:
default:
btnLabel = tr("Hold X");
btnLabel = tr("Hld X");
tooltip = tr("Hold Horizontal stick position.");
icon = Simulator::SimulatorIcon("hold_x");
break;
default:
return NULL;
}
QPushButton * btn = new QPushButton(this);
btn->setObjectName(QString("%1_%2").arg(btnLabel.replace(" ", "_")).arg(stickSide));
QToolButton * btn = new QToolButton(this);
btn->setProperty("btnType", type);
btn->setIcon(icon);
btn->setIconSize(QSize(20, 20));
btn->setToolButtonStyle(Qt::ToolButtonIconOnly);
btn->setText(btnLabel);
QFont font;
font.setPointSize(8);
btn->setFont(font);
btn->setStyleSheet(QLatin1String( \
"QPushButton {"
" background-color: #EEEEEE;"
" border-style: outset;"
" border-width: 1px;"
" border-radius: 4px;"
" border-color: black;"
" padding: 2px;"
"}"
"QPushButton:checked {\n"
" background-color: #4CC417;\n"
" border-style: inset;\n"
"}" ));
btn->setToolTip(tooltip);
btn->setCheckable(true);
btn->setAutoRaise(true);
connect(btn, SIGNAL(toggled(bool)), SLOT(onButtonChange(bool)));
connect(btn, &QToolButton::toggled, this, &VirtualJoystickWidget::onButtonChange);
return btn;
}
@@ -423,76 +373,63 @@ QLayout *VirtualJoystickWidget::createNodeValueLayout(QChar type, QLabel *& valL
int VirtualJoystickWidget::getTrimSliderType(QChar type)
{
using namespace Board;
if (stickSide == 'L') {
if (type == 'H')
return TRIM_AXIS_L_X;
return TRIM_AXIS_LH;
else
return TRIM_AXIS_L_Y;
return TRIM_AXIS_LV;
}
else {
if (type == 'H')
return TRIM_AXIS_R_X;
return TRIM_AXIS_RH;
else
return TRIM_AXIS_R_Y;
return TRIM_AXIS_RV;
}
}
int VirtualJoystickWidget::getTrimButtonType(QChar type, int pos)
{
using namespace Board;
if (stickSide == 'L') {
if (type == 'H') {
if (pos == 0)
return TRIM_LH_L;
return TRIM_SW_LH_DEC;
else
return TRIM_LH_R;
return TRIM_SW_LH_INC;
}
else {
if (pos == 0)
return TRIM_LV_UP;
return TRIM_SW_LV_DEC;
else
return TRIM_LV_DN;
return TRIM_SW_LV_INC;
}
}
// right side
else {
if (type == 'H') {
if (pos == 0)
return TRIM_RH_L;
return TRIM_SW_RH_DEC;
else
return TRIM_RH_R;
return TRIM_SW_RH_INC;
}
else {
if (pos == 0)
return TRIM_RV_UP;
return TRIM_SW_RV_DEC;
else
return TRIM_RV_DN;
return TRIM_SW_RV_INC;
}
}
}
SliderWidget *VirtualJoystickWidget::getTrimSlider(int which)
RadioTrimWidget * VirtualJoystickWidget::getTrimWidget(int which)
{
if (which == TRIM_AXIS_L_X || which == TRIM_AXIS_R_X)
return hTrimSlider;
if (which == Board::TRIM_AXIS_LH || which == Board::TRIM_AXIS_RH)
return hTrimWidget;
else
return vTrimSlider;
}
void VirtualJoystickWidget::onTrimPressed()
{
if (!sender() || !sender()->property("btnType").isValid())
return;
emit trimButtonPressed(sender()->property("btnType").toInt());
}
void VirtualJoystickWidget::onSliderChange(int value)
{
if (!sender() || !sender()->property("trimType").isValid())
return;
emit trimSliderMoved(sender()->property("trimType").toInt(), value);
updateNodeValueLabels();
return vTrimWidget;
}
void VirtualJoystickWidget::onButtonChange(bool checked)
@@ -523,3 +460,57 @@ void VirtualJoystickWidget::updateNodeValueLabels()
if (nodeLabelY)
nodeLabelY->setText(QString("%1").arg((qreal)node->getY() * -100 + getTrimValue(1) / 5, 2, 'f', 0));
}
void VirtualJoystickWidget::onGsMouseEvent(QGraphicsSceneMouseEvent * event)
{
if (!node)
return;
//qDebug() << event->type() << event->scenePos() << event->buttons() << event->isAccepted() << m_stickPressed;
if (event->type() == QEvent::GraphicsSceneMouseRelease && m_stickPressed) {
node->setPressed(false);
m_stickPressed = false;
return;
}
if (!(event->buttons() & Qt::LeftButton))
return;
if (event->type() == QEvent::GraphicsSceneMousePress) {
node->setPressed(true);
m_stickPressed = true;
}
else if (!m_stickPressed || event->type() != QEvent::GraphicsSceneMouseMove) {
return;
}
node->setPos(event->scenePos());
}
/*
* CustomGraphicsScene
*/
void CustomGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
QGraphicsScene::mousePressEvent(event);
if (!event->isAccepted()) {
event->accept();
emit mouseEvent(event);
}
}
void CustomGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
QGraphicsScene::mouseReleaseEvent(event);
emit mouseEvent(event);
}
void CustomGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
QGraphicsScene::mouseMoveEvent(event);
if (!event->isAccepted() && (event->buttons() & Qt::LeftButton)) {
event->accept();
emit mouseEvent(event);
}
}
@@ -27,24 +27,18 @@
#include <QGridLayout>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPushButton>
#include <QToolButton>
#include <QLabel>
class CustomGraphicsScene;
class Node;
class SliderWidget;
class RadioTrimWidget;
class VirtualJoystickWidget : public QWidget
{
Q_OBJECT
public:
enum TrimAxes {
TRIM_AXIS_L_X = 0,
TRIM_AXIS_L_Y,
TRIM_AXIS_R_Y,
TRIM_AXIS_R_X,
};
enum ConstraintTypes {
HOLD_X = 0,
HOLD_Y,
@@ -73,38 +67,60 @@ class VirtualJoystickWidget : public QWidget
virtual void resizeEvent(QResizeEvent *event);
signals:
void trimButtonPressed(int which);
void trimButtonReleased();
void trimSliderMoved(int which, int value);
void trimButtonPressed(int index);
void trimButtonReleased(int index);
void trimSliderMoved(int index, int value);
protected slots:
void onTrimPressed();
void onSliderChange(int value);
void onButtonChange(bool checked);
void updateNodeValueLabels();
void onGsMouseEvent(QGraphicsSceneMouseEvent * event);
protected:
void setSize(const QSize & size, const QSize &);
QWidget * createTrimWidget(QChar type);
QPushButton * createButtonWidget(int type);
RadioTrimWidget * createTrimWidget(QChar type);
QToolButton * createButtonWidget(int type);
QLayout * createNodeValueLayout(QChar type, QLabel *& valLabel);
int getTrimSliderType(QChar type);
int getTrimButtonType(QChar type, int pos);
SliderWidget * getTrimSlider(int which);
RadioTrimWidget * getTrimWidget(int which);
QChar stickSide;
QSize prefSize;
QGridLayout * layout;
QGraphicsView * gv;
QGraphicsScene * scene;
CustomGraphicsScene * scene;
Node * node;
SliderWidget * hTrimSlider, * vTrimSlider;
QPushButton * btnHoldX, * btnHoldY;
QPushButton * btnFixX, * btnFixY;
RadioTrimWidget * hTrimWidget;
RadioTrimWidget * vTrimWidget;
QToolButton * btnHoldX, * btnHoldY;
QToolButton * btnFixX, * btnFixY;
QLabel * nodeLabelX, * nodeLabelY;
QSize extraSize;
float ar; // aspect ratio
bool m_stickPressed;
};
/*
* Custom GraphicsScene for mouse handling
*/
class CustomGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
CustomGraphicsScene(QObject *parent = Q_NULLPTR) :
QGraphicsScene(parent)
{}
signals:
void mouseEvent(QGraphicsSceneMouseEvent * event);
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
};
#endif // VIRTUALJOYSTICKWIDGET_H