mirror of
https://github.com/EdgeTX/edgetx.git
synced 2025-07-26 17:55:12 +03:00
Reduce width of all simulator windows (#4154)
* [simu] Reduce width of all simulator windows and also height of Horus window. (https://github.com/opentx/opentx/issues/3135) * [simu] New vertical channel outputs layout for all simulators, all outputs in one window and horizontally scrollable. Consolidate outputs and gvars widgets to one code base for all sims. Make simulator dialog re-sizable. * [simu] Make simulation dialog resizable, and greatly reduce minimum size requirements of all simulators. Introduces new VirtualJoystickWidget class with all controls. Simplifies every simulator dialog UI form.
This commit is contained in:
parent
df835da07d
commit
b0de35f57d
15 changed files with 3879 additions and 6099 deletions
|
@ -59,10 +59,10 @@ enum BoardEnum {
|
|||
#define CPN_MAX_KEYS 32
|
||||
#define CPN_MAX_MOUSE_ANALOGS 2
|
||||
|
||||
const char * const ARROW_LEFT = "\xE2\x86\x90";
|
||||
const char * const ARROW_UP = "\xE2\x86\x91";
|
||||
const char * const ARROW_RIGHT = "\xE2\x86\x92";
|
||||
const char * const ARROW_DOWN = "\xE2\x86\x93";
|
||||
const char * const ARROW_LEFT = "\u2190";
|
||||
const char * const ARROW_UP = "\u2191";
|
||||
const char * const ARROW_RIGHT = "\u2192";
|
||||
const char * const ARROW_DOWN = "\u2193";
|
||||
|
||||
#if defined(DEBUG)
|
||||
#define HORUS_READY_FOR_RELEASE() true
|
||||
|
|
|
@ -4,6 +4,7 @@ set(simulation_SRCS
|
|||
trainersimu.cpp
|
||||
debugoutput.cpp
|
||||
simulatorinterface.cpp
|
||||
virtualjoystickwidget.cpp
|
||||
)
|
||||
|
||||
set(simulation_UIS
|
||||
|
@ -24,6 +25,7 @@ set(simulation_HDRS
|
|||
telemetrysimu.h
|
||||
trainersimu.h
|
||||
debugoutput.h
|
||||
virtualjoystickwidget.h
|
||||
)
|
||||
|
||||
if(SDL_FOUND)
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -24,10 +24,7 @@
|
|||
#include <iostream>
|
||||
#include "helpers.h"
|
||||
#include "simulatorinterface.h"
|
||||
#include "sliderwidget.h"
|
||||
|
||||
#define GBALL_SIZE 20
|
||||
#define RESX 1024
|
||||
#include "virtualjoystickwidget.h"
|
||||
|
||||
int SimulatorDialog::screenshotIdx = 0;
|
||||
SimulatorDialog * traceCallbackInstance = 0;
|
||||
|
@ -87,9 +84,10 @@ SimulatorDialog::SimulatorDialog(QWidget * parent, SimulatorInterface *simulator
|
|||
TrainerSimu(0),
|
||||
DebugOut(0),
|
||||
buttonPressed(0),
|
||||
trimPressed (TRIM_NONE),
|
||||
trimPressed(TRIM_NONE),
|
||||
middleButtonPressed(false)
|
||||
{
|
||||
setWindowFlags(Qt::Window);
|
||||
//shorcut for telemetry simulator
|
||||
// new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_T), this, SLOT(openTelemetrySimulator()));
|
||||
new QShortcut(QKeySequence(Qt::Key_F4), this, SLOT(openTelemetrySimulator()));
|
||||
|
@ -110,6 +108,23 @@ void SimulatorDialog::closeEvent (QCloseEvent *)
|
|||
{
|
||||
simulator->stop();
|
||||
timer->stop();
|
||||
//g.simuWinGeo(GetCurrentFirmware()->getId(), saveGeometry());
|
||||
}
|
||||
|
||||
void SimulatorDialog::showEvent(QShowEvent * event)
|
||||
{
|
||||
static bool firstShow = true;
|
||||
if (firstShow) {
|
||||
if (flags & SIMULATOR_FLAGS_STICK_MODE_LEFT) {
|
||||
vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
|
||||
vJoyLeft->setStickY(1);
|
||||
}
|
||||
else {
|
||||
vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
|
||||
vJoyRight->setStickY(1);
|
||||
}
|
||||
firstShow = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::mousePressEvent(QMouseEvent *event)
|
||||
|
@ -126,24 +141,9 @@ void SimulatorDialog::mouseReleaseEvent(QMouseEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::onTrimPressed()
|
||||
void SimulatorDialog::onTrimPressed(int which)
|
||||
{
|
||||
if (sender()->objectName() == QString("trimHL_L"))
|
||||
trimPressed = TRIM_LH_L;
|
||||
else if (sender()->objectName() == QString("trimHL_R"))
|
||||
trimPressed = TRIM_LH_R;
|
||||
else if (sender()->objectName() == QString("trimVL_D"))
|
||||
trimPressed = TRIM_LV_DN;
|
||||
else if (sender()->objectName() == QString("trimVL_U"))
|
||||
trimPressed = TRIM_LV_UP;
|
||||
else if (sender()->objectName() == QString("trimVR_D"))
|
||||
trimPressed = TRIM_RV_DN;
|
||||
else if (sender()->objectName() == QString("trimVR_U"))
|
||||
trimPressed = TRIM_RV_UP;
|
||||
else if (sender()->objectName() == QString("trimHR_L"))
|
||||
trimPressed = TRIM_RH_L;
|
||||
else if (sender()->objectName() == QString("trimHR_R"))
|
||||
trimPressed = TRIM_RH_R;
|
||||
trimPressed = which;
|
||||
}
|
||||
|
||||
void SimulatorDialog::onTrimReleased()
|
||||
|
@ -151,6 +151,11 @@ void SimulatorDialog::onTrimReleased()
|
|||
trimPressed = TRIM_NONE;
|
||||
}
|
||||
|
||||
void SimulatorDialog::onTrimSliderMoved(int which, int value)
|
||||
{
|
||||
simulator->setTrim(which, value);
|
||||
}
|
||||
|
||||
void SimulatorDialog::openTelemetrySimulator()
|
||||
{
|
||||
// allow only one instance
|
||||
|
@ -264,28 +269,34 @@ void SimulatorDialog::initUi(T * ui)
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
windowName = tr("Simulating Radio (%1)").arg(GetCurrentFirmware()->getName());
|
||||
setWindowTitle(windowName);
|
||||
|
||||
simulator->setSdPath(g.profile[g.id()].sdPath());
|
||||
simulator->setVolumeGain(g.profile[g.id()].volumeGain());
|
||||
|
||||
lcd = ui->lcd;
|
||||
leftStick = ui->leftStick;
|
||||
rightStick = ui->rightStick;
|
||||
lcd->setData(simulator->getLcd(), lcdWidth, lcdHeight, lcdDepth);
|
||||
|
||||
tabWidget = ui->tabWidget;
|
||||
pots = findWidgets<QDial *>(this, "pot%1");
|
||||
potLabels = findWidgets<QLabel *>(this, "potLabel%1");
|
||||
potValues = findWidgets<QLabel *>(this, "potValue%1");
|
||||
sliders = findWidgets<QSlider *>(this, "slider%1");
|
||||
|
||||
trimHLeft = ui->trimHLeft;
|
||||
trimVLeft = ui->trimVLeft;
|
||||
trimHRight = ui->trimHRight;
|
||||
trimVRight = ui->trimVRight;
|
||||
tabWidget = ui->tabWidget;
|
||||
leftXPerc = ui->leftXPerc;
|
||||
leftYPerc = ui->leftYPerc;
|
||||
rightXPerc = ui->rightXPerc;
|
||||
rightYPerc = ui->rightYPerc;
|
||||
vJoyLeft = new VirtualJoystickWidget(this, 'L');
|
||||
ui->leftStickLayout->addWidget(vJoyLeft);
|
||||
|
||||
setupSticks();
|
||||
vJoyRight = new VirtualJoystickWidget(this, 'R');
|
||||
ui->rightStickLayout->addWidget(vJoyRight);
|
||||
|
||||
resize(0, 0); // to force min height, min width
|
||||
setFixedSize(width(), height());
|
||||
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(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)));
|
||||
|
||||
#ifdef JOYSTICKS
|
||||
if (g.jsSupport()) {
|
||||
|
@ -313,14 +324,11 @@ void SimulatorDialog::initUi(T * ui)
|
|||
joystick->sensitivities[j] = 0;
|
||||
joystick->deadzones[j]=0;
|
||||
}
|
||||
nodeRight->setCenteringY(false); //mode 1,3 -> THR on right
|
||||
ui->holdRightY->setChecked(true);
|
||||
nodeRight->setCenteringX(false); //mode 1,3 -> THR on right
|
||||
ui->holdRightX->setChecked(true);
|
||||
nodeLeft->setCenteringY(false); //mode 1,3 -> THR on right
|
||||
ui->holdLeftY->setChecked(true);
|
||||
nodeLeft->setCenteringX(false); //mode 1,3 -> THR on right
|
||||
ui->holdLeftX->setChecked(true);
|
||||
//mode 1,3 -> THR on right
|
||||
vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
|
||||
vJoyRight->setStickConstraint(VirtualJoystickWidget::HOLD_X, true);
|
||||
vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_Y, true);
|
||||
vJoyLeft->setStickConstraint(VirtualJoystickWidget::HOLD_X, true);
|
||||
connect(joystick, SIGNAL(axisValueChanged(int, int)), this, SLOT(onjoystickAxisValueChanged(int, int)));
|
||||
}
|
||||
else {
|
||||
|
@ -331,126 +339,15 @@ void SimulatorDialog::initUi(T * ui)
|
|||
}
|
||||
#endif
|
||||
|
||||
windowName = tr("Simulating Radio (%1)").arg(GetCurrentFirmware()->getName());
|
||||
setWindowTitle(windowName);
|
||||
|
||||
simulator->setSdPath(g.profile[g.id()].sdPath());
|
||||
simulator->setVolumeGain(g.profile[g.id()].volumeGain());
|
||||
lcd->setData(simulator->getLcd(), lcdWidth, lcdHeight, lcdDepth);
|
||||
|
||||
if (flags & SIMULATOR_FLAGS_STICK_MODE_LEFT) {
|
||||
nodeLeft->setCenteringY(false);
|
||||
ui->holdLeftY->setChecked(true);
|
||||
}
|
||||
else {
|
||||
nodeRight->setCenteringY(false);
|
||||
ui->holdRightY->setChecked(true);
|
||||
}
|
||||
|
||||
setupOutputsDisplay();
|
||||
setupGVarsDisplay();
|
||||
setTrims();
|
||||
|
||||
int outputs = std::min(32, GetCurrentFirmware()->getCapability(Outputs));
|
||||
if (outputs <= 16) {
|
||||
// hide second Outputs tab
|
||||
tabWidget->removeTab(tabWidget->indexOf(ui->outputs2));
|
||||
}
|
||||
else {
|
||||
tabWidget->setTabText(tabWidget->indexOf(ui->outputs), tr("Outputs") + QString(" 1-%1").arg(16));
|
||||
tabWidget->setTabText(tabWidget->indexOf(ui->outputs2), tr("Outputs") + QString(" 17-%1").arg(outputs));
|
||||
}
|
||||
for (int i=0; i<outputs; i++) {
|
||||
QGridLayout * outputTab = ui->channelsLayout;
|
||||
int column = i / (std::min(16,outputs)/2);
|
||||
int line = i % (std::min(16,outputs)/2);
|
||||
if (i >= 16 ) {
|
||||
outputTab = ui->channelsLayout2;
|
||||
column = (i-16) / (std::min(16,outputs-16)/2);
|
||||
line = (i-16) % (std::min(16,outputs-16)/2);
|
||||
}
|
||||
QLabel * label = new QLabel(tabWidget);
|
||||
label->setText(RawSource(SOURCE_TYPE_CH, i).toString());
|
||||
outputTab->addWidget(label, line, column == 0 ? 0 : 5, 1, 1);
|
||||
//restoreGeometry(g.simuWinGeo(GetCurrentFirmware()->getId()));
|
||||
|
||||
QSlider * slider = new QSlider(tabWidget);
|
||||
slider->setEnabled(false);
|
||||
/*slider->setMaximumSize(QSize(16777215, 18));
|
||||
slider->setStyleSheet(QString::fromUtf8("QSlider::sub-page:horizontal:disabled {\n"
|
||||
"border-color: #999;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"QSlider::add-page:horizontal:disabled {\n"
|
||||
"border-color: #999;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"QSlider::handle:horizontal:disabled {\n"
|
||||
"background: #0000CC;\n"
|
||||
"border: 1px solid #aaa;\n"
|
||||
"border-radius: 4px;\n"
|
||||
"}")); */
|
||||
slider->setMinimum(-1024);
|
||||
slider->setMaximum(1024);
|
||||
slider->setPageStep(128);
|
||||
slider->setTracking(false);
|
||||
slider->setOrientation(Qt::Horizontal);
|
||||
slider->setInvertedAppearance(false);
|
||||
slider->setTickPosition(QSlider::TicksBelow);
|
||||
channelSliders << slider;
|
||||
outputTab->addWidget(slider, line, column == 0 ? 1 : 4, 1, 1);
|
||||
if (flags & SIMULATOR_FLAGS_NOTX)
|
||||
tabWidget->setCurrentIndex(1);
|
||||
|
||||
QLabel * value = new QLabel(tabWidget);
|
||||
value->setMinimumSize(QSize(50, 0));
|
||||
value->setAlignment(Qt::AlignCenter);
|
||||
channelValues << value;
|
||||
outputTab->addWidget(value, line, column == 0 ? 2 : 3, 1, 1);
|
||||
}
|
||||
|
||||
int switches = GetCurrentFirmware()->getCapability(LogicalSwitches);
|
||||
for (int i=0; i<switches; i++) {
|
||||
QFrame * swtch = createLogicalSwitch(tabWidget, i, logicalSwitchLabels);
|
||||
ui->logicalSwitchesLayout->addWidget(swtch, i / (switches/2), i % (switches/2), 1, 1);
|
||||
if (outputs > 16) {
|
||||
// repeat logical switches on second outputs tab
|
||||
swtch = createLogicalSwitch(tabWidget, i, logicalSwitchLabels2);
|
||||
ui->logicalSwitchesLayout2->addWidget(swtch, i / (switches/2), i % (switches/2), 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int fmodes = GetCurrentFirmware()->getCapability(FlightModes);
|
||||
int gvars = GetCurrentFirmware()->getCapability(Gvars);
|
||||
if (gvars>0) {
|
||||
for (int fm=0; fm<fmodes; fm++) {
|
||||
QLabel * label = new QLabel(tabWidget);
|
||||
label->setText(QString("FM%1").arg(fm));
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
ui->gvarsLayout->addWidget(label, 0, fm+1);
|
||||
}
|
||||
for (int i=0; i<gvars; i++) {
|
||||
QLabel * label = new QLabel(tabWidget);
|
||||
label->setText(QString("GV%1").arg(i+1));
|
||||
label->setAutoFillBackground(true);
|
||||
if ((i % 2) ==0 ) {
|
||||
label->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }");
|
||||
}
|
||||
ui->gvarsLayout->addWidget(label, i+1, 0);
|
||||
for (int fm=0; fm<fmodes; fm++) {
|
||||
QLabel * value = new QLabel(tabWidget);
|
||||
value->setAutoFillBackground(true);
|
||||
value->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
if ((i % 2) ==0 ) {
|
||||
value->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }");
|
||||
}
|
||||
gvarValues << value;
|
||||
ui->gvarsLayout->addWidget(value, i+1, fm+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SIMULATOR_FLAGS_NOTX) {
|
||||
ui->tabWidget->setCurrentWidget(ui->outputs);
|
||||
}
|
||||
else {
|
||||
ui->tabWidget->setCurrentWidget(ui->simu);
|
||||
}
|
||||
}
|
||||
|
||||
QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QVector<QLabel *> & labels)
|
||||
|
@ -459,17 +356,135 @@ QFrame * SimulatorDialog::createLogicalSwitch(QWidget * parent, int switchNo, QV
|
|||
swtch->setAutoFillBackground(true);
|
||||
swtch->setFrameShape(QFrame::Panel);
|
||||
swtch->setFrameShadow(QFrame::Raised);
|
||||
swtch->setLineWidth(2);
|
||||
swtch->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
swtch->setMaximumHeight(18);
|
||||
QVBoxLayout * layout = new QVBoxLayout(swtch);
|
||||
layout->setContentsMargins(2, 2, 2, 2);
|
||||
layout->setContentsMargins(2, 0, 2, 0);
|
||||
QFont font;
|
||||
font.setPointSize(8);
|
||||
QLabel * label = new QLabel(swtch);
|
||||
label->setFont(font);
|
||||
label->setText(RawSwitch(SWITCH_TYPE_VIRTUAL, switchNo+1).toString());
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
labels << label;
|
||||
layout->addWidget(label);
|
||||
return swtch;
|
||||
}
|
||||
|
||||
void SimulatorDialog::setupOutputsDisplay()
|
||||
{
|
||||
// setup Outputs tab
|
||||
QWidget * outputsWidget = new QWidget();
|
||||
QGridLayout * gridLayout = new QGridLayout(outputsWidget);
|
||||
gridLayout->setHorizontalSpacing(0);
|
||||
gridLayout->setVerticalSpacing(3);
|
||||
gridLayout->setContentsMargins(5, 3, 5, 3);
|
||||
// logical switches area
|
||||
QWidget * logicalSwitches = new QWidget(outputsWidget);
|
||||
logicalSwitches->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||
QGridLayout * logicalSwitchesLayout = new QGridLayout(logicalSwitches);
|
||||
logicalSwitchesLayout->setHorizontalSpacing(3);
|
||||
logicalSwitchesLayout->setVerticalSpacing(2);
|
||||
logicalSwitchesLayout->setContentsMargins(0, 0, 0, 0);
|
||||
gridLayout->addWidget(logicalSwitches, 0, 0, 1, 1);
|
||||
// channels area
|
||||
QScrollArea * scrollArea = new QScrollArea(outputsWidget);
|
||||
QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
sp.setHorizontalStretch(0);
|
||||
sp.setVerticalStretch(0);
|
||||
scrollArea->setSizePolicy(sp);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
QWidget * channelsWidget = new QWidget();
|
||||
QGridLayout * channelsLayout = new QGridLayout(channelsWidget);
|
||||
channelsLayout->setHorizontalSpacing(4);
|
||||
channelsLayout->setVerticalSpacing(3);
|
||||
channelsLayout->setContentsMargins(0, 0, 0, 3);
|
||||
scrollArea->setWidget(channelsWidget);
|
||||
gridLayout->addWidget(scrollArea, 1, 0, 1, 1);
|
||||
|
||||
tabWidget->insertTab(1, outputsWidget, QString(tr("Outputs")));
|
||||
|
||||
// populate outputs
|
||||
int outputs = std::min(32, GetCurrentFirmware()->getCapability(Outputs));
|
||||
int column = 0;
|
||||
for (int i=0; i<outputs; i++) {
|
||||
QLabel * label = new QLabel(tabWidget);
|
||||
label->setText(" " + RawSource(SOURCE_TYPE_CH, i).toString() + " ");
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
channelsLayout->addWidget(label, 0, column, 1, 1);
|
||||
|
||||
QSlider * slider = new QSlider(tabWidget);
|
||||
slider->setEnabled(false);
|
||||
slider->setMinimum(-1024);
|
||||
slider->setMaximum(1024);
|
||||
slider->setPageStep(128);
|
||||
slider->setTracking(false);
|
||||
slider->setOrientation(Qt::Vertical);
|
||||
slider->setInvertedAppearance(false);
|
||||
slider->setTickPosition(QSlider::TicksRight);
|
||||
slider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
|
||||
QLabel * value = new QLabel(tabWidget);
|
||||
value->setMinimumSize(QSize(value->fontMetrics().size(Qt::TextSingleLine, "-100.0").width(), 0));
|
||||
value->setAlignment(Qt::AlignCenter);
|
||||
value->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
channelValues << value;
|
||||
channelsLayout->addWidget(value, 1, column, 1, 1);
|
||||
|
||||
channelSliders << slider;
|
||||
channelsLayout->addWidget(slider, 2, column++, 1, 1);
|
||||
channelsLayout->setAlignment(slider, Qt::AlignHCenter);
|
||||
}
|
||||
|
||||
// populate logical switches
|
||||
int switches = GetCurrentFirmware()->getCapability(LogicalSwitches);
|
||||
int rows = switches / (switches > 16 ? 4 : 2);
|
||||
for (int i=0; i<switches; i++) {
|
||||
QFrame * swtch = createLogicalSwitch(tabWidget, i, logicalSwitchLabels);
|
||||
logicalSwitchesLayout->addWidget(swtch, i / rows, i % rows, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::setupGVarsDisplay()
|
||||
{
|
||||
int fmodes = GetCurrentFirmware()->getCapability(FlightModes);
|
||||
int gvars = GetCurrentFirmware()->getCapability(Gvars);
|
||||
if (gvars>0) {
|
||||
// setup GVars tab
|
||||
QWidget * gvarsWidget = new QWidget();
|
||||
QGridLayout * gvarsLayout = new QGridLayout(gvarsWidget);
|
||||
tabWidget->addTab(gvarsWidget, QString(tr("GVars")));
|
||||
|
||||
for (int fm=0; fm<fmodes; fm++) {
|
||||
QLabel * label = new QLabel(tabWidget);
|
||||
label->setText(QString("FM%1").arg(fm));
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
gvarsLayout->addWidget(label, 0, fm+1);
|
||||
}
|
||||
for (int i=0; i<gvars; i++) {
|
||||
QLabel * label = new QLabel(tabWidget);
|
||||
label->setText(QString("GV%1").arg(i+1));
|
||||
label->setAutoFillBackground(true);
|
||||
if ((i % 2) ==0 ) {
|
||||
label->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }");
|
||||
}
|
||||
gvarsLayout->addWidget(label, i+1, 0);
|
||||
for (int fm=0; fm<fmodes; fm++) {
|
||||
QLabel * value = new QLabel(tabWidget);
|
||||
value->setAutoFillBackground(true);
|
||||
value->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
if ((i % 2) ==0 ) {
|
||||
value->setStyleSheet("QLabel { background-color: rgb(220, 220, 220) }");
|
||||
}
|
||||
gvarValues << value;
|
||||
gvarsLayout->addWidget(value, i+1, fm+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::onButtonPressed(int value)
|
||||
{
|
||||
if (value == Qt::Key_Print) {
|
||||
|
@ -533,6 +548,7 @@ void SimulatorDialog::onTimerEvent()
|
|||
beepVal = 0;
|
||||
QApplication::beep();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateDebugOutput();
|
||||
|
@ -540,11 +556,11 @@ void SimulatorDialog::onTimerEvent()
|
|||
|
||||
void SimulatorDialog::centerSticks()
|
||||
{
|
||||
if (leftStick->scene())
|
||||
nodeLeft->stepToCenter();
|
||||
if (vJoyLeft)
|
||||
vJoyLeft->centerStick();
|
||||
|
||||
if (rightStick->scene())
|
||||
nodeRight->stepToCenter();
|
||||
if (vJoyRight)
|
||||
vJoyRight->centerStick();
|
||||
}
|
||||
|
||||
void SimulatorDialog::start(QByteArray & eeprom)
|
||||
|
@ -569,18 +585,32 @@ void SimulatorDialog::start(const char * filename)
|
|||
|
||||
void SimulatorDialog::setTrims()
|
||||
{
|
||||
typedef VirtualJoystickWidget VJW;
|
||||
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.extended != lastTrims.extended) {
|
||||
int trimMin = -125, trimMax = +125;
|
||||
if (trims.extended) {
|
||||
trimMin = -500;
|
||||
trimMax = +500;
|
||||
}
|
||||
trimHLeft->setRange(trimMin, trimMax); trimHLeft->setValue(trims.values[0]);
|
||||
trimVLeft->setRange(trimMin, trimMax); trimVLeft->setValue(trims.values[1]);
|
||||
trimVRight->setRange(trimMin, trimMax); trimVRight->setValue(trims.values[2]);
|
||||
trimHRight->setRange(trimMin, trimMax); trimHRight->setValue(trims.values[3]);
|
||||
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);
|
||||
}
|
||||
lastTrims = trims;
|
||||
}
|
||||
|
||||
inline int chVal(int val)
|
||||
|
@ -588,26 +618,6 @@ inline int chVal(int val)
|
|||
return qMin(1024, qMax(-1024, val));
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_trimHLeft_valueChanged(int value)
|
||||
{
|
||||
simulator->setTrim(0, value);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_trimVLeft_valueChanged(int value)
|
||||
{
|
||||
simulator->setTrim(1, value);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_trimVRight_valueChanged(int value)
|
||||
{
|
||||
simulator->setTrim(2, value);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_trimHRight_valueChanged(int value)
|
||||
{
|
||||
simulator->setTrim(3, value);
|
||||
}
|
||||
|
||||
void SimulatorDialog::setValues()
|
||||
{
|
||||
TxOutputs outputs;
|
||||
|
@ -622,20 +632,11 @@ void SimulatorDialog::setValues()
|
|||
}
|
||||
}
|
||||
|
||||
leftXPerc->setText(QString("X %1%").arg((qreal)nodeLeft->getX()*100+trims.values[0]/5, 2, 'f', 0));
|
||||
leftYPerc->setText(QString("Y %1%").arg((qreal)nodeLeft->getY()*-100+trims.values[1]/5, 2, 'f', 0));
|
||||
|
||||
rightXPerc->setText(QString("X %1%").arg((qreal)nodeRight->getX()*100+trims.values[3]/5, 2, 'f', 0));
|
||||
rightYPerc->setText(QString("Y %1%").arg((qreal)nodeRight->getY()*-100+trims.values[2]/5, 2, 'f', 0));
|
||||
|
||||
QString CSWITCH_ON = "QLabel { background-color: #4CC417 }";
|
||||
QString CSWITCH_OFF = "QLabel { }";
|
||||
|
||||
for (int i=0; i<GetCurrentFirmware()->getCapability(LogicalSwitches); i++) {
|
||||
logicalSwitchLabels[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF);
|
||||
if (!logicalSwitchLabels2.isEmpty()) {
|
||||
logicalSwitchLabels2[i]->setStyleSheet(outputs.vsw[i] ? CSWITCH_ON : CSWITCH_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int gv=0; gv<numGvars; gv++) {
|
||||
|
@ -649,103 +650,6 @@ void SimulatorDialog::setValues()
|
|||
}
|
||||
}
|
||||
|
||||
void SimulatorDialog::setupSticks()
|
||||
{
|
||||
QGraphicsScene *leftScene = new QGraphicsScene(leftStick);
|
||||
leftScene->setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
leftStick->setScene(leftScene);
|
||||
|
||||
// leftStick->scene()->addLine(0,10,20,30);
|
||||
|
||||
QGraphicsScene *rightScene = new QGraphicsScene(rightStick);
|
||||
rightScene->setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
rightStick->setScene(rightScene);
|
||||
|
||||
// rightStick->scene()->addLine(0,10,20,30);
|
||||
|
||||
nodeLeft = new Node();
|
||||
nodeLeft->setPos(-GBALL_SIZE/2,-GBALL_SIZE/2);
|
||||
nodeLeft->setBallSize(GBALL_SIZE);
|
||||
leftScene->addItem(nodeLeft);
|
||||
|
||||
nodeRight = new Node();
|
||||
nodeRight->setPos(-GBALL_SIZE/2,-GBALL_SIZE/2);
|
||||
nodeRight->setBallSize(GBALL_SIZE);
|
||||
rightScene->addItem(nodeRight);
|
||||
}
|
||||
|
||||
void SimulatorDialog::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
if (leftStick->scene()) {
|
||||
QRect qr = leftStick->contentsRect();
|
||||
qreal w = (qreal)qr.width() - GBALL_SIZE;
|
||||
qreal h = (qreal)qr.height() - GBALL_SIZE;
|
||||
qreal cx = (qreal)qr.width()/2;
|
||||
qreal cy = (qreal)qr.height()/2;
|
||||
leftStick->scene()->setSceneRect(-cx,-cy,w,h);
|
||||
|
||||
QPointF p = nodeLeft->pos();
|
||||
p.setX(qMin(cx, qMax(p.x(), -cx)));
|
||||
p.setY(qMin(cy, qMax(p.y(), -cy)));
|
||||
nodeLeft->setPos(p);
|
||||
}
|
||||
|
||||
if (rightStick->scene()) {
|
||||
QRect qr = rightStick->contentsRect();
|
||||
qreal w = (qreal)qr.width() - GBALL_SIZE;
|
||||
qreal h = (qreal)qr.height() - GBALL_SIZE;
|
||||
qreal cx = (qreal)qr.width()/2;
|
||||
qreal cy = (qreal)qr.height()/2;
|
||||
rightStick->scene()->setSceneRect(-cx,-cy,w,h);
|
||||
|
||||
QPointF p = nodeRight->pos();
|
||||
p.setX(qMin(cx, qMax(p.x(), -cx)));
|
||||
p.setY(qMin(cy, qMax(p.y(), -cy)));
|
||||
nodeRight->setPos(p);
|
||||
}
|
||||
QDialog::resizeEvent(event);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_holdLeftX_clicked(bool checked)
|
||||
{
|
||||
nodeLeft->setCenteringX(!checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_holdLeftY_clicked(bool checked)
|
||||
{
|
||||
nodeLeft->setCenteringY(!checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_holdRightX_clicked(bool checked)
|
||||
{
|
||||
nodeRight->setCenteringX(!checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_holdRightY_clicked(bool checked)
|
||||
{
|
||||
nodeRight->setCenteringY(!checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_FixLeftX_clicked(bool checked)
|
||||
{
|
||||
nodeLeft->setFixedX(checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_FixLeftY_clicked(bool checked)
|
||||
{
|
||||
nodeLeft->setFixedY(checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_FixRightX_clicked(bool checked)
|
||||
{
|
||||
nodeRight->setFixedX(checked);
|
||||
}
|
||||
|
||||
void SimulatorDialog::on_FixRightY_clicked(bool checked)
|
||||
{
|
||||
nodeRight->setFixedY(checked);
|
||||
}
|
||||
|
||||
#ifdef JOYSTICKS
|
||||
void SimulatorDialog::onjoystickAxisValueChanged(int axis, int value)
|
||||
{
|
||||
|
@ -767,16 +671,16 @@ void SimulatorDialog::onjoystickAxisValueChanged(int axis, int value)
|
|||
stickval*=-1;
|
||||
}
|
||||
if (stick==1 ) {
|
||||
nodeRight->setY(-stickval/1024.0);
|
||||
vJoyRight->setStickY(-stickval/1024.0);
|
||||
}
|
||||
else if (stick==2) {
|
||||
nodeRight->setX(stickval/1024.0);
|
||||
vJoyRight->setStickX(stickval/1024.0);
|
||||
}
|
||||
else if (stick==3) {
|
||||
nodeLeft->setY(-stickval/1024.0);
|
||||
vJoyLeft->setStickY(-stickval/1024.0);
|
||||
}
|
||||
else if (stick==4) {
|
||||
nodeLeft->setX(stickval/1024.0);
|
||||
vJoyLeft->setStickX(stickval/1024.0);
|
||||
}
|
||||
else if (stick >= 5 && stick < 5+pots.count()) {
|
||||
pots[stick-5]->setValue(stickval);
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace Ui {
|
|||
// TODO rename + move?
|
||||
class LcdWidget;
|
||||
class SliderWidget;
|
||||
class VirtualJoystickWidget;
|
||||
|
||||
#define SIMULATOR_FLAGS_NOTX 1
|
||||
#define SIMULATOR_FLAGS_STICK_MODE_LEFT 2
|
||||
|
@ -73,6 +74,7 @@ class SimulatorDialog : public QDialog
|
|||
void start(QByteArray & eeprom);
|
||||
virtual void traceCallback(const char * text);
|
||||
|
||||
|
||||
protected:
|
||||
template <class T> void initUi(T * ui);
|
||||
virtual void setLightOn(bool enable) { }
|
||||
|
@ -80,24 +82,19 @@ class SimulatorDialog : public QDialog
|
|||
|
||||
unsigned int flags;
|
||||
LcdWidget * lcd;
|
||||
QGraphicsView * leftStick, * rightStick;
|
||||
QVector<QDial *> pots;
|
||||
QVector<QLabel *> potLabels;
|
||||
QVector<QLabel *> potValues;
|
||||
QVector<QSlider *> sliders;
|
||||
|
||||
SliderWidget * trimHLeft, * trimVLeft, * trimHRight, * trimVRight;
|
||||
QLabel * leftXPerc, * rightXPerc, * leftYPerc, * rightYPerc;
|
||||
QTabWidget * tabWidget;
|
||||
QVector<QLabel *> logicalSwitchLabels;
|
||||
QVector<QLabel *> logicalSwitchLabels2;
|
||||
QVector<QSlider *> channelSliders;
|
||||
QVector<QLabel *> channelValues;
|
||||
QVector<QLabel *> gvarValues;
|
||||
|
||||
void init();
|
||||
Node *nodeLeft;
|
||||
Node *nodeRight;
|
||||
VirtualJoystickWidget *vJoyLeft;
|
||||
VirtualJoystickWidget *vJoyRight;
|
||||
QTimer *timer;
|
||||
QString windowName;
|
||||
unsigned int backLight;
|
||||
|
@ -114,18 +111,18 @@ class SimulatorDialog : public QDialog
|
|||
SimulatorInterface *simulator;
|
||||
unsigned int lastPhase;
|
||||
|
||||
void setupSticks();
|
||||
void setupTimer();
|
||||
void resizeEvent(QResizeEvent *event = 0);
|
||||
QFrame * createLogicalSwitch(QWidget * parent, int switchNo, QVector<QLabel *> & labels);
|
||||
void setupOutputsDisplay();
|
||||
void setupGVarsDisplay();
|
||||
|
||||
virtual void getValues() = 0;
|
||||
void setValues();
|
||||
void centerSticks();
|
||||
void setTrims();
|
||||
|
||||
void setValues();
|
||||
virtual void getValues() = 0;
|
||||
int getValue(qint8 i);
|
||||
bool getSwitch(int swtch, bool nc, qint8 level=0);
|
||||
void setTrims();
|
||||
QFrame * createLogicalSwitch(QWidget * parent, int switchNo, QVector<QLabel *> & labels);
|
||||
|
||||
int beepVal;
|
||||
|
||||
|
@ -141,8 +138,8 @@ class SimulatorDialog : public QDialog
|
|||
QList<QString> traceList;
|
||||
void updateDebugOutput();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *);
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
virtual void mousePressEvent(QMouseEvent *);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *);
|
||||
virtual void wheelEvent(QWheelEvent *);
|
||||
|
@ -155,21 +152,10 @@ class SimulatorDialog : public QDialog
|
|||
|
||||
private slots:
|
||||
void onButtonPressed(int value);
|
||||
void on_FixRightY_clicked(bool checked);
|
||||
void on_FixRightX_clicked(bool checked);
|
||||
void on_FixLeftY_clicked(bool checked);
|
||||
void on_FixLeftX_clicked(bool checked);
|
||||
void on_holdRightY_clicked(bool checked);
|
||||
void on_holdRightX_clicked(bool checked);
|
||||
void on_holdLeftY_clicked(bool checked);
|
||||
void on_holdLeftX_clicked(bool checked);
|
||||
void on_trimHLeft_valueChanged(int);
|
||||
void on_trimVLeft_valueChanged(int);
|
||||
void on_trimHRight_valueChanged(int);
|
||||
void on_trimVRight_valueChanged(int);
|
||||
void onTimerEvent();
|
||||
void onTrimPressed();
|
||||
void onTrimPressed(int which);
|
||||
void onTrimReleased();
|
||||
void onTrimSliderMoved(int which, int value);
|
||||
void openTelemetrySimulator();
|
||||
void openTrainerSimulator();
|
||||
void openDebugOutput();
|
||||
|
|
|
@ -75,36 +75,12 @@ SimulatorDialog9X::SimulatorDialog9X(QWidget * parent, SimulatorInterface *simul
|
|||
if (g.simuSW())
|
||||
restoreSwitches();
|
||||
|
||||
ui->trimHR_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHR_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVR_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVR_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
ui->trimHL_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHL_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVL_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVL_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
for (int i=0; i<pots.count(); i++) {
|
||||
pots[i]->setProperty("index", i);
|
||||
connect(pots[i], SIGNAL(valueChanged(int)), this, SLOT(dialChanged(int)));
|
||||
}
|
||||
connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
}
|
||||
|
||||
SimulatorDialog9X::~SimulatorDialog9X()
|
||||
|
@ -154,10 +130,10 @@ void SimulatorDialog9X::getValues()
|
|||
{
|
||||
TxInputs inputs = {
|
||||
{
|
||||
int(1024*nodeLeft->getX()), // LEFT HORZ
|
||||
int(-1024*nodeLeft->getY()), // LEFT VERT
|
||||
int(-1024*nodeRight->getY()), // RGHT VERT
|
||||
int(1024*nodeRight->getX()) // RGHT HORZ
|
||||
int(1024 * vJoyLeft->getStickX()), // LEFT HORZ
|
||||
int(-1024 * vJoyLeft->getStickY()), // LEFT VERT
|
||||
int(-1024 * vJoyRight->getStickY()), // RGHT VERT
|
||||
int(1024 * vJoyRight->getStickX()) // RGHT HORZ
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
@ -45,33 +45,8 @@ SimulatorDialogFlamenco::SimulatorDialogFlamenco(QWidget * parent, SimulatorInte
|
|||
if (g.simuSW())
|
||||
restoreSwitches();
|
||||
|
||||
ui->trimHR_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHR_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVR_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVR_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
ui->trimHL_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHL_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVL_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVL_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
|
||||
connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
}
|
||||
|
||||
SimulatorDialogFlamenco::~SimulatorDialogFlamenco()
|
||||
|
@ -94,10 +69,10 @@ void SimulatorDialogFlamenco::getValues()
|
|||
{
|
||||
TxInputs inputs = {
|
||||
{
|
||||
int(1024*nodeLeft->getX()), // LEFT HORZ
|
||||
int(-1024*nodeLeft->getY()), // LEFT VERT
|
||||
int(-1024*nodeRight->getY()), // RGHT VERT
|
||||
int(1024*nodeRight->getX()) // RGHT HORZ
|
||||
int(1024 * vJoyLeft->getStickX()), // LEFT HORZ
|
||||
int(-1024 * vJoyLeft->getStickY()), // LEFT VERT
|
||||
int(-1024 * vJoyRight->getStickY()), // RGHT VERT
|
||||
int(1024 * vJoyRight->getStickX()) // RGHT HORZ
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
@ -63,33 +63,8 @@ SimulatorDialogHorus::SimulatorDialogHorus(QWidget * parent, SimulatorInterface
|
|||
if (g.simuSW())
|
||||
restoreSwitches();
|
||||
|
||||
ui->trimHR_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHR_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVR_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVR_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
ui->trimHL_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHL_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVL_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVL_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
|
||||
connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->teleSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator()));
|
||||
connect(ui->trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator()));
|
||||
connect(ui->debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput()));
|
||||
|
@ -116,10 +91,10 @@ void SimulatorDialogHorus::getValues()
|
|||
{
|
||||
TxInputs inputs = {
|
||||
{
|
||||
int(1024*nodeLeft->getX()), // LEFT HORZ
|
||||
int(-1024*nodeLeft->getY()), // LEFT VERT
|
||||
int(-1024*nodeRight->getY()), // RGHT VERT
|
||||
int(1024*nodeRight->getX()) // RGHT HORZ
|
||||
int(1024 * vJoyLeft->getStickX()), // LEFT HORZ
|
||||
int(-1024 * vJoyLeft->getStickY()), // LEFT VERT
|
||||
int(-1024 * vJoyRight->getStickY()), // RGHT VERT
|
||||
int(1024 * vJoyRight->getStickX()) // RGHT HORZ
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
@ -70,33 +70,8 @@ SimulatorDialogTaranis::SimulatorDialogTaranis(QWidget * parent, SimulatorInterf
|
|||
}
|
||||
}
|
||||
|
||||
ui->trimHR_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHR_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVR_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVR_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
ui->trimHL_L->setText(QString::fromUtf8(ARROW_LEFT));
|
||||
ui->trimHL_R->setText(QString::fromUtf8(ARROW_RIGHT));
|
||||
ui->trimVL_U->setText(QString::fromUtf8(ARROW_UP));
|
||||
ui->trimVL_D->setText(QString::fromUtf8(ARROW_DOWN));
|
||||
|
||||
connect(ui->leftbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->rightbuttons, SIGNAL(buttonPressed(int)), this, SLOT(onButtonPressed(int)));
|
||||
connect(ui->trimHR_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVR_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_R, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHL_L, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_U, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimVL_D, SIGNAL(pressed()), this, SLOT(onTrimPressed()));
|
||||
connect(ui->trimHR_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHR_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVR_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_R, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimHL_L, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_U, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->trimVL_D, SIGNAL(released()), this, SLOT(onTrimReleased()));
|
||||
connect(ui->teleSim, SIGNAL(released()), this, SLOT(openTelemetrySimulator()));
|
||||
connect(ui->trainerSim, SIGNAL(released()), this, SLOT(openTrainerSimulator()));
|
||||
connect(ui->debugConsole, SIGNAL(released()), this, SLOT(openDebugOutput()));
|
||||
|
@ -131,10 +106,10 @@ void SimulatorDialogTaranis::getValues()
|
|||
|
||||
TxInputs inputs = {
|
||||
{
|
||||
int(1024*nodeLeft->getX()), // LEFT HORZ
|
||||
int(-1024*nodeLeft->getY()), // LEFT VERT
|
||||
int(-1024*nodeRight->getY()), // RGHT VERT
|
||||
int(1024*nodeRight->getX()) // RGHT HORZ
|
||||
int(1024 * vJoyLeft->getStickX()), // LEFT HORZ
|
||||
int(-1024 * vJoyLeft->getStickY()), // LEFT VERT
|
||||
int(-1024 * vJoyRight->getStickY()), // RGHT VERT
|
||||
int(1024 * vJoyRight->getStickX()) // RGHT HORZ
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@ class SliderWidget : public QSlider
|
|||
|
||||
public:
|
||||
|
||||
explicit SliderWidget(QFrame * parent = 0):
|
||||
explicit SliderWidget(QWidget * parent = 0):
|
||||
QSlider(parent)
|
||||
{
|
||||
}
|
||||
|
|
496
companion/src/simulation/virtualjoystickwidget.cpp
Normal file
496
companion/src/simulation/virtualjoystickwidget.cpp
Normal file
|
@ -0,0 +1,496 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "virtualjoystickwidget.h"
|
||||
#include "../constants.h"
|
||||
#include "sliderwidget.h"
|
||||
#include "modeledit/node.h"
|
||||
#include "helpers.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),
|
||||
btnHoldX(NULL),
|
||||
btnHoldY(NULL),
|
||||
btnFixX(NULL),
|
||||
btnFixY(NULL),
|
||||
nodeLabelX(NULL),
|
||||
nodeLabelY(NULL)
|
||||
{
|
||||
ar = (float)size.width() / size.height();
|
||||
extraSize = QSize(0, 0);
|
||||
|
||||
// 5 col x 4 rows
|
||||
layout = new QGridLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setSizePolicy(sizePolicy);
|
||||
|
||||
gv = new QGraphicsView(this);
|
||||
gv->setSizePolicy(sizePolicy);
|
||||
gv->setMinimumSize(QSize(150, 150));
|
||||
gv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
gv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
scene = new QGraphicsScene(gv);
|
||||
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
gv->setScene(scene);
|
||||
|
||||
node = new Node();
|
||||
node->setPos(-GBALL_SIZE / 2, -GBALL_SIZE / 2);
|
||||
node->setBallSize(GBALL_SIZE);
|
||||
scene->addItem(node);
|
||||
|
||||
int colvt, colbb, colvx, colvy;
|
||||
if (stickSide == 'L') {
|
||||
colvt = 3;
|
||||
colbb = 1;
|
||||
colvx = 1;
|
||||
colvy = 3;
|
||||
}
|
||||
else {
|
||||
colvt = 1;
|
||||
colbb = 3;
|
||||
colvx = 3;
|
||||
colvy = 1;
|
||||
}
|
||||
|
||||
if (showTrims) {
|
||||
QWidget * hTrimWidget = createTrimWidget('H');
|
||||
QWidget * 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());
|
||||
}
|
||||
|
||||
if (showBtns) {
|
||||
QVBoxLayout * btnbox = new QVBoxLayout();
|
||||
btnbox->setContentsMargins(9, 9, 9, 9);
|
||||
btnbox->setSpacing(2);
|
||||
btnbox->addWidget(btnHoldY = createButtonWidget(HOLD_Y));
|
||||
btnbox->addWidget(btnFixY = createButtonWidget(FIX_Y));
|
||||
btnbox->addWidget(btnFixX = createButtonWidget(FIX_X));
|
||||
btnbox->addWidget(btnHoldX = createButtonWidget(HOLD_X));
|
||||
|
||||
layout->addLayout(btnbox, 1, colbb, 1, 1);
|
||||
|
||||
extraSize.setWidth(extraSize.width() + btnbox->sizeHint().width());
|
||||
}
|
||||
|
||||
if (showValues) {
|
||||
QLayout * valX = createNodeValueLayout('X', nodeLabelX);
|
||||
QLayout * valY = createNodeValueLayout('Y', nodeLabelY);
|
||||
layout->addLayout(valX, 2, colvx, 1, 1);
|
||||
layout->addLayout(valY, 2, colvy, 1, 1);
|
||||
}
|
||||
|
||||
layout->addItem(new QSpacerItem(0, 0), 0, 0, 1, 5); // r0 c0-4: top v spacer
|
||||
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
|
||||
|
||||
connect(node, SIGNAL(xChanged()), this, SLOT(updateNodeValueLabels()));
|
||||
connect(node, SIGNAL(yChanged()), this, SLOT(updateNodeValueLabels()));
|
||||
|
||||
setSize(prefSize);
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setStickX(qreal x)
|
||||
{
|
||||
node->setX(x);
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setStickY(qreal y)
|
||||
{
|
||||
node->setY(y);
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setStickPos(QPointF xy)
|
||||
{
|
||||
node->setPos(xy);
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::centerStick()
|
||||
{
|
||||
node->stepToCenter();
|
||||
}
|
||||
|
||||
qreal VirtualJoystickWidget::getStickX()
|
||||
{
|
||||
return node->getX();
|
||||
}
|
||||
|
||||
qreal VirtualJoystickWidget::getStickY()
|
||||
{
|
||||
return node->getY();
|
||||
}
|
||||
|
||||
QPointF VirtualJoystickWidget::getStickPos()
|
||||
{
|
||||
return QPointF(node->getX(), node->getY());
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setTrimValue(int which, int value)
|
||||
{
|
||||
SliderWidget * slider = getTrimSlider(which);
|
||||
if (slider) {
|
||||
slider->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setTrimRange(int which, int min, int max)
|
||||
{
|
||||
SliderWidget * slider = getTrimSlider(which);
|
||||
if (slider) {
|
||||
slider->setRange(min, max);
|
||||
}
|
||||
}
|
||||
|
||||
int VirtualJoystickWidget::getTrimValue(int which)
|
||||
{
|
||||
SliderWidget * slider = getTrimSlider(which);
|
||||
if (slider) {
|
||||
return slider->value();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setStickConstraint(int which, bool active)
|
||||
{
|
||||
if (btnHoldX == NULL)
|
||||
return; // no buttons
|
||||
|
||||
switch (which) {
|
||||
case HOLD_X:
|
||||
btnHoldX->setChecked(active);
|
||||
break;
|
||||
case HOLD_Y:
|
||||
btnHoldY->setChecked(active);
|
||||
break;
|
||||
case FIX_X:
|
||||
btnFixX->setChecked(active);
|
||||
break;
|
||||
case FIX_Y:
|
||||
btnFixY->setChecked(active);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::setSize(QSize size)
|
||||
{
|
||||
float thisAspectRatio = (float)size.width() / size.height();
|
||||
float newGvSz, spacerSz;
|
||||
bool sized = false;
|
||||
|
||||
if (thisAspectRatio > ar) {
|
||||
// constrain width
|
||||
newGvSz = (height() - extraSize.height()) * ar; // new width
|
||||
spacerSz = (width() - newGvSz - extraSize.width()) / 2; // + 0.5;
|
||||
if (spacerSz >= 0.0f) {
|
||||
layout->setRowStretch(0, 0);
|
||||
layout->setColumnStretch(0, spacerSz);
|
||||
layout->setColumnStretch(4, spacerSz);
|
||||
layout->setRowStretch(3, 0);
|
||||
sized = true;
|
||||
}
|
||||
}
|
||||
if (!sized) {
|
||||
// constrain height
|
||||
newGvSz = (width() - extraSize.width()) * ar; // new height
|
||||
spacerSz = (height() - newGvSz - extraSize.height()) / 2; // + 0.5;
|
||||
spacerSz = qMax(spacerSz, 0.0f);
|
||||
layout->setRowStretch(0, spacerSz);
|
||||
layout->setColumnStretch(0, 0);
|
||||
layout->setColumnStretch(4, 0);
|
||||
layout->setRowStretch(3, spacerSz);
|
||||
}
|
||||
|
||||
layout->setColumnStretch(2, newGvSz);
|
||||
layout->setRowStretch(1, newGvSz);
|
||||
|
||||
prefSize = QSize(newGvSz + extraSize.width(), newGvSz + extraSize.height());
|
||||
gv->resize(newGvSz, newGvSz);
|
||||
gv->updateGeometry();
|
||||
repositionNode();
|
||||
//qDebug() << thisAspectRatio << size << newGvSz << spacerSz << extraSize << gv->geometry() << gv->contentsRect() << gv->frameRect() << getStickPos();
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::repositionNode()
|
||||
{
|
||||
QRect qr = gv->contentsRect();
|
||||
qreal w = (qreal)qr.width() - GBALL_SIZE;
|
||||
qreal h = (qreal)qr.height() - GBALL_SIZE;
|
||||
qreal cx = (qreal)qr.width()/2;
|
||||
qreal cy = (qreal)qr.height()/2;
|
||||
scene->setSceneRect(-cx,-cy,w,h);
|
||||
|
||||
QPointF p = node->pos();
|
||||
p.setX(qMin(cx, qMax(p.x(), -cx)));
|
||||
p.setY(qMin(cy, qMax(p.y(), -cy)));
|
||||
node->setPos(p);
|
||||
|
||||
updateNodeValueLabels();
|
||||
}
|
||||
|
||||
QWidget *VirtualJoystickWidget::createTrimWidget(QChar type)
|
||||
{
|
||||
QSizePolicy sp;
|
||||
QString btnAlabel, btnBlabel;
|
||||
|
||||
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)));
|
||||
|
||||
return trimWidget;
|
||||
}
|
||||
|
||||
QPushButton * VirtualJoystickWidget::createButtonWidget(int type)
|
||||
{
|
||||
QString btnRole, btnLabel;
|
||||
switch (type) {
|
||||
case HOLD_Y:
|
||||
btnLabel = tr("Hold Y");
|
||||
break;
|
||||
case FIX_Y:
|
||||
btnLabel = tr("Fix Y");
|
||||
break;
|
||||
case FIX_X:
|
||||
btnLabel = tr("Fix X");
|
||||
break;
|
||||
case HOLD_X:
|
||||
default:
|
||||
btnLabel = tr("Hold X");
|
||||
break;
|
||||
}
|
||||
QPushButton * btn = new QPushButton(this);
|
||||
btn->setObjectName(QString("%1_%2").arg(btnLabel.replace(" ", "_")).arg(stickSide));
|
||||
btn->setProperty("btnType", type);
|
||||
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->setCheckable(true);
|
||||
|
||||
connect(btn, SIGNAL(toggled(bool)), SLOT(onButtonChange(bool)));
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
QLayout *VirtualJoystickWidget::createNodeValueLayout(QChar type, QLabel *& valLabel)
|
||||
{
|
||||
QLabel * lbl = new QLabel(QString("%1 %").arg(type), this);
|
||||
lbl->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
lbl->setAlignment(Qt::AlignCenter);
|
||||
QLabel * val = new QLabel("0");
|
||||
val->setObjectName(QString("val_%1").arg(type));
|
||||
val->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
val->setAlignment(Qt::AlignCenter);
|
||||
QVBoxLayout * layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(2, 2, 2, 2);
|
||||
layout->setSpacing(2);
|
||||
layout->addWidget(lbl);
|
||||
layout->addWidget(val);
|
||||
|
||||
valLabel = val;
|
||||
return layout;
|
||||
}
|
||||
|
||||
int VirtualJoystickWidget::getTrimSliderType(QChar type)
|
||||
{
|
||||
if (stickSide == 'L') {
|
||||
if (type == 'H')
|
||||
return TRIM_AXIS_L_X;
|
||||
else
|
||||
return TRIM_AXIS_L_Y;
|
||||
}
|
||||
else {
|
||||
if (type == 'H')
|
||||
return TRIM_AXIS_R_X;
|
||||
else
|
||||
return TRIM_AXIS_R_Y;
|
||||
}
|
||||
}
|
||||
|
||||
int VirtualJoystickWidget::getTrimButtonType(QChar type, int pos)
|
||||
{
|
||||
if (stickSide == 'L') {
|
||||
if (type == 'H') {
|
||||
if (pos == 0)
|
||||
return TRIM_LH_L;
|
||||
else
|
||||
return TRIM_LH_R;
|
||||
}
|
||||
else {
|
||||
if (pos == 0)
|
||||
return TRIM_LV_UP;
|
||||
else
|
||||
return TRIM_LV_DN;
|
||||
}
|
||||
}
|
||||
// right side
|
||||
else {
|
||||
if (type == 'H') {
|
||||
if (pos == 0)
|
||||
return TRIM_RH_L;
|
||||
else
|
||||
return TRIM_RH_R;
|
||||
}
|
||||
else {
|
||||
if (pos == 0)
|
||||
return TRIM_RV_UP;
|
||||
else
|
||||
return TRIM_RV_DN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SliderWidget *VirtualJoystickWidget::getTrimSlider(int which)
|
||||
{
|
||||
if (which == TRIM_AXIS_L_X || which == TRIM_AXIS_R_X)
|
||||
return hTrimSlider;
|
||||
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();
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::onButtonChange(bool checked)
|
||||
{
|
||||
if (!sender() || !sender()->property("btnType").isValid())
|
||||
return;
|
||||
|
||||
switch (sender()->property("btnType").toInt()) {
|
||||
case HOLD_Y:
|
||||
node->setCenteringY(!checked);
|
||||
break;
|
||||
case FIX_Y:
|
||||
node->setFixedY(checked);
|
||||
break;
|
||||
case FIX_X:
|
||||
node->setFixedX(checked);
|
||||
break;
|
||||
case HOLD_X:
|
||||
node->setCenteringX(!checked);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualJoystickWidget::updateNodeValueLabels()
|
||||
{
|
||||
if (nodeLabelX)
|
||||
nodeLabelX->setText(QString("%1").arg((qreal)node->getX() * 100 + getTrimValue(0) / 5, 2, 'f', 0));
|
||||
if (nodeLabelY)
|
||||
nodeLabelY->setText(QString("%1").arg((qreal)node->getY() * -100 + getTrimValue(1) / 5, 2, 'f', 0));
|
||||
}
|
121
companion/src/simulation/virtualjoystickwidget.h
Normal file
121
companion/src/simulation/virtualjoystickwidget.h
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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 VIRTUALJOYSTICKWIDGET_H
|
||||
#define VIRTUALJOYSTICKWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QResizeEvent>
|
||||
#include <QBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
|
||||
class Node;
|
||||
class SliderWidget;
|
||||
|
||||
#define GBALL_SIZE 20
|
||||
#define RESX 1024
|
||||
|
||||
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,
|
||||
FIX_X,
|
||||
FIX_Y
|
||||
};
|
||||
|
||||
explicit VirtualJoystickWidget(QWidget * parent = NULL, QChar side = 'L', bool showTrims = true, bool showBtns = true, bool showValues = true, QSize size = QSize(245, 245));
|
||||
|
||||
void setStickX(qreal x);
|
||||
void setStickY(qreal y);
|
||||
void setStickPos(QPointF xy);
|
||||
void centerStick();
|
||||
qreal getStickX();
|
||||
qreal getStickY();
|
||||
QPointF getStickPos();
|
||||
|
||||
void setTrimValue(int which, int value);
|
||||
void setTrimRange(int which, int min, int max);
|
||||
int getTrimValue(int which);
|
||||
|
||||
void setStickConstraint(int which, bool active);
|
||||
|
||||
virtual QSize sizeHint() const
|
||||
{
|
||||
return prefSize;
|
||||
}
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
setSize(event->size());
|
||||
}
|
||||
|
||||
signals:
|
||||
void trimButtonPressed(int which);
|
||||
void trimButtonReleased();
|
||||
void trimSliderMoved(int which, int value);
|
||||
|
||||
protected slots:
|
||||
void onTrimPressed();
|
||||
void onSliderChange(int value);
|
||||
void onButtonChange(bool checked);
|
||||
void updateNodeValueLabels();
|
||||
|
||||
protected:
|
||||
void setSize(QSize size);
|
||||
void repositionNode();
|
||||
QWidget * createTrimWidget(QChar type);
|
||||
QPushButton * createButtonWidget(int type);
|
||||
QLayout * createNodeValueLayout(QChar type, QLabel *& valLabel);
|
||||
int getTrimSliderType(QChar type);
|
||||
int getTrimButtonType(QChar type, int pos);
|
||||
SliderWidget * getTrimSlider(int which);
|
||||
|
||||
QChar stickSide;
|
||||
QSize prefSize;
|
||||
QGridLayout * layout;
|
||||
QGraphicsView * gv;
|
||||
QGraphicsScene * scene;
|
||||
Node * node;
|
||||
SliderWidget * hTrimSlider, * vTrimSlider;
|
||||
QPushButton * btnHoldX, * btnHoldY;
|
||||
QPushButton * btnFixX, * btnFixY;
|
||||
QLabel * nodeLabelX, * nodeLabelY;
|
||||
QSize extraSize;
|
||||
float ar; // aspect ratio
|
||||
|
||||
};
|
||||
|
||||
#endif // VIRTUALJOYSTICKWIDGET_H
|
Loading…
Add table
Add a link
Reference in a new issue