ffbnulleffect.cpp \
conditioneffectsettings.cpp \
ffbconditioneffectparameters.cpp \
- ffbconditioneffect.cpp
+ ffbconditioneffect.cpp \
+ rampeffectsettings.cpp \
+ ffbrampeffectparameters.cpp \
+ ffbrampeffect.cpp
HEADERS += mainwindow.h \
deviceprober.h \
ffbnulleffect.h \
conditioneffectsettings.h \
ffbconditioneffectparameters.h \
- ffbconditioneffect.h
+ ffbconditioneffect.h \
+ rampeffectsettings.h \
+ ffbrampeffectparameters.h \
+ ffbrampeffect.h
FORMS += mainwindow.ui \
constanteffectsettings.ui \
envelopesettings.ui \
periodiceffectsettings.ui \
- conditioneffectsettings.ui
+ conditioneffectsettings.ui \
+ rampeffectsettings.ui
QMAKE_CXXFLAGS += -std=c++11 -Wall
+QMAKE_CXXFLAGS_DEBUG += -ggdb3
OTHER_FILES += \
TODO.txt
#include "conditioneffectsettings.h"
#include "ui_conditioneffectsettings.h"
+#include <QDebug>
ConditionEffectSettings::ConditionEffectSettings(QWidget* parent) :
EffectSettings(parent),
ui(new Ui::ConditionEffectSettings)
{
ui->setupUi(this);
+ connect(ui->cbox_axis, SIGNAL(currentIndexChanged(int)), this, SLOT(axisChanged(const int)));
+}
+
+void ConditionEffectSettings::axisChanged(const int idx)
+{
+ ui->qstw_center->setCurrentIndex(idx);
+ ui->qstw_deadband->setCurrentIndex(idx);
+ ui->qstw_leftCoeff->setCurrentIndex(idx);
+ ui->qstw_leftSat->setCurrentIndex(idx);
+ ui->qstw_rightCoeff->setCurrentIndex(idx);
+ ui->qstw_rightSat->setCurrentIndex(idx);
+ qDebug() << "Axis changed" << idx;
}
void ConditionEffectSettings::fillAvailableSubtypesList(const QStringList& list)
bool ConditionEffectSettings::fillFromParameters(const std::shared_ptr<FFBConditionEffectParameters> cdParams)
{
- ui->qle_center->setText(QString::number(cdParams->center));
- ui->qle_deadband->setText(QString::number(cdParams->deadband));
- ui->qle_leftCoeff->setText(QString::number(cdParams->leftCoeff));
- ui->qle_rightCoeff->setText(QString::number(cdParams->rightCoeff));
- ui->qle_leftSat->setText(QString::number(cdParams->leftSat));
- ui->qle_rightSat->setText(QString::number(cdParams->rightCoeff));
+ ui->qle_centerX->setText(QString::number(cdParams->center[FFBConditionEffectParameters::Axis::X]));
+ ui->qle_deadbandX->setText(QString::number(cdParams->deadband[FFBConditionEffectParameters::Axis::X]));
+ ui->qle_leftCoeffX->setText(QString::number(cdParams->leftCoeff[FFBConditionEffectParameters::Axis::X]));
+ ui->qle_rightCoeffX->setText(QString::number(cdParams->rightCoeff[FFBConditionEffectParameters::Axis::X]));
+ ui->qle_leftSatX->setText(QString::number(cdParams->leftSat[FFBConditionEffectParameters::Axis::X]));
+ ui->qle_rightSatX->setText(QString::number(cdParams->rightCoeff[FFBConditionEffectParameters::Axis::X]));
+ ui->qle_centerY->setText(QString::number(cdParams->center[FFBConditionEffectParameters::Axis::Y]));
+ ui->qle_deadbandY->setText(QString::number(cdParams->deadband[FFBConditionEffectParameters::Axis::Y]));
+ ui->qle_leftCoeffY->setText(QString::number(cdParams->leftCoeff[FFBConditionEffectParameters::Axis::Y]));
+ ui->qle_rightCoeffY->setText(QString::number(cdParams->rightCoeff[FFBConditionEffectParameters::Axis::Y]));
+ ui->qle_leftSatY->setText(QString::number(cdParams->leftSat[FFBConditionEffectParameters::Axis::Y]));
+ ui->qle_rightSatY->setText(QString::number(cdParams->rightCoeff[FFBConditionEffectParameters::Axis::Y]));
return true;
}
-QString ConditionEffectSettings::center() const
+FFBConditionEffectParameters::Axis ConditionEffectSettings::axis() const
+{
+ switch (ui->cbox_axis->currentIndex()) {
+ case 0:
+ return FFBConditionEffectParameters::Axis::X;
+ case 1:
+ return FFBConditionEffectParameters::Axis::Y;
+ default:
+ return FFBConditionEffectParameters::Axis::NONE;
+ }
+}
+
+QString ConditionEffectSettings::centerX() const
+{
+ return ui->qle_centerX->text();
+}
+
+QString ConditionEffectSettings::centerY() const
+{
+ return ui->qle_centerY->text();
+}
+
+QString ConditionEffectSettings::deadbandX() const
+{
+ return ui->qle_deadbandX->text();
+}
+
+QString ConditionEffectSettings::deadbandY() const
+{
+ return ui->qle_deadbandY->text();
+}
+
+QString ConditionEffectSettings::leftCoeffX() const
+{
+ return ui->qle_leftCoeffX->text();
+}
+
+QString ConditionEffectSettings::leftCoeffY() const
+{
+ return ui->qle_leftCoeffY->text();
+}
+
+QString ConditionEffectSettings::rightCoeffX() const
{
- return ui->qle_center->text();
+ return ui->qle_rightCoeffX->text();
}
-QString ConditionEffectSettings::deadband() const
+QString ConditionEffectSettings::rightCoeffY() const
{
- return ui->qle_deadband->text();
+ return ui->qle_rightCoeffY->text();
}
-QString ConditionEffectSettings::leftCoeff() const
+QString ConditionEffectSettings::leftSatX() const
{
- return ui->qle_leftCoeff->text();
+ return ui->qle_leftSatX->text();
}
-QString ConditionEffectSettings::rightCoeff() const
+QString ConditionEffectSettings::leftSatY() const
{
- return ui->qle_rightCoeff->text();
+ return ui->qle_leftSatY->text();
}
-QString ConditionEffectSettings::leftSat() const
+QString ConditionEffectSettings::rightSatX() const
{
- return ui->qle_leftSat->text();
+ return ui->qle_rightSatX->text();
}
-QString ConditionEffectSettings::rightSat() const
+QString ConditionEffectSettings::rightSatY() const
{
- return ui->qle_rightSat->text();
+ return ui->qle_rightSatY->text();
}
int ConditionEffectSettings::subtypeIdx() const
void fillAvailableSubtypesList(const QStringList& list);
bool fillFromParameters(const std::shared_ptr<FFBEffectParameters> params);
bool fillFromParameters(const std::shared_ptr<FFBConditionEffectParameters> cdParams);
- QString center() const;
- QString deadband() const;
- QString leftCoeff() const;
- QString rightCoeff() const;
- QString leftSat() const;
- QString rightSat() const;
+ FFBConditionEffectParameters::Axis axis() const;
+ QString centerX() const;
+ QString centerY() const;
+ QString deadbandX() const;
+ QString deadbandY() const;
+ QString leftCoeffX() const;
+ QString leftCoeffY() const;
+ QString rightCoeffX() const;
+ QString rightCoeffY() const;
+ QString leftSatX() const;
+ QString leftSatY() const;
+ QString rightSatX() const;
+ QString rightSatY() const;
int subtypeIdx() const;
private:
Ui::ConditionEffectSettings* ui;
+
+private slots:
+ void axisChanged(const int);
};
#endif // CONDITIONEFFECTSETTINGS_H
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
- <item row="1" column="0">
+ <item row="2" column="0">
<widget class="QLabel" name="ql_leftSat">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Left saturation:</string>
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="qle_leftSat"/>
- </item>
- <item row="2" column="0">
+ <item row="3" column="0">
<widget class="QLabel" name="ql_rightSat">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Right saturation:</string>
</property>
</widget>
</item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="qle_rightSat"/>
- </item>
- <item row="3" column="0">
+ <item row="4" column="0">
<widget class="QLabel" name="ql_leftCoeff">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Left coefficient:</string>
</property>
</widget>
</item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="qle_leftCoeff"/>
- </item>
- <item row="4" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="ql_rightCoeff">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Right coefficient:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QLineEdit" name="qle_rightCoeff"/>
- </item>
- <item row="5" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="ql_deadband">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Deadband:</string>
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="ql_center">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Center:</string>
</property>
</widget>
</item>
- <item row="5" column="1">
- <widget class="QLineEdit" name="qle_deadband"/>
- </item>
- <item row="6" column="1">
- <widget class="QLineEdit" name="qle_center"/>
- </item>
<item row="0" column="0">
<widget class="QLabel" name="ql_subtype">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="text">
<string>Subtype:</string>
</property>
<item row="0" column="1">
<widget class="QComboBox" name="cbox_subtype"/>
</item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="ql_axis">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Axis:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="cbox_axis">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>X</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QStackedWidget" name="qstw_leftSat">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="leftSatX">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="qle_leftSatX">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="leftSatY">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QLineEdit" name="qle_leftSatY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QStackedWidget" name="qstw_rightSat">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="rightSatX">
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QLineEdit" name="qle_rightSatX">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="rightSatY">
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QLineEdit" name="qle_rightSatY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QStackedWidget" name="qstw_leftCoeff">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="leftCoeffX">
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QLineEdit" name="qle_leftCoeffX">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="leftCoeffY">
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <widget class="QLineEdit" name="qle_leftCoeffY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QStackedWidget" name="qstw_rightCoeff">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="rightCoeffX">
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <widget class="QLineEdit" name="qle_rightCoeffX">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="rightCoeffY">
+ <layout class="QVBoxLayout" name="verticalLayout_9">
+ <item>
+ <widget class="QLineEdit" name="qle_rightCoeffY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QStackedWidget" name="qstw_deadband">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="deadbandX">
+ <layout class="QVBoxLayout" name="verticalLayout_10">
+ <item>
+ <widget class="QLineEdit" name="qle_deadbandX">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="deadbandY">
+ <layout class="QVBoxLayout" name="verticalLayout_11">
+ <item>
+ <widget class="QLineEdit" name="qle_deadbandY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QStackedWidget" name="qstw_center">
+ <widget class="QWidget" name="centerX">
+ <layout class="QVBoxLayout" name="verticalLayout_12">
+ <item>
+ <widget class="QLineEdit" name="qle_centerX">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="centerY">
+ <layout class="QVBoxLayout" name="verticalLayout_13">
+ <item>
+ <widget class="QLineEdit" name="qle_centerY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="maxLength">
+ <number>6</number>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
</layout>
</item>
</layout>
{
struct ff_effect* eff = FFBEffect::createFFStruct(m_params);
- eff->u.condition[0].center = m_params->center;
- eff->u.condition[0].deadband = m_params->deadband;
- eff->u.condition[0].left_coeff = m_params->leftCoeff;
- eff->u.condition[0].right_coeff = m_params->rightCoeff;
- eff->u.condition[0].left_saturation = m_params->leftSat;
- eff->u.condition[0].right_saturation = m_params->rightSat;
+ eff->u.condition[0].center = m_params->center[FFBConditionEffectParameters::Axis::X];
+ eff->u.condition[0].deadband = m_params->deadband[FFBConditionEffectParameters::Axis::X];
+ eff->u.condition[0].left_coeff = m_params->leftCoeff[FFBConditionEffectParameters::Axis::X];
+ eff->u.condition[0].right_coeff = m_params->rightCoeff[FFBConditionEffectParameters::Axis::X];
+ eff->u.condition[0].left_saturation = m_params->leftSat[FFBConditionEffectParameters::Axis::X];
+ eff->u.condition[0].right_saturation = m_params->rightSat[FFBConditionEffectParameters::Axis::X];
+
+ eff->u.condition[1].center = m_params->center[FFBConditionEffectParameters::Axis::Y];
+ eff->u.condition[1].deadband = m_params->deadband[FFBConditionEffectParameters::Axis::Y];
+ eff->u.condition[1].left_coeff = m_params->leftCoeff[FFBConditionEffectParameters::Axis::Y];
+ eff->u.condition[1].right_coeff = m_params->rightCoeff[FFBConditionEffectParameters::Axis::Y];
+ eff->u.condition[1].left_saturation = m_params->leftSat[FFBConditionEffectParameters::Axis::Y];
+ eff->u.condition[1].right_saturation = m_params->rightSat[FFBConditionEffectParameters::Axis::Y];
switch (m_params->subtype) {
case ConditionSubtypes::DAMPER:
bool FFBConditionEffect::setParameters(const std::shared_ptr<FFBEffectParameters> params)
{
try {
- const std::shared_ptr<FFBConditionEffectParameters> cdParams = std::dynamic_pointer_cast<FFBConditionEffectParameters>(params);
- return setParameters(cdParams);
- } catch (std::bad_cast& ex) {
+ return setParameters(std::dynamic_pointer_cast<FFBConditionEffectParameters>(params));
+ //return setParameters(cdParams);
+ } catch (const std::bad_cast& ex) {
qCritical(ex.what());
return false;
}
if (!checkGenericParameters(params))
return false;
- if (!checkBoundsInclusive(m_params->center, -0x7FFF, 0x7FFF)) {
- reportError("Center out of bounds,");
+ if (!checkBoundsInclusive(params->center[FFBConditionEffectParameters::Axis::X], -0x7FFF, 0x7FFF)) {
+ reportError("Center X out of bounds,");
+ return false;
+ }
+ if (!checkBoundsInclusive(params->center[FFBConditionEffectParameters::Axis::Y], -0x7FFF, 0x7FFF)) {
+ reportError("Center Y out of bounds,");
return false;
}
- if (!checkBoundsInclusive(params->deadband, 0, 0xFFFF)) {
- reportError("Deadband out of bounds.");
+ if (!checkBoundsInclusive(params->deadband[FFBConditionEffectParameters::Axis::X], 0, 0xFFFF)) {
+ reportError("Deadband X out of bounds.");
+ return false;
+ }
+ if (!checkBoundsInclusive(params->deadband[FFBConditionEffectParameters::Axis::Y], 0, 0xFFFF)) {
+ reportError("Deadband Y out of bounds.");
return false;
}
- if (!checkBoundsInclusive(params->leftCoeff, -0x7FFF, 0x7FFF)) {
- reportError("Left coefficient out of bounds.");
+ if (!checkBoundsInclusive(params->leftCoeff[FFBConditionEffectParameters::Axis::X], -0x7FFF, 0x7FFF)) {
+ reportError("Left coefficient X out of bounds.");
+ return false;
+ }
+ if (!checkBoundsInclusive(params->leftCoeff[FFBConditionEffectParameters::Axis::Y], -0x7FFF, 0x7FFF)) {
+ reportError("Left coefficient Y out of bounds.");
return false;
}
- if (!checkBoundsInclusive(params->rightCoeff, -0x7FFF, 0x7FFF)) {
- reportError("Right coefficient out of bounds.");
+ if (!checkBoundsInclusive(params->rightCoeff[FFBConditionEffectParameters::Axis::X], -0x7FFF, 0x7FFF)) {
+ reportError("Right coefficient X out of bounds.");
+ return false;
+ }
+ if (!checkBoundsInclusive(params->rightCoeff[FFBConditionEffectParameters::Axis::Y], -0x7FFF, 0x7FFF)) {
+ reportError("Right coefficient Y out of bounds.");
return false;
}
- if (!checkBoundsInclusive(params->leftSat, 0, 0xFFFF)) {
- reportError("Left saturation out of bounds.");
+ if (!checkBoundsInclusive(params->leftSat[FFBConditionEffectParameters::Axis::X], 0, 0xFFFF)) {
+ reportError("Left saturation X out of bounds.");
+ return false;
+ }
+ if (!checkBoundsInclusive(params->leftSat[FFBConditionEffectParameters::Axis::Y], 0, 0xFFFF)) {
+ reportError("Left saturation Y out of bounds.");
return false;
}
- if (!checkBoundsInclusive(params->rightSat, 0, 0xFFFF)) {
- reportError("Right saturation out of bounds.");
+ if (!checkBoundsInclusive(params->rightSat[FFBConditionEffectParameters::Axis::X], 0, 0xFFFF)) {
+ reportError("Right saturation X out of bounds.");
+ return false;
+ }
+ if (!checkBoundsInclusive(params->rightSat[FFBConditionEffectParameters::Axis::Y], 0, 0xFFFF)) {
+ reportError("Right saturation Y out of bounds.");
return false;
}
#include "ffbconditioneffectparameters.h"
FFBConditionEffectParameters::FFBConditionEffectParameters() :
- FFBEffectParameters(),
- center(0),
- deadband(0),
- leftCoeff(0),
- rightCoeff(0),
- leftSat(0),
- rightSat(0)
+ FFBEffectParameters()
{}
-bool FFBConditionEffectParameters::centerFromString(const QString& center)
+bool FFBConditionEffectParameters::centerFromString(const QString& center, Axis a)
{
- return qstringToInt(this->center, center);
+ bool ok = false;
+ int val = center.toInt(&ok);
+ if (!ok) return false;
+
+ this->center[a] = val;
+ return true;
}
-bool FFBConditionEffectParameters::deadbandFromString(const QString& deadband)
+bool FFBConditionEffectParameters::deadbandFromString(const QString& deadband, Axis a)
{
- return qstringToInt(this->deadband, deadband);
+ bool ok = false;
+ int val = deadband.toInt(&ok);
+ if (!ok) return false;
+
+ this->deadband[a] = val;
+ return true;
}
-bool FFBConditionEffectParameters::leftCoeffFromString(const QString& leftCoeff)
+bool FFBConditionEffectParameters::leftCoeffFromString(const QString& leftCoeff, Axis a)
{
- return qstringToInt(this->leftCoeff, leftCoeff);
+ bool ok = false;
+ int val = leftCoeff.toInt(&ok);
+ if (!ok) return false;
+
+ this->leftCoeff[a] = val;
+ return true;
}
-bool FFBConditionEffectParameters::rightCoeffFromString(const QString& rightCoeff)
+bool FFBConditionEffectParameters::rightCoeffFromString(const QString& rightCoeff, Axis a)
{
- return qstringToInt(this->rightCoeff, rightCoeff);
+ bool ok = false;
+ int val = rightCoeff.toInt(&ok);
+ if (!ok) return false;
+
+ this->rightCoeff[a] = val;
+ return true;
}
-bool FFBConditionEffectParameters::leftSatFromString(const QString& leftSat)
+bool FFBConditionEffectParameters::leftSatFromString(const QString& leftSat, Axis a)
{
- return qstringToInt(this->leftSat, leftSat);
+ bool ok = false;
+ int val = leftSat.toInt(&ok);
+ if (!ok) return false;
+
+ this->leftSat[a] = val;
+ return true;
}
-bool FFBConditionEffectParameters::rightSatFromString(const QString& rightSat)
+bool FFBConditionEffectParameters::rightSatFromString(const QString& rightSat, Axis a)
{
- return qstringToInt(this->rightSat, rightSat);
+ bool ok = false;
+ int val = rightSat.toInt(&ok);
+ if (!ok) return false;
+
+ this->rightSat[a] = val;
+ return true;
}
#define FFBCONDITIONEFFECTPARAMETERS_H
#include "ffbeffectparameters.h"
+#include <map>
class FFBConditionEffectParameters : public FFBEffectParameters
{
public:
+ enum class Axis : quint8 { NONE = 0, X = 1, Y = 2 };
+ struct Axis_less {
+ bool operator()(Axis a, Axis b) const { return quint8(a) == quint8(b); }
+ };
+
FFBConditionEffectParameters();
- bool centerFromString(const QString& center);
- bool deadbandFromString(const QString& deadband);
- bool leftCoeffFromString(const QString& leftCoeff);
- bool rightCoeffFromString(const QString& rightCoeff);
- bool leftSatFromString(const QString& leftSat);
- bool rightSatFromString(const QString& rightSat);
+ bool centerFromString(const QString& center, Axis a);
+ bool deadbandFromString(const QString& deadband, Axis a);
+ bool leftCoeffFromString(const QString& leftCoeff, Axis a);
+ bool rightCoeffFromString(const QString& rightCoeff, Axis a);
+ bool leftSatFromString(const QString& leftSat, Axis a);
+ bool rightSatFromString(const QString& rightSat, Axis a);
inline void subtypeFromIdx(const ConditionSubtypes subtype) { this->subtype = subtype; }
- int center;
- int deadband;
- int leftCoeff;
- int rightCoeff;
- int leftSat;
- int rightSat;
+ std::map<Axis, int, Axis_less> center;
+ std::map<Axis, int, Axis_less> deadband;
+ std::map<Axis, int, Axis_less> leftCoeff;
+ std::map<Axis, int, Axis_less> rightCoeff;
+ std::map<Axis, int, Axis_less> leftSat;
+ std::map<Axis, int, Axis_less> rightSat;
ConditionSubtypes subtype;
private:
inline bool qstringToInt(int& val, const QString& str) {
return std::shared_ptr<FFBEffect>(new FFBPeriodicEffect());
case FFBEffectTypes::CONDITION:
return std::shared_ptr<FFBEffect>(new FFBConditionEffect());
+ case FFBEffectTypes::RAMP:
+ return std::shared_ptr<FFBEffect>(new FFBRampEffect());
default:
return nullptr;
}
#include "ffbconstanteffect.h"
#include "ffbnulleffect.h"
#include "ffbperiodiceffect.h"
+#include "ffbrampeffect.h"
class FFBEffectFactory
{
explicit FFBNullEffect();
inline struct ff_effect* createFFStruct() { return nullptr; }
inline const std::shared_ptr<FFBEffectParameters> parameters() const { return nullptr; }
- inline bool setParameters(const std::shared_ptr<FFBEffectParameters> params) { return false; }
+ inline bool setParameters(const std::shared_ptr<FFBEffectParameters> params) { (void)(params); return false; }
};
#endif // FFBNULLEFFECT_H
--- /dev/null
+#include "ffbrampeffect.h"
+
+FFBRampEffect::FFBRampEffect() :
+ FFBEffect(FFBEffectTypes::RAMP)
+{
+}
+
+struct ff_effect* FFBRampEffect::createFFStruct()
+{
+ struct ff_effect* eff = FFBEffect::createFFStruct(m_params);
+ if (eff == nullptr)
+ return nullptr;
+
+ eff->type = FF_RAMP;
+
+ eff->u.ramp.envelope.attack_length = m_params->attackLength;
+ eff->u.ramp.envelope.attack_level = m_params->attackLevel;
+ eff->u.ramp.envelope.fade_length = m_params->fadeLength;
+ eff->u.ramp.envelope.fade_level = m_params->fadeLevel;
+
+ eff->u.ramp.end_level = m_params->endLevel;
+ eff->u.ramp.start_level = m_params->startLevel;
+
+ return eff;
+}
+
+
+bool FFBRampEffect::setParameters(const std::shared_ptr<FFBEffectParameters> params)
+{
+ try {
+ return setParameters(std::dynamic_pointer_cast<FFBRampEffectParameters>(params));
+ } catch (const std::bad_cast& ex) {
+ reportError("Invalid effect parameters object " + QString(ex.what()));
+ return false;
+ }
+}
+
+bool FFBRampEffect::setParameters(const std::shared_ptr<FFBRampEffectParameters> params)
+{
+ if (!checkGenericParameters(params))
+ return false;
+
+ if (!checkBoundsInclusive(params->attackLength, 0, 0xFFFF)) {
+ reportError("Attack length out of bounds.");
+ return false;
+ }
+
+ if (!checkBoundsInclusive(params->attackLevel, 0, 0xFFFF)) {
+ reportError("Attack level out of bounds.");
+ return false;
+ }
+
+ if (!checkBoundsInclusive(params->fadeLength, 0, 0xFFFF)) {
+ reportError("Fade length out of bounds.");
+ return false;
+ }
+
+ if (!checkBoundsInclusive(params->endLevel, -0x7FFF, 0x7FFF)) {
+ reportError("End level out of bounds");
+ return false;
+ }
+
+ if (!checkBoundsInclusive(params->startLevel, -0x7FFF, 0x7FFF)) {
+ reportError("Start level out of bounds");
+ return false;
+ }
+
+ m_params = params;
+ return true;
+}
+
+FFBRampEffect::~FFBRampEffect()
+{
+}
--- /dev/null
+#ifndef FFBRAMPEFFECT_H
+#define FFBRAMPEFFECT_H
+
+#include "ffbeffect.h"
+#include "ffbrampeffectparameters.h"
+
+class FFBRampEffect : public FFBEffect
+{
+public:
+ FFBRampEffect();
+ ~FFBRampEffect();
+ struct ff_effect* createFFStruct();
+ inline const std::shared_ptr<FFBEffectParameters> parameters() const { return m_params; }
+ bool setParameters(const std::shared_ptr<FFBEffectParameters> params);
+ bool setParameters(const std::shared_ptr<FFBRampEffectParameters> params);
+
+private:
+ std::shared_ptr<FFBRampEffectParameters> m_params;
+};
+
+#endif // FFBRAMPEFFECT_H
--- /dev/null
+#include "ffbrampeffectparameters.h"
+
+FFBRampEffectParameters::FFBRampEffectParameters() :
+ FFBEffectParameters(), FFBEnvelopeParameters(),
+ endLevel(0),
+ startLevel(0)
+{
+}
+
+bool FFBRampEffectParameters::endLevelFromString(const QString& endLevel)
+{
+ bool ok;
+ this->endLevel = endLevel.toInt(&ok);
+ return ok;
+}
+
+bool FFBRampEffectParameters::startLevelFromString(const QString& startLevel)
+{
+ bool ok;
+ this->startLevel = startLevel.toInt(&ok);
+ return ok;
+}
+
--- /dev/null
+#ifndef FFBRAMPEFFECTPARAMETERS_H
+#define FFBRAMPEFFECTPARAMETERS_H
+
+#include "ffbeffectparameters.h"
+#include "ffbenvelopeparameters.h"
+
+class FFBRampEffectParameters : public FFBEffectParameters, public FFBEnvelopeParameters
+{
+public:
+ FFBRampEffectParameters();
+ bool endLevelFromString(const QString& endLevel);
+ bool startLevelFromString(const QString& startLevel);
+
+ int endLevel;
+ int startLevel;
+};
+
+#endif // FFBRAMPEFFECTPARAMETERS_H
#define APP_NAME "FFBChecker"
static const int APP_VERSION_MAJOR(0);
static const int APP_VERSION_MINOR(2);
-static const char APP_VERSION_REL('a');
+static const char APP_VERSION_REL('b');
enum class FFBEffectTypes { NONE, CONSTANT, PERIODIC, RAMP, CONDITION, RUMBLE};
enum class PeriodicWaveforms { NONE, SQUARE, TRIANGLE, SINE, SAW_UP, SAW_DOWN };
m_constantEffSet = new ConstantEffectSettings();
m_periodicEffSet = new PeriodicEffectSettings();
m_conditionEffSet = new ConditionEffectSettings();
+ m_rampEffSet = new RampEffectSettings();
ui->qstw_effectSpecifics->addWidget(m_conditionEffSet);
ui->qstw_effectSpecifics->addWidget(m_constantEffSet);
ui->qstw_effectSpecifics->addWidget(m_periodicEffSet);
+ ui->qstw_effectSpecifics->addWidget(m_rampEffSet);
fillDeviceList();
connect(ui->cbox_devices, SIGNAL(activated(const QString&)), this, SLOT(onDeviceSelected(const QString&)));
return m_periodicEffSet;
case FFBEffectTypes::CONDITION:
return m_conditionEffSet;
+ case FFBEffectTypes::RAMP:
+ return m_rampEffSet;
default:
abort();
}
}
case FFBEffectTypes::CONDITION:
{
- std::shared_ptr<FFBConditionEffectParameters> cdParams = std::shared_ptr<FFBConditionEffectParameters>(new FFBConditionEffectParameters);
- if (!readGeneralEffectParameters(params))
+ std::shared_ptr<FFBConditionEffectParameters> iParams = std::shared_ptr<FFBConditionEffectParameters>(new FFBConditionEffectParameters);
+ if (!readGeneralEffectParameters(iParams))
return false;
- if (!cdParams->centerFromString(m_conditionEffSet->center())) {
+ if (!iParams->centerFromString(m_conditionEffSet->centerX(), FFBConditionEffectParameters::Axis::X)) {
QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Center\"");
return false;
}
- if (!cdParams->deadbandFromString(m_conditionEffSet->deadband())) {
+ if (!iParams->centerFromString(m_conditionEffSet->centerY(), FFBConditionEffectParameters::Axis::Y)) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Center\"");
+ return false;
+ }
+ if (!iParams->deadbandFromString(m_conditionEffSet->deadbandX(), FFBConditionEffectParameters::Axis::X)) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Deadband\"");
+ return false;
+ }
+ if (!iParams->deadbandFromString(m_conditionEffSet->deadbandY(), FFBConditionEffectParameters::Axis::Y)) {
QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Deadband\"");
return false;
}
- if (!cdParams->leftCoeffFromString(m_conditionEffSet->leftCoeff())) {
+ if (!iParams->leftCoeffFromString(m_conditionEffSet->leftCoeffX(), FFBConditionEffectParameters::Axis::X)) {
QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Left coefficient\"");
return false;
}
- if (!cdParams->rightCoeffFromString(m_conditionEffSet->rightCoeff())) {
+ if (!iParams->leftCoeffFromString(m_conditionEffSet->leftCoeffY(), FFBConditionEffectParameters::Axis::Y)) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Left coefficient\"");
+ return false;
+ }
+ if (!iParams->rightCoeffFromString(m_conditionEffSet->rightCoeffX(), FFBConditionEffectParameters::Axis::X)) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Right coefficient\"");
+ return false;
+ }
+ if (!iParams->rightCoeffFromString(m_conditionEffSet->rightCoeffY(), FFBConditionEffectParameters::Axis::Y)) {
QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Right coefficient\"");
return false;
}
- if (!cdParams->leftSatFromString(m_conditionEffSet->leftSat())) {
+ if (!iParams->leftSatFromString(m_conditionEffSet->leftSatX(), FFBConditionEffectParameters::Axis::X)) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Left saturation\"");
+ return false;
+ }
+ if (!iParams->leftSatFromString(m_conditionEffSet->leftSatY(), FFBConditionEffectParameters::Axis::Y)) {
QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Left saturation\"");
return false;
}
- if (!cdParams->rightSatFromString(m_conditionEffSet->rightSat())) {
+ if (!iParams->rightSatFromString(m_conditionEffSet->rightSatX(), FFBConditionEffectParameters::Axis::X)) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Right saturation\"");
+ return false;
+ }
+ if (!iParams->rightSatFromString(m_conditionEffSet->rightSatY(), FFBConditionEffectParameters::Axis::Y)) {
QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Right saturation\"");
return false;
}
ConditionSubtypes subtype = m_activeDevice->conditionSubtypeByIdx(m_conditionEffSet->subtypeIdx());
- cdParams->subtypeFromIdx(subtype);
+ iParams->subtypeFromIdx(subtype);
+
+ params = iParams;
+ break;
+ }
+ case FFBEffectTypes::RAMP: {
+ std::shared_ptr<FFBRampEffectParameters> iParams = std::shared_ptr<FFBRampEffectParameters>(new FFBRampEffectParameters);
+ if (!readGeneralEffectParameters(iParams))
+ return false;
+ if (!readEnvelopeParameters(iParams, m_rampEffSet->envelopeSettings()))
+ return false;
- params = cdParams;
+ if (!iParams->endLevelFromString(m_rampEffSet->endLevel())) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"End level\"");
+ return false;
+ }
+ if (!iParams->startLevelFromString(m_rampEffSet->startLevel())) {
+ QMessageBox::warning(this, res_inputFormatErrCap, "Invalid data in field \"Start level\"");
+ return false;
+ }
+
+ params = iParams;
+ break;
}
default:
qDebug() << "Unhandled type of effect";
#include "ffbconstanteffectparameters.h"
#include "ffbdevice.h"
#include "ffbperiodiceffectparameters.h"
+#include "ffbrampeffectparameters.h"
#include "periodiceffectsettings.h"
+#include "rampeffectsettings.h"
#include <memory>
#include <QMainWindow>
ConditionEffectSettings* m_conditionEffSet;
ConstantEffectSettings* m_constantEffSet;
PeriodicEffectSettings* m_periodicEffSet;
+ RampEffectSettings* m_rampEffSet;
std::shared_ptr<DeviceProber> m_prober;
Ui::MainWindow* ui;
--- /dev/null
+#include "rampeffectsettings.h"
+#include "ui_rampeffectsettings.h"
+
+RampEffectSettings::RampEffectSettings(QWidget* parent) :
+ EffectSettings(parent),
+ ui(new Ui::RampEffectSettings)
+{
+ ui->setupUi(this);
+}
+
+const EnvelopeSettings* RampEffectSettings::envelopeSettings() const
+{
+ return ui->qwid_envelope;
+}
+
+QString RampEffectSettings::endLevel() const
+{
+ return ui->qle_endLevel->text();
+}
+
+QString RampEffectSettings::startLevel() const
+{
+ return ui->qle_startLevel->text();
+}
+
+bool RampEffectSettings::fillFromParameters(const std::shared_ptr<FFBEffectParameters> params)
+{
+ try {
+ const std::shared_ptr<FFBRampEffectParameters> rfParams = std::dynamic_pointer_cast<FFBRampEffectParameters>(params);
+
+ ui->qle_endLevel->setText(QString::number(rfParams->endLevel));
+ ui->qle_startLevel->setText(QString::number(rfParams->startLevel));
+ return ui->qwid_envelope->fillFromParameters(params);
+ } catch (std::bad_cast& ex) {
+ qCritical(ex.what());
+ return false;
+ }
+ return false;
+}
+
+RampEffectSettings::~RampEffectSettings()
+{
+ delete ui;
+}
--- /dev/null
+#ifndef RAMPEFFECTSETTINGS_H
+#define RAMPEFFECTSETTINGS_H
+
+#include "effectsettings.h"
+#include "envelopesettings.h"
+#include"ffbrampeffectparameters.h"
+
+namespace Ui {
+ class RampEffectSettings;
+}
+
+class RampEffectSettings : public EffectSettings
+{
+ Q_OBJECT
+
+public:
+ explicit RampEffectSettings(QWidget* parent = nullptr);
+ ~RampEffectSettings();
+ const EnvelopeSettings* envelopeSettings() const;
+ bool fillFromParameters(const std::shared_ptr<FFBEffectParameters> params);
+ QString endLevel() const;
+ QString startLevel() const;
+
+private:
+ Ui::RampEffectSettings *ui;
+};
+
+#endif // RAMPEFFECTSETTINGS_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RampEffectSettings</class>
+ <widget class="QWidget" name="RampEffectSettings">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>84</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="ql_startLevel">
+ <property name="text">
+ <string>Start level:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="ql_endLevel">
+ <property name="text">
+ <string>End level:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="qle_startLevel">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="qle_endLevel">
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="EnvelopeSettings" name="qwid_envelope" native="true"/>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>EnvelopeSettings</class>
+ <extends>QWidget</extends>
+ <header location="global">envelopesettings.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>