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() :
autoButtonMapping(-1),
manualButtonMapping(-1),
stabilizeButtonMapping(-1),
joystickName(tr("Unitinialized"))
joystickName(tr("Unitinialized")),
joystickButtons(0),
joystickID(0)
{
loadSettings();
......@@ -47,10 +49,11 @@ JoystickInput::JoystickInput() :
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*)));
// Enter main loop
//start();
// Start this thread. This allows the Joystick Settings window to work correctly even w/o any UASes connected.
start();
}
JoystickInput::~JoystickInput()
......@@ -108,14 +111,13 @@ void JoystickInput::setActiveUAS(UASInterface* uas)
this->uas = uas;
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)));
}
if (!isRunning())
if (this->uas)
{
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()
}
// Enumerate joysticks and select one
int numJoysticks = SDL_NumJoysticks();
joysticksFound = SDL_NumJoysticks();
// Wait for joysticks if none is connected
while (numJoysticks == 0 && !done)
// Wait for joysticks if none are connected
while (joysticksFound == 0 && !done)
{
QGC::SLEEP::msleep(400);
// INITIALIZE SDL Joystick support
......@@ -138,29 +140,33 @@ void JoystickInput::init()
{
printf("Couldn't initialize SimpleDirectMediaLayer: %s\n", SDL_GetError());
}
numJoysticks = SDL_NumJoysticks();
joysticksFound = SDL_NumJoysticks();
}
if (done)
{
return;
}
printf("%d Input devices found:\n", numJoysticks);
for(int i=0; i < SDL_NumJoysticks(); i++ )
qDebug() << QString("%1 Input devices found:").arg(joysticksFound);
for(int i=0; i < joysticksFound; i++ )
{
printf("\t- %s\n", SDL_JoystickName(i));
joystickName = QString(SDL_JoystickName(i));
qDebug() << QString("\t- %1").arg(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);
joystick = SDL_JoystickOpen(defaultIndex);
// And attach to the default joystick.
setActiveJoystick(defaultIndex);
// Make sure active UAS is set
setActiveUAS(UASManager::instance()->getActiveUAS());
}
void JoystickInput::shutdown()
{
done = true;
......@@ -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()
{
return joystickName;
......
......@@ -69,41 +69,61 @@ public:
*/
void storeSettings();
int getMappingThrustAxis()
int getMappingThrustAxis() const
{
return thrustAxis;
}
int getMappingXAxis()
int getMappingXAxis() const
{
return xAxis;
}
int getMappingYAxis()
int getMappingYAxis() const
{
return yAxis;
}
int getMappingYawAxis()
int getMappingYawAxis() const
{
return yawAxis;
}
int getMappingAutoButton()
int getMappingAutoButton() const
{
return autoButtonMapping;
}
int getMappingManualButton()
int getMappingManualButton() const
{
return manualButtonMapping;
}
int getMappingStabilizeButton()
int getMappingStabilizeButton() const
{
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 sdlJoystickMax;
......@@ -127,6 +147,9 @@ protected:
int stabilizeButtonMapping;
SDL_Event event;
QString joystickName;
int joystickButtons;
int joystickID;
int joysticksFound;
void init();
......@@ -198,6 +221,8 @@ signals:
public slots:
void setActiveUAS(UASInterface* uas);
/** @brief Switch to a new joystick by ID number. */
void setActiveJoystick(int id);
void setMappingThrustAxis(int mapping)
{
thrustAxis = mapping;
......
......@@ -5,6 +5,7 @@
JoystickWidget::JoystickWidget(JoystickInput* joystick, QWidget *parent) :
QDialog(parent),
joystick(joystick),
m_ui(new Ui::JoystickWidget)
{
m_ui->setupUi(this);
......@@ -14,30 +15,50 @@ JoystickWidget::JoystickWidget(JoystickInput* joystick, QWidget *parent) :
position.moveCenter(QDesktopWidget().availableGeometry().center());
move(position.topLeft());
clearKeys();
this->joystick = joystick;
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());
// Initialize the UI based on the current joystick
initUI();
// 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(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->pitchMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingYAxis(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->autoMapSpinBox, SIGNAL(valueChanged(int)), this->joystick, SLOT(setMappingAutoButton(int)));
// Display the widget
this->window()->setWindowTitle(tr("Joystick Settings"));
if (joystick) updateStatus(tr("Found joystick: %1").arg(joystick->getName()));
// Update the UI if the joystick changes.
connect(m_ui->joystickNameComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUIForJoystick(int)));
// Display the widget above all other windows.
this->raise();
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()
{
delete m_ui;
......@@ -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)
{
......@@ -91,66 +141,46 @@ void JoystickWidget::setHat(float x, float 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)
{
QString colorstyle;
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());
switch(key) {
case 0:
m_ui->button0->setStyleSheet(colorstyle);
break;
case 1:
m_ui->button1->setStyleSheet(colorstyle);
break;
case 2:
m_ui->button2->setStyleSheet(colorstyle);
break;
case 3:
m_ui->button3->setStyleSheet(colorstyle);
break;
case 4:
m_ui->button4->setStyleSheet(colorstyle);
break;
case 5:
m_ui->button5->setStyleSheet(colorstyle);
break;
case 6:
m_ui->button6->setStyleSheet(colorstyle);
break;
case 7:
m_ui->button7->setStyleSheet(colorstyle);
break;
case 8:
m_ui->button8->setStyleSheet(colorstyle);
break;
case 9:
m_ui->button9->setStyleSheet(colorstyle);
break;
case 10:
m_ui->button10->setStyleSheet(colorstyle);
break;
}
QTimer::singleShot(20, this, SLOT(clearKeys()));
// QString colorstyle;
// 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());
// switch(key) {
// case 0:
// m_ui->button0->setStyleSheet(colorstyle);
// break;
// case 1:
// m_ui->button1->setStyleSheet(colorstyle);
// break;
// case 2:
// m_ui->button2->setStyleSheet(colorstyle);
// break;
// case 3:
// m_ui->button3->setStyleSheet(colorstyle);
// break;
// case 4:
// m_ui->button4->setStyleSheet(colorstyle);
// break;
// case 5:
// m_ui->button5->setStyleSheet(colorstyle);
// break;
// case 6:
// m_ui->button6->setStyleSheet(colorstyle);
// break;
// case 7:
// m_ui->button7->setStyleSheet(colorstyle);
// break;
// case 8:
// m_ui->button8->setStyleSheet(colorstyle);
// break;
// case 9:
// m_ui->button9->setStyleSheet(colorstyle);
// break;
// case 10:
// m_ui->button10->setStyleSheet(colorstyle);
// break;
// }
updateStatus(tr("Key %1 pressed").arg(key));
}
......
......@@ -69,20 +69,26 @@ public slots:
void setZ(float z);
/** @brief Hat switch position */
void setHat(float x, float y);
/** @brief Clear keys */
void clearKeys();
/** @brief Joystick keys, as labeled on the joystick */
void pressKey(int key);
/** @brief Update status string */
void updateStatus(const QString& status);
protected:
/** @brief Update the proper number of buttons for the current joystick. */
void updateButtons();
/** @brief UI change event */
virtual void changeEvent(QEvent *e);
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:
Ui::JoystickWidget *m_ui;
/** @brief Initialize all dynamic UI elements (button list, joystick names, etc.) */
void initUI();
};
#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