Commit e169b59f authored by Bryant's avatar Bryant

The Joystick Settings window now supports selecting between multiple joysticks...

The Joystick Settings window now supports selecting between multiple joysticks for control input and updates its UI accordingly. Much work is left to be done: light/dark styling, settings management, control mappings.
parent bcb61f43
...@@ -38,7 +38,9 @@ JoystickInput::JoystickInput() : ...@@ -38,7 +38,9 @@ JoystickInput::JoystickInput() :
autoButtonMapping(-1), autoButtonMapping(-1),
manualButtonMapping(-1), manualButtonMapping(-1),
stabilizeButtonMapping(-1), stabilizeButtonMapping(-1),
joystickName(tr("Unitinialized")) joystickName(tr("Unitinialized")),
joystickButtons(0),
joystickID(0)
{ {
loadSettings(); loadSettings();
...@@ -47,10 +49,11 @@ JoystickInput::JoystickInput() : ...@@ -47,10 +49,11 @@ JoystickInput::JoystickInput() :
calibrationNegative[i] = sdlJoystickMin; calibrationNegative[i] = sdlJoystickMin;
} }
// Listen for when the active UAS changes so we can change who we're sending data to.
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
// Enter main loop // Start this thread. This allows the Joystick Settings window to work correctly even w/o any UASes connected.
//start(); start();
} }
JoystickInput::~JoystickInput() JoystickInput::~JoystickInput()
...@@ -108,14 +111,13 @@ void JoystickInput::setActiveUAS(UASInterface* uas) ...@@ -108,14 +111,13 @@ void JoystickInput::setActiveUAS(UASInterface* uas)
this->uas = uas; this->uas = uas;
tmp = dynamic_cast<UAS*>(this->uas); if (this->uas)
if(tmp) {
connect(this, SIGNAL(joystickChanged(double,double,double,double,int,int,int)), tmp, SLOT(setManualControlCommands(double,double,double,double,int,int,int)));
connect(this, SIGNAL(buttonPressed(int)), tmp, SLOT(receiveButton(int)));
}
if (!isRunning())
{ {
start(); tmp = dynamic_cast<UAS*>(this->uas);
if(tmp) {
connect(this, SIGNAL(joystickChanged(double,double,double,double,int,int,int)), tmp, SLOT(setManualControlCommands(double,double,double,double,int,int,int)));
connect(this, SIGNAL(buttonPressed(int)), tmp, SLOT(receiveButton(int)));
}
} }
} }
...@@ -127,10 +129,10 @@ void JoystickInput::init() ...@@ -127,10 +129,10 @@ void JoystickInput::init()
} }
// Enumerate joysticks and select one // Enumerate joysticks and select one
int numJoysticks = SDL_NumJoysticks(); joysticksFound = SDL_NumJoysticks();
// Wait for joysticks if none is connected // Wait for joysticks if none are connected
while (numJoysticks == 0 && !done) while (joysticksFound == 0 && !done)
{ {
QGC::SLEEP::msleep(400); QGC::SLEEP::msleep(400);
// INITIALIZE SDL Joystick support // INITIALIZE SDL Joystick support
...@@ -138,29 +140,33 @@ void JoystickInput::init() ...@@ -138,29 +140,33 @@ void JoystickInput::init()
{ {
printf("Couldn't initialize SimpleDirectMediaLayer: %s\n", SDL_GetError()); printf("Couldn't initialize SimpleDirectMediaLayer: %s\n", SDL_GetError());
} }
numJoysticks = SDL_NumJoysticks(); joysticksFound = SDL_NumJoysticks();
} }
if (done) if (done)
{ {
return; return;
} }
printf("%d Input devices found:\n", numJoysticks); qDebug() << QString("%1 Input devices found:").arg(joysticksFound);
for(int i=0; i < SDL_NumJoysticks(); i++ ) for(int i=0; i < joysticksFound; i++ )
{ {
printf("\t- %s\n", SDL_JoystickName(i)); qDebug() << QString("\t- %1").arg(SDL_JoystickName(i));
joystickName = QString(SDL_JoystickName(i)); SDL_Joystick* x = SDL_JoystickOpen(i);
qDebug() << QString("Number of Axes: %1").arg(QString::number(SDL_JoystickNumAxes(x)));
qDebug() << QString("Number of Buttons: %1").arg(QString::number(SDL_JoystickNumButtons(x)));
qDebug() << QString("Number of Balls: %1").arg(QString::number(SDL_JoystickNumBalls(x)));
SDL_JoystickClose(x);
} }
printf("\nOpened %s\n", SDL_JoystickName(defaultIndex));
SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickEventState(SDL_ENABLE);
joystick = SDL_JoystickOpen(defaultIndex); // And attach to the default joystick.
setActiveJoystick(defaultIndex);
// Make sure active UAS is set // Make sure active UAS is set
setActiveUAS(UASManager::instance()->getActiveUAS()); setActiveUAS(UASManager::instance()->getActiveUAS());
} }
void JoystickInput::shutdown() void JoystickInput::shutdown()
{ {
done = true; done = true;
...@@ -324,6 +330,18 @@ void JoystickInput::run() ...@@ -324,6 +330,18 @@ void JoystickInput::run()
} }
void JoystickInput::setActiveJoystick(int id)
{
joystickID = id;
joystick = SDL_JoystickOpen(joystickID);
if (joystick)
{
joystickName = QString(SDL_JoystickName(joystickID));
joystickButtons = SDL_JoystickNumButtons(joystick);
qDebug() << QString("Switching to joystick '%1' with %2 buttons").arg(joystickName, QString::number(joystickButtons));
}
}
const QString& JoystickInput::getName() const QString& JoystickInput::getName()
{ {
return joystickName; return joystickName;
......
...@@ -69,41 +69,61 @@ public: ...@@ -69,41 +69,61 @@ public:
*/ */
void storeSettings(); void storeSettings();
int getMappingThrustAxis() int getMappingThrustAxis() const
{ {
return thrustAxis; return thrustAxis;
} }
int getMappingXAxis() int getMappingXAxis() const
{ {
return xAxis; return xAxis;
} }
int getMappingYAxis() int getMappingYAxis() const
{ {
return yAxis; return yAxis;
} }
int getMappingYawAxis() int getMappingYawAxis() const
{ {
return yawAxis; return yawAxis;
} }
int getMappingAutoButton() int getMappingAutoButton() const
{ {
return autoButtonMapping; return autoButtonMapping;
} }
int getMappingManualButton() int getMappingManualButton() const
{ {
return manualButtonMapping; return manualButtonMapping;
} }
int getMappingStabilizeButton() int getMappingStabilizeButton() const
{ {
return stabilizeButtonMapping; return stabilizeButtonMapping;
} }
int getJoystickNumButtons() const
{
return joystickButtons;
}
int getJoystickID() const
{
return joystickID;
}
int getNumJoysticks() const
{
return joysticksFound;
}
QString getJoystickNameById(int id) const
{
return QString(SDL_JoystickName(id));
}
const double sdlJoystickMin; const double sdlJoystickMin;
const double sdlJoystickMax; const double sdlJoystickMax;
...@@ -127,6 +147,9 @@ protected: ...@@ -127,6 +147,9 @@ protected:
int stabilizeButtonMapping; int stabilizeButtonMapping;
SDL_Event event; SDL_Event event;
QString joystickName; QString joystickName;
int joystickButtons;
int joystickID;
int joysticksFound;
void init(); void init();
...@@ -198,6 +221,8 @@ signals: ...@@ -198,6 +221,8 @@ signals:
public slots: public slots:
void setActiveUAS(UASInterface* uas); void setActiveUAS(UASInterface* uas);
/** @brief Switch to a new joystick by ID number. */
void setActiveJoystick(int id);
void setMappingThrustAxis(int mapping) void setMappingThrustAxis(int mapping)
{ {
thrustAxis = mapping; thrustAxis = mapping;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
JoystickWidget::JoystickWidget(JoystickInput* joystick, QWidget *parent) : JoystickWidget::JoystickWidget(JoystickInput* joystick, QWidget *parent) :
QDialog(parent), QDialog(parent),
joystick(joystick),
m_ui(new Ui::JoystickWidget) m_ui(new Ui::JoystickWidget)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
...@@ -14,30 +15,50 @@ JoystickWidget::JoystickWidget(JoystickInput* joystick, QWidget *parent) : ...@@ -14,30 +15,50 @@ JoystickWidget::JoystickWidget(JoystickInput* joystick, QWidget *parent) :
position.moveCenter(QDesktopWidget().availableGeometry().center()); position.moveCenter(QDesktopWidget().availableGeometry().center());
move(position.topLeft()); move(position.topLeft());
clearKeys(); // Initialize the UI based on the current joystick
this->joystick = joystick; initUI();
m_ui->rollMapSpinBox->setValue(joystick->getMappingXAxis());
m_ui->pitchMapSpinBox->setValue(joystick->getMappingYAxis());
m_ui->yawMapSpinBox->setValue(joystick->getMappingYawAxis());
m_ui->throttleMapSpinBox->setValue(joystick->getMappingThrustAxis());
m_ui->autoMapSpinBox->setValue(joystick->getMappingAutoButton());
// Watch for input events from the joystick
connect(this->joystick, SIGNAL(joystickChanged(double,double,double,double,int,int,int)), this, SLOT(updateJoystick(double,double,double,double,int,int))); connect(this->joystick, SIGNAL(joystickChanged(double,double,double,double,int,int,int)), this, SLOT(updateJoystick(double,double,double,double,int,int)));
connect(this->joystick, SIGNAL(buttonPressed(int)), this, SLOT(pressKey(int))); connect(this->joystick, SIGNAL(buttonPressed(int)), this, SLOT(pressKey(int)));
// Watch for changes to the button/axis mappings
connect(m_ui->rollMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingXAxis(int))); connect(m_ui->rollMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingXAxis(int)));
connect(m_ui->pitchMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingYAxis(int))); connect(m_ui->pitchMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingYAxis(int)));
connect(m_ui->yawMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingYawAxis(int))); connect(m_ui->yawMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingYawAxis(int)));
connect(m_ui->throttleMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingThrustAxis(int))); connect(m_ui->throttleMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingThrustAxis(int)));
connect(m_ui->autoMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingAutoButton(int))); connect(m_ui->autoMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingAutoButton(int)));
// Display the widget // Update the UI if the joystick changes.
this->window()->setWindowTitle(tr("Joystick Settings")); connect(m_ui->joystickNameComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUIForJoystick(int)));
if (joystick) updateStatus(tr("Found joystick: %1").arg(joystick->getName()));
// Display the widget above all other windows.
this->raise();
this->show(); this->show();
} }
void JoystickWidget::initUI()
{
// Add the joysticks to the top combobox. They're indexed by their item number.
// And set the currently-selected combobox item to the current joystick.
int joysticks = joystick->getNumJoysticks();
if (joysticks)
{
for (int i = 0; i < joysticks; i++)
{
m_ui->joystickNameComboBox->addItem(joystick->getJoystickNameById(i));
}
m_ui->joystickNameComboBox->setCurrentIndex(joystick->getJoystickID());
}
else
{
m_ui->joystickNameComboBox->addItem(tr("No joysticks found. Connect and restart QGC to add one."));
}
// Add any missing buttons
updateUIForJoystick(joystick->getJoystickID());
}
JoystickWidget::~JoystickWidget() JoystickWidget::~JoystickWidget()
{ {
delete m_ui; delete m_ui;
...@@ -63,6 +84,35 @@ void JoystickWidget::changeEvent(QEvent *e) ...@@ -63,6 +84,35 @@ void JoystickWidget::changeEvent(QEvent *e)
} }
} }
void JoystickWidget::updateUIForJoystick(int id)
{
// Delete all the old buttonlabels
foreach (QLabel* l, m_ui->buttonLabelBox->findChildren<QLabel*>())
{
delete l;
}
// Set the JoystickInput to listen to the new joystick instead.
joystick->setActiveJoystick(id);
// And add new ones for every new button found.
for (int i = 0; i < joystick->getJoystickNumButtons(); i++)
{
QLabel* buttonLabel = new QLabel(m_ui->buttonLabelBox);
buttonLabel->setText(QString::number(i));
buttonLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
buttonLabel->setAlignment(Qt::AlignCenter);
// And make sure we insert BEFORE the vertical spacer.
m_ui->buttonLabelLayout->insertWidget(i, buttonLabel);
}
// Update the mapping UI
m_ui->rollMapSpinBox->setValue(joystick->getMappingXAxis());
m_ui->pitchMapSpinBox->setValue(joystick->getMappingYAxis());
m_ui->yawMapSpinBox->setValue(joystick->getMappingYawAxis());
m_ui->throttleMapSpinBox->setValue(joystick->getMappingThrustAxis());
m_ui->autoMapSpinBox->setValue(joystick->getMappingAutoButton());
}
void JoystickWidget::setThrottle(float thrust) void JoystickWidget::setThrottle(float thrust)
{ {
...@@ -91,66 +141,46 @@ void JoystickWidget::setHat(float x, float y) ...@@ -91,66 +141,46 @@ void JoystickWidget::setHat(float x, float y)
updateStatus(tr("Hat position: x: %1, y: %2").arg(x).arg(y)); updateStatus(tr("Hat position: x: %1, y: %2").arg(x).arg(y));
} }
void JoystickWidget::clearKeys()
{
QString colorstyle;
QColor buttonStyleColor = QColor(200, 20, 20);
colorstyle = QString("QLabel { border: 1px solid #EEEEEE; border-radius: 4px; padding: 0px; margin: 0px; background-color: %1;}").arg(buttonStyleColor.name());
m_ui->button0->setStyleSheet(colorstyle);
m_ui->button1->setStyleSheet(colorstyle);
m_ui->button2->setStyleSheet(colorstyle);
m_ui->button3->setStyleSheet(colorstyle);
m_ui->button4->setStyleSheet(colorstyle);
m_ui->button5->setStyleSheet(colorstyle);
m_ui->button6->setStyleSheet(colorstyle);
m_ui->button7->setStyleSheet(colorstyle);
m_ui->button8->setStyleSheet(colorstyle);
m_ui->button9->setStyleSheet(colorstyle);
m_ui->button10->setStyleSheet(colorstyle);
}
void JoystickWidget::pressKey(int key) void JoystickWidget::pressKey(int key)
{ {
QString colorstyle; // QString colorstyle;
QColor buttonStyleColor = QColor(20, 200, 20); // QColor buttonStyleColor = QColor(20, 200, 20);
colorstyle = QString("QLabel { border: 1px solid #EEEEEE; border-radius: 4px; padding: 0px; margin: 0px; background-color: %1;}").arg(buttonStyleColor.name()); // colorstyle = QString("QLabel { border: 1px solid #EEEEEE; border-radius: 4px; padding: 0px; margin: 0px; background-color: %1;}").arg(buttonStyleColor.name());
switch(key) { // switch(key) {
case 0: // case 0:
m_ui->button0->setStyleSheet(colorstyle); // m_ui->button0->setStyleSheet(colorstyle);
break; // break;
case 1: // case 1:
m_ui->button1->setStyleSheet(colorstyle); // m_ui->button1->setStyleSheet(colorstyle);
break; // break;
case 2: // case 2:
m_ui->button2->setStyleSheet(colorstyle); // m_ui->button2->setStyleSheet(colorstyle);
break; // break;
case 3: // case 3:
m_ui->button3->setStyleSheet(colorstyle); // m_ui->button3->setStyleSheet(colorstyle);
break; // break;
case 4: // case 4:
m_ui->button4->setStyleSheet(colorstyle); // m_ui->button4->setStyleSheet(colorstyle);
break; // break;
case 5: // case 5:
m_ui->button5->setStyleSheet(colorstyle); // m_ui->button5->setStyleSheet(colorstyle);
break; // break;
case 6: // case 6:
m_ui->button6->setStyleSheet(colorstyle); // m_ui->button6->setStyleSheet(colorstyle);
break; // break;
case 7: // case 7:
m_ui->button7->setStyleSheet(colorstyle); // m_ui->button7->setStyleSheet(colorstyle);
break; // break;
case 8: // case 8:
m_ui->button8->setStyleSheet(colorstyle); // m_ui->button8->setStyleSheet(colorstyle);
break; // break;
case 9: // case 9:
m_ui->button9->setStyleSheet(colorstyle); // m_ui->button9->setStyleSheet(colorstyle);
break; // break;
case 10: // case 10:
m_ui->button10->setStyleSheet(colorstyle); // m_ui->button10->setStyleSheet(colorstyle);
break; // break;
} // }
QTimer::singleShot(20, this, SLOT(clearKeys()));
updateStatus(tr("Key %1 pressed").arg(key)); updateStatus(tr("Key %1 pressed").arg(key));
} }
......
...@@ -69,20 +69,26 @@ public slots: ...@@ -69,20 +69,26 @@ public slots:
void setZ(float z); void setZ(float z);
/** @brief Hat switch position */ /** @brief Hat switch position */
void setHat(float x, float y); void setHat(float x, float y);
/** @brief Clear keys */
void clearKeys();
/** @brief Joystick keys, as labeled on the joystick */ /** @brief Joystick keys, as labeled on the joystick */
void pressKey(int key); void pressKey(int key);
/** @brief Update status string */ /** @brief Update status string */
void updateStatus(const QString& status); void updateStatus(const QString& status);
protected: protected:
/** @brief Update the proper number of buttons for the current joystick. */
void updateButtons();
/** @brief UI change event */ /** @brief UI change event */
virtual void changeEvent(QEvent *e); virtual void changeEvent(QEvent *e);
JoystickInput* joystick; ///< Reference to the joystick JoystickInput* joystick; ///< Reference to the joystick
protected slots:
/** @brief Update the UI for a new joystick based on SDL ID. */
void updateUIForJoystick(int id);
private: private:
Ui::JoystickWidget *m_ui; Ui::JoystickWidget *m_ui;
/** @brief Initialize all dynamic UI elements (button list, joystick names, etc.) */
void initUI();
}; };
#endif // JOYSTICKWIDGET_H #endif // JOYSTICKWIDGET_H
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment