Files
antimicrox/src/joycontrolstick.cpp
2022-10-11 12:25:15 +02:00

3964 lines
122 KiB
C++

/* antimicrox Gamepad to KB+M event mapper
* Copyright (C) 2015 Travis Nickles <nickles.travis@gmail.com>
* Copyright (C) 2020 Jagoda Górska <juliagoda.pl@protonmail>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 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.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "joycontrolstick.h"
#include "globalvariables.h"
#include "inputdevice.h"
#include "joyaxis.h"
#include "joybuttontypes/joycontrolstickbutton.h"
#include "joybuttontypes/joycontrolstickmodifierbutton.h"
#include "xml/joybuttonxml.h"
#include <QDebug>
#include <QHashIterator>
#include <QLabel>
#include <QPointer>
#include <QStringList>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
//#include <QtTest/QTest>
#include <math.h>
const JoyControlStick::JoyMode JoyControlStick::DEFAULTMODE = JoyControlStick::StandardMode;
JoyControlStick::JoyControlStick(JoyAxis *axis1, JoyAxis *axis2, int index, int originset, QObject *parent)
: QObject(parent)
{
this->axisX = axis1;
this->axisX->setControlStick(this);
this->axisY = axis2;
this->axisY->setControlStick(this);
this->index = index;
this->originset = originset;
this->modifierButton = nullptr;
reset();
populateStickBtns();
directionDelayTimer.setSingleShot(true);
connect(&directionDelayTimer, &QTimer::timeout, this, &JoyControlStick::stickDirectionChangeEvent);
}
JoyControlStick::~JoyControlStick()
{
if (!axisX.isNull())
axisX->removeControlStick(false);
if (!axisY.isNull())
axisY->removeControlStick(false);
}
/**
* @brief Take the input value for the two axes that make up a stick and
* activate the proper event based on the current values.
* @param Should set changing routines be ignored.
*/
void JoyControlStick::joyEvent(bool ignoresets)
{
safezone = !inDeadZone();
if (safezone && !isActive)
{
isActive = true;
emit active(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
if (ignoresets || (stickDelay == 0))
{
if (directionDelayTimer.isActive())
directionDelayTimer.stop();
createDeskEvent(ignoresets);
} else
{
if (!directionDelayTimer.isActive())
directionDelayTimer.start(stickDelay);
}
} else if (!safezone && isActive)
{
isActive = false;
emit released(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
if (ignoresets || (stickDelay == 0))
{
if (directionDelayTimer.isActive())
directionDelayTimer.stop();
createDeskEvent(ignoresets);
} else
{
if (!directionDelayTimer.isActive())
directionDelayTimer.start(stickDelay);
}
} else if (isActive)
{
if (ignoresets || (stickDelay == 0))
{
if (directionDelayTimer.isActive())
directionDelayTimer.stop();
createDeskEvent(ignoresets);
} else
{
JoyStickDirections pendingDirection = calculateStickDirection();
if (currentDirection != pendingDirection)
{
if (!directionDelayTimer.isActive())
directionDelayTimer.start(stickDelay);
} else
{
if (directionDelayTimer.isActive())
directionDelayTimer.stop();
createDeskEvent(ignoresets);
}
}
}
emit moved(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
pendingStickEvent = false;
}
/**
* @brief Check the current stick position to see if it lies in
* the assigned dead zone.
* @return If stick position is in the assigned dead zone
*/
bool JoyControlStick::inDeadZone()
{
int axis1Value = axisX->getCurrentRawValue();
int axis2Value = axisY->getCurrentRawValue();
int squareDist = (axis1Value * axis1Value) + (axis2Value * axis2Value);
return squareDist <= (deadZone * deadZone);
}
/**
* @brief Populate the virtual buttons assigned to an analog stick.
*/
void JoyControlStick::populateButtons() { populateStickBtns(); }
void JoyControlStick::populateStickBtns()
{
JoyControlStickButton *button = new JoyControlStickButton(this, StickUp, originset, getParentSet(), this);
buttons.insert(StickUp, button);
button = new JoyControlStickButton(this, StickDown, originset, getParentSet(), this);
buttons.insert(StickDown, button);
button = new JoyControlStickButton(this, StickLeft, originset, getParentSet(), this);
buttons.insert(StickLeft, button);
button = new JoyControlStickButton(this, StickRight, originset, getParentSet(), this);
buttons.insert(StickRight, button);
button = new JoyControlStickButton(this, StickLeftUp, originset, getParentSet(), this);
buttons.insert(StickLeftUp, button);
button = new JoyControlStickButton(this, StickLeftDown, originset, getParentSet(), this);
buttons.insert(StickLeftDown, button);
button = new JoyControlStickButton(this, StickRightDown, originset, getParentSet(), this);
buttons.insert(StickRightDown, button);
button = new JoyControlStickButton(this, StickRightUp, originset, getParentSet(), this);
buttons.insert(StickRightUp, button);
modifierButton = new JoyControlStickModifierButton(this, originset, getParentSet(), this);
}
/**
* @brief Get the assigned dead zone value.
* @return Assigned dead zone value
*/
int JoyControlStick::getDeadZone() { return deadZone; }
/**
* @brief Get the assigned diagonal range value.
* @return Assigned diagonal range.
*/
int JoyControlStick::getDiagonalRange() { return diagonalRange; }
/**
* @brief Find the position of the two stick axes, deactivate no longer used
* stick direction button and then activate direction buttons for new
* direction.
* @param Should set changing operations be ignored. Necessary in the middle
* of a set change.
*/
void JoyControlStick::createDeskEvent(bool ignoresets)
{
JoyControlStickButton *eventbutton1 = nullptr;
JoyControlStickButton *eventbutton2 = nullptr;
JoyControlStickButton *eventbutton3 = nullptr;
if (safezone)
{
switch (currentMode)
{
case StandardMode:
determineStandardModeEvent(eventbutton1, eventbutton2);
break;
case EightWayMode:
determineEightWayModeEvent(eventbutton1, eventbutton2, eventbutton3);
break;
case FourWayCardinal:
determineFourWayCardinalEvent(eventbutton1, eventbutton2);
break;
case FourWayDiagonal:
determineFourWayDiagonalEvent(eventbutton3);
break;
}
} else
{
currentDirection = StickCentered;
}
/*
* Release any currently active stick buttons.
*/
if ((eventbutton1 == nullptr) && (activeButton1 != nullptr))
{
// Currently in deadzone. Disable currently active button.
performButtonRelease(activeButton1, ignoresets);
} else if ((eventbutton1 != nullptr) && (activeButton1 != nullptr) && (eventbutton1 != activeButton1))
{
// Deadzone skipped. Button for new event is not the currently
// active button. Disable the active button.
performButtonRelease(activeButton1, ignoresets);
}
if ((eventbutton2 == nullptr) && (activeButton2 != nullptr))
{
// Currently in deadzone. Disable currently active button.
performButtonRelease(activeButton2, ignoresets);
} else if ((eventbutton2 != nullptr) && (activeButton2 != nullptr) && (eventbutton2 != activeButton2))
{
// Deadzone skipped. Button for new event is not the currently
// active button. Disable the active button.
performButtonRelease(activeButton2, ignoresets);
}
if ((eventbutton3 == nullptr) && (activeButton3 != nullptr))
{
// Currently in deadzone. Disable currently active button.
performButtonRelease(activeButton3, ignoresets);
} else if ((eventbutton3 != nullptr) && (activeButton3 != nullptr) && (eventbutton3 != activeButton3))
{
// Deadzone skipped. Button for new event is not the currently
// active button. Disable the active button.
performButtonRelease(activeButton3, ignoresets);
}
// Activate modifier button before activating directional buttons.
// Value from the new stick event will be used to determine
// distance events.
// Release modifier button after releasing directional buttons.
double distance = getAbsoluteRawDistance();
if (m_modifier_zone_inverted)
{
if (safezone && distance < m_modifier_zone)
modifierButton->joyEvent(true, ignoresets);
else
modifierButton->joyEvent(false, ignoresets);
} else
{
if (safezone && distance > m_modifier_zone)
modifierButton->joyEvent(true, ignoresets);
else
modifierButton->joyEvent(false, ignoresets);
}
/*
* Enable stick buttons.
*/
if ((eventbutton1 != nullptr) && (activeButton1 == nullptr))
{
// There is no active button. Call joyEvent and set current
// button as active button
performButtonPress(eventbutton1, activeButton1, ignoresets);
} else if ((eventbutton1 != nullptr) && (activeButton1 != nullptr) && (eventbutton1 == activeButton1))
{
// Button is currently active. Just pass current value
performButtonPress(eventbutton1, activeButton1, ignoresets);
}
if ((eventbutton2 != nullptr) && (activeButton2 == nullptr))
{
// There is no active button. Call joyEvent and set current
// button as active button
performButtonPress(eventbutton2, activeButton2, ignoresets);
} else if ((eventbutton2 != nullptr) && (activeButton2 != nullptr) && (eventbutton2 == activeButton2))
{
// Button is currently active. Just pass current value
performButtonPress(eventbutton2, activeButton2, ignoresets);
}
if ((eventbutton3 != nullptr) && (activeButton3 == nullptr))
{
// There is no active button. Call joyEvent and set current
// button as active button
performButtonPress(eventbutton3, activeButton3, ignoresets);
} else if ((eventbutton3 != nullptr) && (activeButton3 != nullptr) && (eventbutton3 == activeButton3))
{
// Button is currently active. Just pass current value
performButtonPress(eventbutton3, activeButton3, ignoresets);
}
}
/**
* @brief Calculate the bearing (in degrees) corresponding to the current
* position of the X and Y axes of a stick.
* @return Bearing (in degrees)
*/
double JoyControlStick::calculateBearing()
{
return calculateBearing(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
/**
* @brief Calculate the bearing (in degrees) corresponding to the
* passed X and Y axes values associated with the stick.
* @param X axis value
* @param Y axis value
* @return Bearing (in degrees)
*/
double JoyControlStick::calculateBearing(int axisXValue, int axisYValue)
{
double finalAngle = 0.0;
int axis1Value = axisXValue;
int axis2Value = axisYValue;
if ((axis1Value == 0) && (axis2Value == 0))
{
finalAngle = 0.0;
} else
{
double temp1 = axis1Value;
double temp2 = axis2Value;
double angle = (atan2(temp1, -temp2) * 180) / GlobalVariables::JoyControlStick::PI;
if ((axis1Value >= 0) && (axis2Value <= 0))
{
// NE Quadrant
finalAngle = angle;
} else if ((axis1Value >= 0) && (axis2Value >= 0))
{
// SE Quadrant (angle will be positive)
finalAngle = angle;
} else if ((axis1Value <= 0) && (axis2Value >= 0))
{
// SW Quadrant (angle will be negative)
finalAngle = 360.0 + angle;
} else if ((axis1Value <= 0) && (axis2Value <= 0))
{
// NW Quadrant (angle will be negative)
finalAngle = 360.0 + angle;
}
}
return finalAngle;
}
/**
* @brief Get current radial distance of the stick position past the assigned
* dead zone.
* @return Distance percentage in the range of 0.0 - 1.0.
*/
double JoyControlStick::getDistanceFromDeadZone()
{
return getDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
/**
* @brief Get radial distance of the stick position past the assigned dead zone
* based on the passed X and Y axes values associated with the stick.
* @param X axis value
* @param Y axis value
* @return Distance percentage in the range of 0.0 - 1.0.
*/
double JoyControlStick::getDistanceFromDeadZone(int axisXValue, int axisYValue)
{
double distance = 0.0;
int axis1Value = axisXValue;
int axis2Value = axisYValue;
double angle2 = atan2(axis1Value, -axis2Value);
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
int squared_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value);
int dist = sqrt(squared_dist);
double squareStickFullPhi = qMin((ang_sin != 0.0) ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
double adjustedDist = (circleStickFull > 1.0) ? (dist / circleStickFull) : dist;
double adjustedDeadZone = (circleStickFull > 1.0) ? (deadZone / circleStickFull) : deadZone;
distance = (adjustedDist - adjustedDeadZone) / (static_cast<double>(maxZone) - adjustedDeadZone);
distance = qBound(0.0, distance, 1.0);
return distance;
}
/**
* @brief Get distance of the Y axis past the assigned dead zone.
* @param Should interpolation be performed along the diagonal regions.
* @return Distance percentage in the range of 0.0 - 1.0.
*/
double JoyControlStick::calculateYDistanceFromDeadZone(bool interpolate)
{
return calculateYDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue(), interpolate);
}
/**
* @brief Get distance of the Y axis past the assigned dead zone based
* on the passed X and Y axis values for the analog stick.
* @param X axis value
* @param Y axis value
* @param Should interpolation be performed along the diagonal regions.
* @return Distance percentage in the range of 0.0 - 1.0.
*/
double JoyControlStick::calculateYDistanceFromDeadZone(int axisXValue, int axisYValue, bool interpolate)
{
double distance = 0.0;
int axis1Value = axisXValue;
int axis2Value = axisYValue;
double angle2 = atan2(axis1Value, -axis2Value);
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
int deadY = abs(floor(deadZone * ang_cos + 0.5));
double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
double adjustedAxis2Value = (circleStickFull > 1.0) ? (axis2Value / circleStickFull) : axis2Value;
double adjustedDeadYZone = (circleStickFull > 1.0) ? (deadY / circleStickFull) : deadY;
// Interpolation would return the correct value if diagonalRange is 90 but
// the routine gets skipped to save time.
if (interpolate && (diagonalRange < 90))
{
JoyStickDirections direction = calculateStickDirection(axis1Value, axis2Value);
if ((direction == StickRightUp) || (direction == StickUp))
{
QList<double> tempangles = getDiagonalZoneAngles();
double minangle = tempangles.at(1);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadY = fabs(square_dist * sin(minangle * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadY = qMax(adjustedDeadYZone, mindeadY);
double maxRange = static_cast<double>(maxZone) - currentDeadY;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
distance = tempdist4;
} else if ((direction == StickRightDown) || (direction == StickRight))
{
QList<double> tempfuck = getDiagonalZoneAngles();
double minangle = tempfuck.at(4);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadY = fabs(square_dist * sin((minangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadY = qMax(adjustedDeadYZone, mindeadY);
double maxRange = static_cast<double>(maxZone) - currentDeadY;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
distance = tempdist4;
} else if ((direction == StickLeftDown) || (direction == StickDown))
{
QList<double> tempangles = getDiagonalZoneAngles();
double minangle = tempangles.at(6);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadY = fabs(square_dist * sin((minangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadY = qMax(adjustedDeadYZone, mindeadY);
double maxRange = static_cast<double>(maxZone) - currentDeadY;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
distance = tempdist4;
} else if ((direction == StickLeftUp) || (direction == StickLeft))
{
QList<double> tempangles = getDiagonalZoneAngles();
double minangle = tempangles.at(8);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadY = fabs(square_dist * sin((minangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadY = qMax(adjustedDeadYZone, mindeadY);
double maxRange = static_cast<double>(maxZone) - currentDeadY;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
distance = tempdist4;
} else
{
// Backup plan. Should not arrive here.
double maxRange = static_cast<double>(maxZone) - adjustedDeadYZone;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis2Value) - adjustedDeadYZone) / maxRange;
distance = tempdist4;
}
} else
{
// No interpolation desired or diagonal range is 90 degrees.
double maxRange = static_cast<double>(maxZone) - adjustedDeadYZone;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis2Value) - adjustedDeadYZone) / maxRange;
distance = tempdist4;
}
distance = qBound(0.0, distance, 1.0);
return distance;
}
/**
* @brief Get distance of the X axis past the assigned dead zone.
* @param Should interpolation be performed along the diagonal regions.
* @return Distance percentage in the range of 0.0 - 1.0.
*/
double JoyControlStick::calculateXDistanceFromDeadZone(bool interpolate)
{
return calculateXDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue(), interpolate);
}
/**
* @brief Get distance of the X axis past the assigned dead zone based
* on the passed X and Y axis values for the analog stick.
* @param X axis value
* @param Y axis value
* @param Should interpolation be performed along the diagonal regions.
* @return Distance percentage in the range of 0.0 - 1.0.
*/
double JoyControlStick::calculateXDistanceFromDeadZone(int axisXValue, int axisYValue, bool interpolate)
{
double distance = 0.0;
int axis1Value = axisXValue;
int axis2Value = axisYValue;
double angle2 = atan2(axis1Value, -axis2Value);
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
int deadX = abs(floor(deadZone * ang_sin + 0.5));
double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
double adjustedAxis1Value = (circleStickFull > 1.0) ? (axis1Value / circleStickFull) : axis1Value;
double adjustedDeadXZone = (circleStickFull > 1.0) ? (deadX / circleStickFull) : deadX;
// Interpolation would return the correct value if diagonalRange is 90 but
// the routine gets skipped to save time.
if (interpolate && (diagonalRange < 90))
{
JoyStickDirections direction = calculateStickDirection(axis1Value, axis2Value);
if ((direction == StickRightUp) || (direction == StickRight))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(3);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadX = fabs(square_dist * cos(maxangle * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadX = qMax(mindeadX, adjustedDeadXZone);
double maxRange = static_cast<double>(maxZone) - currentDeadX;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
distance = tempdist4;
} else if ((direction == StickRightDown) || (direction == StickDown))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(5);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadX = fabs(square_dist * cos((maxangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadX = qMax(mindeadX, adjustedDeadXZone);
double maxRange = static_cast<double>(maxZone) - currentDeadX;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
distance = tempdist4;
} else if ((direction == StickLeftDown) || (direction == StickLeft))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(7);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadX = fabs(square_dist * cos((maxangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadX = qMax(mindeadX, adjustedDeadXZone);
double maxRange = static_cast<double>(maxZone) - currentDeadX;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
distance = tempdist4;
} else if ((direction == StickLeftUp) || (direction == StickUp))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(1);
double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
double mindeadX = fabs(square_dist * cos((maxangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0));
double currentDeadX = qMax(mindeadX, adjustedDeadXZone);
double maxRange = static_cast<double>(maxZone) - currentDeadX;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
distance = tempdist4;
} else
{
// Backup plan. Should not arrive here.
double maxRange = static_cast<double>(maxZone) - adjustedDeadXZone;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis1Value) - adjustedDeadXZone) / maxRange;
distance = tempdist4;
}
} else
{
// No interpolation desired or diagonal range is 90 degrees.
double maxRange = static_cast<double>(maxZone) - adjustedDeadXZone;
double tempdist4 = 0.0;
if (maxRange != 0.0)
tempdist4 = (fabs(adjustedAxis1Value) - adjustedDeadXZone) / maxRange;
distance = tempdist4;
}
distance = qBound(0.0, distance, 1.0);
return distance;
}
/**
* @brief Get the raw radial distance of the stick. Values will be between 0 - 32,767.
* @return Radial distance in the range of 0 - 32,767.
*/
double JoyControlStick::getAbsoluteRawDistance()
{
double temp = getAbsoluteRawDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
return temp;
}
double JoyControlStick::getAbsoluteRawDistance(int axisXValue, int axisYValue)
{
int axis1Value = axisXValue;
int axis2Value = axisYValue;
int square_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value);
return sqrt(square_dist);
}
double JoyControlStick::getNormalizedAbsoluteDistance()
{
int axis1Value = axisX->getCurrentRawValue();
int axis2Value = axisY->getCurrentRawValue();
int square_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value);
double distance = sqrt(square_dist) / static_cast<double>(maxZone);
if (distance > 1.0)
distance = 1.0;
else if (distance < 0.0)
distance = 0.0;
return distance;
}
double JoyControlStick::getRadialDistance(int axisXValue, int axisYValue)
{
int axis1Value = axisXValue;
int axis2Value = axisYValue;
int square_dist = (axis1Value * axis1Value) + (axis2Value * axis2Value);
double distance = sqrt(square_dist) / static_cast<double>(maxZone);
if (distance > 1.0)
distance = 1.0;
else if (distance < 0.0)
distance = 0.0;
return distance;
}
void JoyControlStick::setIndex(int index) { this->index = index; }
int JoyControlStick::getIndex() { return index; }
int JoyControlStick::getRealJoyIndex() { return index + 1; }
QString JoyControlStick::getName(bool forceFullFormat, bool displayNames)
{
QString label = getPartialName(forceFullFormat, displayNames);
label.append(": ");
QStringList tempList = QStringList();
if (buttons.contains(StickUp))
{
JoyControlStickButton *button = buttons.value(StickUp);
if (!button->getButtonName().isEmpty())
tempList.append(button->getButtonName());
else
tempList.append(button->getSlotsSummary());
}
if (buttons.contains(StickLeft))
{
JoyControlStickButton *button = buttons.value(StickLeft);
if (!button->getButtonName().isEmpty())
tempList.append(button->getButtonName());
else
tempList.append(button->getSlotsSummary());
}
if (buttons.contains(StickDown))
{
JoyControlStickButton *button = buttons.value(StickDown);
if (!button->getButtonName().isEmpty())
tempList.append(button->getButtonName());
else
tempList.append(button->getSlotsSummary());
}
if (buttons.contains(StickRight))
{
JoyControlStickButton *button = buttons.value(StickRight);
if (!button->getButtonName().isEmpty())
tempList.append(button->getButtonName());
else
tempList.append(button->getSlotsSummary());
}
label.append(tempList.join(", "));
return label;
}
QString JoyControlStick::getPartialName(bool forceFullFormat, bool displayNames)
{
QString label = QString();
if (!stickName.isEmpty() && displayNames)
{
if (forceFullFormat)
label.append(tr("Stick")).append(" ");
label.append(stickName);
} else if (!defaultStickName.isEmpty())
{
if (forceFullFormat)
label.append(tr("Stick")).append(" ");
label.append(defaultStickName);
} else
{
label.append(tr("Stick")).append(" ");
label.append(QString::number(getRealJoyIndex()));
}
setStickName(label);
return label;
}
void JoyControlStick::setDefaultStickName(QString tempname)
{
defaultStickName = tempname;
emit stickNameChanged();
}
QString JoyControlStick::getDefaultStickName() { return defaultStickName; }
int JoyControlStick::getMaxZone() { return maxZone; }
/**
* @brief Returns the modifier zone of the stick
*/
int JoyControlStick::getModifierZone() const { return m_modifier_zone; }
/**
* @brief Checks if the modifier zone of this stick is inverted
* @returns True if the modifier zone is inverted, false otherwise
*/
bool JoyControlStick::getModifierZoneInverted() const { return m_modifier_zone_inverted; }
int JoyControlStick::getCurrentlyAssignedSet() { return originset; }
void JoyControlStick::reset()
{
deadZone = GlobalVariables::JoyControlStick::DEFAULTDEADZONE;
maxZone = GlobalVariables::JoyAxis::AXISMAXZONE;
m_modifier_zone = GlobalVariables::JoyControlStick::DEFAULTMODIFIERZONE;
m_modifier_zone_inverted = GlobalVariables::JoyControlStick::DEFAULTMODIFIERZONEINVERTED;
diagonalRange = GlobalVariables::JoyControlStick::DEFAULTDIAGONALRANGE;
isActive = false;
pendingStickEvent = false;
activeButton1 = nullptr;
activeButton2 = nullptr;
activeButton3 = nullptr;
safezone = false;
currentDirection = StickCentered;
currentMode = StandardMode;
stickName.clear();
circle = GlobalVariables::JoyControlStick::DEFAULTCIRCLE;
stickDelay = GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY;
resetButtons();
}
void JoyControlStick::setDeadZone(int value)
{
value = std::min(abs(value), GlobalVariables::JoyAxis::AXISMAX);
if ((value != deadZone) && (value <= maxZone))
{
deadZone = value;
emit deadZoneChanged(value);
emit propertyUpdated();
}
}
void JoyControlStick::setMaxZone(int value)
{
value = std::min(abs(value), GlobalVariables::JoyAxis::AXISMAX);
if ((value != maxZone) && (value > deadZone))
{
maxZone = value;
emit maxZoneChanged(value);
emit propertyUpdated();
}
}
/**
* @brief Sets the modifier zone of the stick to the given value
* @param[in] value New stick modifier zone
*/
void JoyControlStick::setModifierZone(int value)
{
value = std::min(abs(value), GlobalVariables::JoyAxis::AXISMAX);
if ((value != m_modifier_zone) && (value < maxZone) && (value > deadZone))
{
m_modifier_zone = value;
emit modifierZoneChanged(value);
emit propertyUpdated();
}
}
/**
* @brief Inverts the direction of the modifier zone of the stick.
* @param[in] value True if the zone should be inverted, false otherwise.
*/
void JoyControlStick::setModifierZoneInverted(bool value)
{
if (value != m_modifier_zone_inverted)
{
m_modifier_zone_inverted = value;
emit modifierZoneChanged(m_modifier_zone);
emit propertyUpdated();
}
}
/**
* @brief Check if the stick is calibrated
* @returns True if both axes of the stick are calibrated, false otherwise.
*/
bool JoyControlStick::isCalibrated() const { return axisX->isCalibrated() && axisY->isCalibrated(); }
/**
* @brief Resets the calibration of both stick axes back to uncalibrated state.
*/
void JoyControlStick::resetCalibration()
{
axisX->resetCalibration();
axisY->resetCalibration();
}
/**
* @brief Reads the calibration values of both stick axes
* @param[out] offsetX Offset value "a" for X axis
* @param[out] gainX Gain value "b" for X axis
* @param[out] offsetY Offset value "a" for Y axis
* @param[out] gainY Gain value "b" for Y axis
*/
void JoyControlStick::getCalibration(double *offsetX, double *gainX, double *offsetY, double *gainY) const
{
axisX->getCalibration(offsetX, gainX);
axisY->getCalibration(offsetY, gainY);
}
/**
* @brief Sets the axis calibration values and sets the calibration flag.
* Calibrated value is calculated by the formula "a+b*x".
* @param[in] offsetX Offset value "a" for X axis
* @param[in] gainX Gain value "b" for X axis
* @param[in] offsetY Offset value "a" for Y axis
* @param[in] gainY Gain value "b" for Y axis
*/
void JoyControlStick::setCalibration(double offsetX, double gainX, double offsetY, double gainY)
{
axisX->setCalibration(offsetX, gainX);
axisY->setCalibration(offsetY, gainY);
}
/**
* @brief Set the diagonal range value for a stick.
* @param Value between 1 - 90.
*/
void JoyControlStick::setDiagonalRange(int value)
{
if (value < 1)
value = 1;
else if (value > 90)
value = 90;
if (value != diagonalRange)
{
diagonalRange = value;
emit diagonalRangeChanged(value);
emit propertyUpdated();
}
}
/**
* @brief Take a XML stream and set the stick and direction button properties
* according to the values contained within the stream.
* @param QXmlStreamReader instance that will be used to read property values.
*/
void JoyControlStick::readConfig(QXmlStreamReader *xml)
{
if (xml->isStartElement() && (xml->name() == "stick"))
{
xml->readNextStartElement();
while (!xml->atEnd() && (!xml->isEndElement() && (xml->name() != "stick")))
{
if ((xml->name() == "deadZone") && xml->isStartElement())
{
QString temptext = xml->readElementText();
int tempchoice = temptext.toInt();
this->setDeadZone(tempchoice);
} else if ((xml->name() == "maxZone") && xml->isStartElement())
{
QString temptext = xml->readElementText();
int tempchoice = temptext.toInt();
this->setMaxZone(tempchoice);
} else if ((xml->name() == "modifierZone") && xml->isStartElement())
{
QString temptext = xml->readElementText();
int tempchoice = temptext.toInt();
setModifierZone(tempchoice);
} else if ((xml->name() == "modifierZoneInverted") && xml->isStartElement())
{
QString temptext = xml->readElementText();
int tempchoice = temptext.toInt();
setModifierZoneInverted(tempchoice);
} else if ((xml->name() == "diagonalRange") && xml->isStartElement())
{
QString temptext = xml->readElementText();
int tempchoice = temptext.toInt();
this->setDiagonalRange(tempchoice);
} else if ((xml->name() == "mode") && xml->isStartElement())
{
QString temptext = xml->readElementText();
if (temptext == "eight-way")
{
this->setJoyMode(EightWayMode);
} else if (temptext == "four-way")
{
this->setJoyMode(FourWayCardinal);
} else if (temptext == "diagonal")
{
this->setJoyMode(FourWayDiagonal);
}
} else if ((xml->name() == "squareStick") && xml->isStartElement())
{
int tempchoice = xml->readElementText().toInt();
if ((tempchoice > 0) && (tempchoice <= 100))
this->setCircleAdjust(tempchoice / 100.0);
} else if ((xml->name() == GlobalVariables::JoyControlStickButton::xmlName) && xml->isStartElement())
{
int index = xml->attributes().value("index").toString().toInt();
JoyControlStickButton *button = buttons.value(static_cast<JoyStickDirections>(index));
QPointer<JoyButtonXml> joyButtonXml = new JoyButtonXml(button);
if (button != nullptr)
joyButtonXml->readConfig(xml);
else
xml->skipCurrentElement();
if (!joyButtonXml.isNull())
delete joyButtonXml;
} else if ((xml->name() == GlobalVariables::JoyControlStickModifierButton::xmlName) && xml->isStartElement())
{
JoyButtonXml *joyButtonXml = new JoyButtonXml(modifierButton);
joyButtonXml->readConfig(xml);
} else if ((xml->name() == "stickDelay") && xml->isStartElement())
{
QString temptext = xml->readElementText();
int tempchoice = temptext.toInt();
this->setStickDelay(tempchoice);
} else
{
xml->skipCurrentElement();
}
xml->readNextStartElement();
}
}
}
/**
* @brief Write the status of the properties of a stick and direction buttons
* to an XML stream.
* @param QXmlStreamWriter instance that will be used to write a profile.
*/
void JoyControlStick::writeConfig(QXmlStreamWriter *xml)
{
if (!isDefault())
{
xml->writeStartElement("stick");
xml->writeAttribute("index", QString::number(index + 1));
if (deadZone != GlobalVariables::JoyControlStick::DEFAULTDEADZONE)
xml->writeTextElement("deadZone", QString::number(deadZone));
if (maxZone != GlobalVariables::JoyControlStick::DEFAULTMAXZONE)
xml->writeTextElement("maxZone", QString::number(maxZone));
if (m_modifier_zone != GlobalVariables::JoyControlStick::DEFAULTMODIFIERZONE)
xml->writeTextElement("modifierZone", QString::number(m_modifier_zone));
if (m_modifier_zone_inverted != GlobalVariables::JoyControlStick::DEFAULTMODIFIERZONEINVERTED)
xml->writeTextElement("modifierZoneInverted", QString::number(m_modifier_zone_inverted));
if ((currentMode == StandardMode || currentMode == EightWayMode) &&
(diagonalRange != GlobalVariables::JoyControlStick::DEFAULTDIAGONALRANGE))
{
xml->writeTextElement("diagonalRange", QString::number(diagonalRange));
}
switch (currentMode)
{
case EightWayMode:
xml->writeTextElement("mode", "eight-way");
break;
case FourWayCardinal:
xml->writeTextElement("mode", "four-way");
break;
case FourWayDiagonal:
xml->writeTextElement("mode", "diagonal");
break;
default:
break;
}
if (circle > GlobalVariables::JoyControlStick::DEFAULTCIRCLE)
xml->writeTextElement("squareStick", QString::number(circle * 100));
if (stickDelay > GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY)
xml->writeTextElement("stickDelay", QString::number(stickDelay));
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
JoyButtonXml *joyButtonXml = new JoyButtonXml(button);
joyButtonXml->writeConfig(xml);
delete joyButtonXml;
joyButtonXml = nullptr;
}
if (!modifierButton->isDefault())
{
JoyButtonXml *joyButtonXmlModif = new JoyButtonXml(modifierButton);
joyButtonXmlModif->writeConfig(xml);
}
xml->writeEndElement();
}
}
/**
* @brief Reset all the properties of the stick direction buttons and the
* stick modifier button.
*/
void JoyControlStick::resetButtons()
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyButton *button = iter.next().value();
if (button != nullptr)
button->reset();
}
if (modifierButton != nullptr)
modifierButton->reset();
}
/**
* @brief Get a pointer to the stick direction button for the desired
* direction.
* @param Value of the direction of the stick.
* @return Pointer to the stick direction button for the stick
* direction.
*/
JoyControlStickButton *JoyControlStick::getDirectionButton(JoyStickDirections direction)
{
JoyControlStickButton *button = buttons.value(direction);
return button;
}
/**
* @brief Used to calculate the distance value that should be used for mouse
* movement.
* @param button
* @return Distance factor that should be used for mouse movement
*/
double JoyControlStick::calculateMouseDirectionalDistance(JoyControlStickButton *button)
{
double finalDistance = 0.0;
switch (currentDirection)
{
case StickUp: {
finalDistance = calculateYDistanceFromDeadZone(true);
break;
}
case StickRightUp: {
if ((activeButton1 != nullptr) && (activeButton1 == button))
{
finalDistance = calculateXDistanceFromDeadZone(true);
} else if ((activeButton2 != nullptr) && (activeButton2 == button))
{
finalDistance = calculateYDistanceFromDeadZone(true);
} else if ((activeButton3 != nullptr) && (activeButton3 == button))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
}
break;
}
case StickRight: {
finalDistance = calculateXDistanceFromDeadZone(true);
break;
}
case StickRightDown: {
if ((activeButton1 != nullptr) && (activeButton1 == button))
{
finalDistance = calculateXDistanceFromDeadZone(true);
} else if ((activeButton2 != nullptr) && (activeButton2 == button))
{
finalDistance = calculateYDistanceFromDeadZone(true);
} else if ((activeButton3 != nullptr) && (activeButton3 == button))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
}
break;
}
case StickDown: {
finalDistance = calculateYDistanceFromDeadZone(true);
break;
}
case StickLeftDown: {
if ((activeButton1 != nullptr) && (activeButton1 == button))
{
finalDistance = calculateXDistanceFromDeadZone(true);
} else if ((activeButton2 != nullptr) && (activeButton2 == button))
{
finalDistance = calculateYDistanceFromDeadZone(true);
} else if ((activeButton3 != nullptr) && (activeButton3 == button))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
}
break;
}
case StickLeft: {
finalDistance = calculateXDistanceFromDeadZone(true);
break;
}
case StickLeftUp: {
if ((activeButton1 != nullptr) && (activeButton1 == button))
{
finalDistance = calculateXDistanceFromDeadZone(true);
} else if ((activeButton2 != nullptr) && (activeButton2 == button))
{
finalDistance = calculateYDistanceFromDeadZone(true);
} else if ((activeButton3 != nullptr) && (activeButton3 == button))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
}
break;
}
default:
break;
}
return finalDistance;
}
double JoyControlStick::calculateLastMouseDirectionalDistance(JoyControlStickButton *button)
{
double finalDistance = 0.0;
JoyStickDirections direction =
calculateStickDirection(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue());
if ((direction == StickUp) && (button->getJoyNumber() == static_cast<int>(StickUp)))
{
if (axisY->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true);
}
} else if (direction == StickRightUp)
{
if (button->getJoyNumber() == static_cast<int>(StickRight))
{
if (axisX->getLastKnownThrottleValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickUp))
{
if (axisY->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickRightUp))
{
if ((axisX->getLastKnownThrottleValue() <= 0) || (axisY->getLastKnownThrottleValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
}
} else if ((direction == StickRight) && (button->getJoyNumber() == static_cast<int>(StickRight)))
{
if (axisX->getLastKnownThrottleValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true);
}
} else if (direction == StickRightDown)
{
if (button->getJoyNumber() == static_cast<int>(StickRight))
{
if (axisX->getLastKnownThrottleValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickDown))
{
if (axisY->getLastKnownThrottleValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickRightDown))
{
if ((axisX->getLastKnownThrottleValue() <= 0) || (axisY->getLastKnownThrottleValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
}
} else if (direction == StickDown && (button->getJoyNumber() == static_cast<int>(StickDown)))
{
if (axisY->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true);
}
} else if (direction == StickLeftDown)
{
if (button->getJoyNumber() == static_cast<int>(StickLeft))
{
if (axisX->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickDown))
{
if (axisY->getLastKnownThrottleValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickLeftDown))
{
if ((axisX->getLastKnownThrottleValue() >= 0) || (axisY->getLastKnownThrottleValue() <= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
}
} else if ((direction == StickLeft) && (button->getJoyNumber() == static_cast<int>(StickLeft)))
{
if (axisX->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue(), true);
}
} else if (direction == StickLeftUp)
{
if (button->getJoyNumber() == static_cast<int>(StickLeft))
{
if (axisX->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickUp))
{
if (axisY->getLastKnownThrottleValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue(), true);
}
} else if (button->getJoyNumber() == static_cast<int>(StickLeftUp))
{
if ((axisX->getLastKnownThrottleValue() >= 0) || (axisY->getLastKnownThrottleValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
}
}
return finalDistance;
}
double JoyControlStick::calculateLastDirectionalDistance()
{
double finalDistance = 0.0;
JoyStickDirections direction =
calculateStickDirection(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue());
switch (direction)
{
case StickUp: {
if (!(axisX->getLastKnownThrottleValue() >= 0))
{
finalDistance =
calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue());
}
break;
}
case StickRightUp: {
if (!(axisY->getLastKnownThrottleValue() <= 0) && !(axisY->getLastKnownThrottleValue() >= 0))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
break;
}
case StickRight: {
if (!(axisX->getLastKnownThrottleValue() <= 0))
{
finalDistance =
calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue());
}
break;
}
case StickRightDown: {
if (!(axisY->getLastKnownThrottleValue() <= 0) && !(axisY->getLastKnownThrottleValue() <= 0))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
break;
}
case StickDown: {
if (!(axisY->getLastKnownThrottleValue() <= 0))
{
finalDistance =
calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue());
}
break;
}
case StickLeftDown: {
if (!(axisY->getLastKnownThrottleValue() >= 0) && !(axisY->getLastKnownThrottleValue() <= 0))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
break;
}
case StickLeft: {
if (!(axisX->getLastKnownThrottleValue() >= 0))
{
finalDistance =
calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(), axisY->getLastKnownThrottleValue());
}
break;
}
case StickLeftUp: {
if (!(axisY->getLastKnownThrottleValue() >= 0) && !(axisY->getLastKnownThrottleValue() >= 0))
{
finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
axisY->getLastKnownThrottleValue());
}
break;
}
default:
break;
}
return finalDistance;
}
double JoyControlStick::calculateLastAccelerationDirectionalDistance()
{
double finalDistance = 0.0;
switch (currentDirection)
{
case StickUp: {
if (!(axisX->getLastKnownRawValue() >= 0))
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
break;
}
case StickRightUp: {
if (!(axisY->getLastKnownRawValue() <= 0) && !(axisY->getLastKnownRawValue() >= 0))
finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
break;
}
case StickRight: {
if (!(axisX->getLastKnownRawValue() <= 0))
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
break;
}
case StickRightDown: {
if (!(axisY->getLastKnownRawValue() <= 0) && !(axisY->getLastKnownRawValue() <= 0))
finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
break;
}
case StickDown: {
if (!(axisY->getLastKnownRawValue() <= 0))
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
break;
}
case StickLeftDown: {
if (!(axisY->getLastKnownRawValue() >= 0) && !(axisY->getLastKnownRawValue() <= 0))
finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
break;
}
case StickLeft: {
if (!(axisX->getLastKnownRawValue() >= 0))
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
break;
}
case StickLeftUp: {
if (!(axisY->getLastKnownRawValue() >= 0) && !(axisY->getLastKnownRawValue() >= 0))
finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
break;
}
default:
break;
}
return finalDistance;
}
/**
* @brief Used to calculate the distance value that should be used for keyboard
* events and distance slots
* @return Distance factor that should be used for keyboard events and
* distance slots
*/
double JoyControlStick::calculateDirectionalDistance()
{
double finalDistance = 0.0;
switch (currentDirection)
{
case StickUp: {
finalDistance = calculateYDistanceFromDeadZone();
break;
}
case StickRightUp: {
finalDistance = getDistanceFromDeadZone();
break;
}
case StickRight: {
finalDistance = calculateXDistanceFromDeadZone();
break;
}
case StickRightDown: {
finalDistance = getDistanceFromDeadZone();
break;
}
case StickDown: {
finalDistance = calculateYDistanceFromDeadZone();
break;
}
case StickLeftDown: {
finalDistance = getDistanceFromDeadZone();
break;
}
case StickLeft: {
finalDistance = calculateXDistanceFromDeadZone();
break;
}
case StickLeftUp: {
finalDistance = getDistanceFromDeadZone();
break;
}
default:
break;
}
return finalDistance;
}
/**
* @brief Get the value for the currently active stick direction.
* @return Value of the corresponding active stick direction.
*/
JoyControlStick::JoyStickDirections JoyControlStick::getCurrentDirection() { return currentDirection; }
/**
* @brief Get the value for the corresponding X axis.
* @return X axis value.
*/
int JoyControlStick::getXCoordinate() { return axisX->getCurrentRawValue(); }
/**
* @brief Get the value for the corresponding Y axis.
* @return Y axis value.
*/
int JoyControlStick::getYCoordinate() { return axisY->getCurrentRawValue(); }
int JoyControlStick::getCircleXCoordinate()
{
int axisXValue = axisX->getCurrentRawValue();
int axisYValue = axisX->getCurrentRawValue();
if (this->circle > 0.0)
axisXValue = calculateCircleXValue(axisXValue, axisYValue);
return axisXValue;
}
int JoyControlStick::getCircleYCoordinate()
{
int axisXValue = axisX->getCurrentRawValue();
int axisYValue = axisY->getCurrentRawValue();
if (this->circle > 0.0)
axisYValue = calculateCircleYValue(axisXValue, axisYValue);
return axisYValue;
}
int JoyControlStick::calculateCircleXValue(int axisXValue, int axisYValue)
{
int value = axisXValue;
if (this->circle > 0.0)
{
int axis1Value = axisXValue;
int axis2Value = axisYValue;
double angle2 = atan2(axis1Value, -axis2Value);
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
double squareStickFull = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFull - 1) * circle + 1;
value = (circleStickFull > 1.0) ? floor((axisXValue / circleStickFull) + 0.5) : value;
}
return value;
}
int JoyControlStick::calculateCircleYValue(int axisXValue, int axisYValue)
{
int value = axisYValue;
if (this->circle > 0.0)
{
int axis1Value = axisXValue;
int axis2Value = axisYValue;
double angle2 = atan2(axis1Value, -axis2Value);
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
double squareStickFull = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFull - 1) * circle + 1;
value = (circleStickFull > 1.0) ? floor((axisYValue / circleStickFull) + 0.5) : value;
}
return value;
}
QList<double> JoyControlStick::getDiagonalZoneAngles()
{
QList<double> anglesList;
int diagonalAngle = diagonalRange;
double cardinalAngle = (360 - (diagonalAngle * 4)) / 4.0;
double initialLeft = 360 - ((cardinalAngle) / 2.0);
double initialRight = ((cardinalAngle) / 2.0);
double upRightInitial = initialRight;
double rightInitial = upRightInitial + diagonalAngle;
double downRightInitial = rightInitial + cardinalAngle;
double downInitial = downRightInitial + diagonalAngle;
double downLeftInitial = downInitial + cardinalAngle;
double leftInitial = downLeftInitial + diagonalAngle;
double upLeftInitial = leftInitial + cardinalAngle;
anglesList.append(initialLeft);
anglesList.append(initialRight);
anglesList.append(upRightInitial);
anglesList.append(rightInitial);
anglesList.append(downRightInitial);
anglesList.append(downInitial);
anglesList.append(downLeftInitial);
anglesList.append(leftInitial);
anglesList.append(upLeftInitial);
return anglesList;
}
QList<int> JoyControlStick::getFourWayCardinalZoneAngles()
{
QList<int> anglesList;
int zoneRange = 90;
int rightInitial = 45;
int downInitial = rightInitial + zoneRange;
int leftInitial = downInitial + zoneRange;
int upInitial = leftInitial + zoneRange;
anglesList.append(rightInitial);
anglesList.append(downInitial);
anglesList.append(leftInitial);
anglesList.append(upInitial);
return anglesList;
}
QList<int> JoyControlStick::getFourWayDiagonalZoneAngles()
{
QList<int> anglesList;
int zoneRange = 90;
int upRightInitial = 0;
int downRightInitial = zoneRange;
int downLeftInitial = downRightInitial + zoneRange;
int upLeftInitial = downLeftInitial + zoneRange;
anglesList.append(upRightInitial);
anglesList.append(downRightInitial);
anglesList.append(downLeftInitial);
anglesList.append(upLeftInitial);
return anglesList;
}
QHash<JoyControlStick::JoyStickDirections, JoyControlStickButton *> *JoyControlStick::getButtons() { return &buttons; }
JoyAxis *JoyControlStick::getAxisX() { return axisX; }
JoyAxis *JoyControlStick::getAxisY() { return axisY; }
void JoyControlStick::replaceXAxis(JoyAxis *axis)
{
if (axis->getParentSet() == axisY->getParentSet())
{
axisX->removeControlStick();
this->axisX = axis;
this->axisX->setControlStick(this);
}
}
void JoyControlStick::replaceYAxis(JoyAxis *axis)
{
if (axis->getParentSet() == axisX->getParentSet())
{
axisY->removeControlStick();
this->axisY = axis;
this->axisY->setControlStick(this);
}
}
void JoyControlStick::replaceAxes(JoyAxis *axisX, JoyAxis *axisY)
{
if (axisX->getParentSet() == axisY->getParentSet())
{
this->axisX->removeControlStick();
this->axisY->removeControlStick();
this->axisX = axisX;
this->axisY = axisY;
this->axisX->setControlStick(this);
this->axisY->setControlStick(this);
}
}
void JoyControlStick::setJoyMode(JoyMode mode)
{
currentMode = mode;
emit joyModeChanged();
emit propertyUpdated();
}
JoyControlStick::JoyMode JoyControlStick::getJoyMode() { return currentMode; }
void JoyControlStick::releaseButtonEvents()
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->joyEvent(false, true);
}
}
bool JoyControlStick::isDefault()
{
bool value = true;
value = value && (deadZone == GlobalVariables::JoyControlStick::DEFAULTDEADZONE);
value = value && (maxZone == GlobalVariables::JoyControlStick::DEFAULTMAXZONE);
value = value && (m_modifier_zone == GlobalVariables::JoyControlStick::DEFAULTMODIFIERZONE);
value = value && (m_modifier_zone_inverted == GlobalVariables::JoyControlStick::DEFAULTMODIFIERZONEINVERTED);
value = value && (diagonalRange == GlobalVariables::JoyControlStick::DEFAULTDIAGONALRANGE);
value = value && (currentMode == DEFAULTMODE);
value = value && qFuzzyCompare(circle, GlobalVariables::JoyControlStick::DEFAULTCIRCLE);
value = value && (stickDelay == GlobalVariables::JoyControlStick::DEFAULTSTICKDELAY);
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
value = value && (button->isDefault());
}
if (modifierButton != nullptr)
value = value && modifierButton->isDefault();
return value;
}
void JoyControlStick::setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setMouseMode(mode);
}
}
bool JoyControlStick::hasSameButtonsMouseMode()
{
bool result = true;
JoyButton::JoyMouseMovementMode initialMode = JoyButton::MouseCursor;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
initialMode = button->getMouseMode();
while (++iter != temphash.cend())
{
button = iter.value();
JoyButton::JoyMouseMovementMode temp = button->getMouseMode();
if (temp != initialMode)
{
result = false;
break;
}
}
return result;
}
JoyButton::JoyMouseMovementMode JoyControlStick::getButtonsPresetMouseMode()
{
JoyButton::JoyMouseMovementMode resultMode = JoyButton::MouseCursor;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return resultMode;
JoyControlStickButton *button = iter.value();
resultMode = button->getMouseMode();
while (++iter != temphash.cend())
{
button = iter.value();
JoyButton::JoyMouseMovementMode temp = button->getMouseMode();
if (temp != resultMode)
{
resultMode = JoyButton::MouseCursor;
break;
}
}
return resultMode;
}
void JoyControlStick::setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setMouseCurve(mouseCurve);
}
}
bool JoyControlStick::hasSameButtonsMouseCurve()
{
bool result = true;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
JoyButton::JoyMouseCurve initialCurve = button->getMouseCurve();
while (++iter != temphash.cend())
{
button = iter.value();
JoyButton::JoyMouseCurve temp = button->getMouseCurve();
if (temp != initialCurve)
{
result = false;
break;
}
}
return result;
}
JoyButton::JoyMouseCurve JoyControlStick::getButtonsPresetMouseCurve()
{
JoyButton::JoyMouseCurve resultCurve = JoyButton::LinearCurve;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return resultCurve;
JoyControlStickButton *button = iter.value();
resultCurve = button->getMouseCurve();
while (++iter != temphash.cend())
{
button = iter.value();
JoyButton::JoyMouseCurve temp = button->getMouseCurve();
if (temp != resultCurve)
{
resultCurve = JoyButton::LinearCurve;
break;
}
}
return resultCurve;
}
void JoyControlStick::setButtonsSpringWidth(int value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setSpringWidth(value);
}
}
void JoyControlStick::setButtonsSpringHeight(int value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setSpringHeight(value);
}
}
int JoyControlStick::getButtonsPresetSpringWidth()
{
int presetSpringWidth = 0;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return presetSpringWidth;
JoyControlStickButton *button = iter.value();
presetSpringWidth = button->getSpringWidth();
while (++iter != temphash.cend())
{
button = iter.value();
int temp = button->getSpringWidth();
if (temp != presetSpringWidth)
{
presetSpringWidth = 0;
break;
}
}
return presetSpringWidth;
}
int JoyControlStick::getButtonsPresetSpringHeight()
{
int presetSpringHeight = 0;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return presetSpringHeight;
JoyControlStickButton *button = iter.value();
presetSpringHeight = button->getSpringHeight();
while (++iter != temphash.cend())
{
button = iter.value();
int temp = button->getSpringHeight();
if (temp != presetSpringHeight)
{
presetSpringHeight = 0;
break;
}
}
return presetSpringHeight;
}
void JoyControlStick::setButtonsSensitivity(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setSensitivity(value);
}
}
double JoyControlStick::getButtonsPresetSensitivity()
{
double presetSensitivity = 1.0;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return presetSensitivity;
JoyControlStickButton *button = iter.value();
presetSensitivity = button->getSensitivity();
while (++iter != temphash.cend())
{
button = iter.value();
double temp = button->getSensitivity();
if (!qFuzzyCompare(temp, presetSensitivity))
{
presetSensitivity = 1.0;
break;
}
}
return presetSensitivity;
}
QHash<JoyControlStick::JoyStickDirections, JoyControlStickButton *> JoyControlStick::getApplicableButtons()
{
QHash<JoyStickDirections, JoyControlStickButton *> temphash;
if ((currentMode == StandardMode) || (currentMode == EightWayMode) || (currentMode == FourWayCardinal))
{
temphash.insert(StickUp, buttons.value(StickUp));
temphash.insert(StickDown, buttons.value(StickDown));
temphash.insert(StickLeft, buttons.value(StickLeft));
temphash.insert(StickRight, buttons.value(StickRight));
}
if ((currentMode == EightWayMode) || (currentMode == FourWayDiagonal))
{
temphash.insert(StickLeftUp, buttons.value(StickLeftUp));
temphash.insert(StickRightUp, buttons.value(StickRightUp));
temphash.insert(StickRightDown, buttons.value(StickRightDown));
temphash.insert(StickLeftDown, buttons.value(StickLeftDown));
}
return temphash;
}
void JoyControlStick::setStickName(QString tempName)
{
if ((tempName.length() <= 20) && (tempName != stickName))
{
stickName = tempName;
emit stickNameChanged();
// emit propertyUpdated();
}
}
QString JoyControlStick::getStickName() { return stickName; }
void JoyControlStick::setButtonsWheelSpeedX(int value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setWheelSpeed(value, 'X');
}
}
void JoyControlStick::setButtonsWheelSpeedY(int value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setWheelSpeed(value, 'Y');
}
}
/**
* @brief Get pointer to the set that a stick belongs to.
* @return Pointer to the set that a stick belongs to.
*/
SetJoystick *JoyControlStick::getParentSet()
{
SetJoystick *temp = nullptr;
if (axisX != nullptr)
temp = axisX->getParentSet();
else if (axisY != nullptr)
temp = axisY->getParentSet();
return temp;
}
/**
* @brief Activate a stick direction button.
* @param Stick direction button that will be activated.
* @param [out] Pointer to the currently active button.
* @param Should set changing routines be ignored.
*/
void JoyControlStick::performButtonPress(JoyControlStickButton *eventbutton, JoyControlStickButton *&activebutton,
bool ignoresets)
{
activebutton = eventbutton;
eventbutton->joyEvent(true, ignoresets);
}
/**
* @brief Stick direction button to release.
* @param Stick direction button that will be released.
* @param Should set changing routines be ignored.
*/
void JoyControlStick::performButtonRelease(JoyControlStickButton *&eventbutton, bool ignoresets)
{
eventbutton->joyEvent(false, ignoresets);
eventbutton = nullptr;
}
/**
* @brief Determine which stick direction buttons should be active for a
* standard mode stick.
* @param [out] Pointer to an X axis stick direction button that should be active.
* @param [out] Pointer to a Y axis stick direction button that should be active.
*/
void JoyControlStick::determineStandardModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2)
{
double bearing = calculateBearing();
QList<double> anglesList = getDiagonalZoneAngles();
double initialLeft = anglesList.value(0);
double initialRight = anglesList.value(1);
double upRightInitial = anglesList.value(2);
double rightInitial = anglesList.value(3);
double downRightInitial = anglesList.value(4);
double downInitial = anglesList.value(5);
double downLeftInitial = anglesList.value(6);
double leftInitial = anglesList.value(7);
double upLeftInitial = anglesList.value(8);
if ((bearing <= initialRight) || (bearing >= initialLeft))
{
currentDirection = StickUp;
eventbutton2 = buttons.value(StickUp);
} else if ((bearing >= upRightInitial) && (bearing < rightInitial))
{
currentDirection = StickRightUp;
eventbutton1 = buttons.value(StickRight);
eventbutton2 = buttons.value(StickUp);
} else if ((bearing >= rightInitial) && (bearing < downRightInitial))
{
currentDirection = StickRight;
eventbutton1 = buttons.value(StickRight);
} else if ((bearing >= downRightInitial) && (bearing < downInitial))
{
currentDirection = StickRightDown;
eventbutton1 = buttons.value(StickRight);
eventbutton2 = buttons.value(StickDown);
} else if ((bearing >= downInitial) && (bearing < downLeftInitial))
{
currentDirection = StickDown;
eventbutton2 = buttons.value(StickDown);
} else if ((bearing >= downLeftInitial) && (bearing < leftInitial))
{
currentDirection = StickLeftDown;
eventbutton1 = buttons.value(StickLeft);
eventbutton2 = buttons.value(StickDown);
} else if ((bearing >= leftInitial) && (bearing < upLeftInitial))
{
currentDirection = StickLeft;
eventbutton1 = buttons.value(StickLeft);
} else if ((bearing >= upLeftInitial) && (bearing < initialLeft))
{
currentDirection = StickLeftUp;
eventbutton1 = buttons.value(StickLeft);
eventbutton2 = buttons.value(StickUp);
}
}
/**
* @brief Determine which stick direction button should be active for a 8 way
* mode stick.
* @param [out] Pointer to an X axis stick direction button that should be active.
* @param [out] Pointer to a Y axis stick direction button that should be active.
* @param [out] Pointer to a diagonal stick direction button that should be active.
*/
void JoyControlStick::determineEightWayModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2,
JoyControlStickButton *&eventbutton3)
{
double bearing = calculateBearing();
QList<double> anglesList = getDiagonalZoneAngles();
double initialLeft = anglesList.value(0);
double initialRight = anglesList.value(1);
double upRightInitial = anglesList.value(2);
double rightInitial = anglesList.value(3);
double downRightInitial = anglesList.value(4);
double downInitial = anglesList.value(5);
double downLeftInitial = anglesList.value(6);
double leftInitial = anglesList.value(7);
double upLeftInitial = anglesList.value(8);
if ((bearing <= initialRight) || (bearing >= initialLeft))
{
currentDirection = StickUp;
eventbutton2 = buttons.value(StickUp);
} else if ((bearing >= upRightInitial) && (bearing < rightInitial))
{
currentDirection = StickRightUp;
eventbutton3 = buttons.value(StickRightUp);
} else if ((bearing >= rightInitial) && (bearing < downRightInitial))
{
currentDirection = StickRight;
eventbutton1 = buttons.value(StickRight);
} else if ((bearing >= downRightInitial) && (bearing < downInitial))
{
currentDirection = StickRightDown;
eventbutton3 = buttons.value(StickRightDown);
} else if ((bearing >= downInitial) && (bearing < downLeftInitial))
{
currentDirection = StickDown;
eventbutton2 = buttons.value(StickDown);
} else if ((bearing >= downLeftInitial) && (bearing < leftInitial))
{
currentDirection = StickLeftDown;
eventbutton3 = buttons.value(StickLeftDown);
} else if ((bearing >= leftInitial) && (bearing < upLeftInitial))
{
currentDirection = StickLeft;
eventbutton1 = buttons.value(StickLeft);
} else if ((bearing >= upLeftInitial) && (bearing < initialLeft))
{
currentDirection = StickLeftUp;
eventbutton3 = buttons.value(StickLeftUp);
}
}
/**
* @brief Determine which cardinal stick direction button should be active
* when using a four way cardinal stick.
* @param [out] Pointer to an X axis stick direction button that should be active.
* @param [out] Pointer to a Y axis stick direction button that should be active.
*/
void JoyControlStick::determineFourWayCardinalEvent(JoyControlStickButton *&eventbutton1,
JoyControlStickButton *&eventbutton2)
{
double bearing = calculateBearing();
QList<int> anglesList = getFourWayCardinalZoneAngles();
int rightInitial = anglesList.value(0);
int downInitial = anglesList.value(1);
int leftInitial = anglesList.value(2);
int upInitial = anglesList.value(3);
if ((bearing < rightInitial) || (bearing >= upInitial))
{
currentDirection = StickUp;
eventbutton2 = buttons.value(StickUp);
} else if ((bearing >= rightInitial) && (bearing < downInitial))
{
currentDirection = StickRight;
eventbutton1 = buttons.value(StickRight);
} else if ((bearing >= downInitial) && (bearing < leftInitial))
{
currentDirection = StickDown;
eventbutton2 = buttons.value(StickDown);
} else if ((bearing >= leftInitial) && (bearing < upInitial))
{
currentDirection = StickLeft;
eventbutton1 = buttons.value(StickLeft);
}
}
/**
* @brief Determine which stick direction button should be active when using 4 way
* diagonal mode.
* @param [out] pointer to a diagonal stick direction button that should be active.
*/
void JoyControlStick::determineFourWayDiagonalEvent(JoyControlStickButton *&eventbutton3)
{
double bearing = calculateBearing();
QList<int> anglesList = getFourWayDiagonalZoneAngles();
int upRightInitial = anglesList.value(0);
int downRightInitial = anglesList.value(1);
int downLeftInitial = anglesList.value(2);
int upLeftInitial = anglesList.value(3);
if ((bearing >= upRightInitial) && (bearing < downRightInitial))
{
currentDirection = StickRightUp;
eventbutton3 = buttons.value(StickRightUp);
} else if ((bearing >= downRightInitial) && (bearing < downLeftInitial))
{
currentDirection = StickRightDown;
eventbutton3 = buttons.value(StickRightDown);
} else if ((bearing >= downLeftInitial) && (bearing < upLeftInitial))
{
currentDirection = StickLeftDown;
eventbutton3 = buttons.value(StickLeftDown);
} else if (bearing >= upLeftInitial)
{
currentDirection = StickLeftUp;
eventbutton3 = buttons.value(StickLeftUp);
}
}
/**
* @brief Find the current stick direction based on a Standard mode stick.
* @return Current direction the stick is positioned.
*/
JoyControlStick::JoyStickDirections JoyControlStick::determineStandardModeDirection()
{
return determineStandardModeDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
JoyControlStick::JoyStickDirections JoyControlStick::determineStandardModeDirection(int axisXValue, int axisYValue)
{
JoyStickDirections result = StickCentered;
double bearing = calculateBearing(axisXValue, axisYValue);
QList<double> anglesList = getDiagonalZoneAngles();
int initialLeft = anglesList.value(0);
int initialRight = anglesList.value(1);
int upRightInitial = anglesList.value(2);
int rightInitial = anglesList.value(3);
int downRightInitial = anglesList.value(4);
int downInitial = anglesList.value(5);
int downLeftInitial = anglesList.value(6);
int leftInitial = anglesList.value(7);
int upLeftInitial = anglesList.value(8);
if ((bearing <= initialRight) || (bearing >= initialLeft))
{
result = StickUp;
} else if ((bearing >= upRightInitial) && (bearing < rightInitial))
{
result = StickRightUp;
} else if ((bearing >= rightInitial) && (bearing < downRightInitial))
{
result = StickRight;
} else if ((bearing >= downRightInitial) && (bearing < downInitial))
{
result = StickRightDown;
} else if ((bearing >= downInitial) && (bearing < downLeftInitial))
{
result = StickDown;
} else if ((bearing >= downLeftInitial) && (bearing < leftInitial))
{
result = StickLeftDown;
} else if ((bearing >= leftInitial) && (bearing < upLeftInitial))
{
result = StickLeft;
} else if ((bearing >= upLeftInitial) && (bearing < initialLeft))
{
result = StickLeftUp;
}
return result;
}
/**
* @brief Find the current stick direction based on a Eight Way mode stick.
* @return Current direction the stick is positioned.
*/
JoyControlStick::JoyStickDirections JoyControlStick::determineEightWayModeDirection()
{
return determineStandardModeDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
JoyControlStick::JoyStickDirections JoyControlStick::determineEightWayModeDirection(int axisXValue, int axisYValue)
{
return determineStandardModeDirection(axisXValue, axisYValue);
}
/**
* @brief Find the current stick direction based on a Four Way Cardinal mode
* stick.
* @return Current direction the stick is positioned.
*/
JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayCardinalDirection()
{
return determineFourWayCardinalDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayCardinalDirection(int axisXValue, int axisYValue)
{
JoyStickDirections result = StickCentered;
double bearing = calculateBearing(axisXValue, axisYValue);
QList<int> anglesList = getFourWayCardinalZoneAngles();
int rightInitial = anglesList.value(0);
int downInitial = anglesList.value(1);
int leftInitial = anglesList.value(2);
int upInitial = anglesList.value(3);
if ((bearing < rightInitial) || (bearing >= upInitial))
{
result = StickUp;
} else if ((bearing >= rightInitial) && (bearing < downInitial))
{
result = StickRight;
} else if ((bearing >= downInitial) && (bearing < leftInitial))
{
result = StickDown;
} else if ((bearing >= leftInitial) && (bearing < upInitial))
{
result = StickLeft;
}
return result;
}
/**
* @brief Find the current stick direction based on a Four Way Diagonal mode
* stick.
* @return Current direction the stick is positioned.
*/
JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayDiagonalDirection()
{
return determineFourWayDiagonalDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
JoyControlStick::JoyStickDirections JoyControlStick::determineFourWayDiagonalDirection(int axisXValue, int axisYValue)
{
JoyStickDirections result = StickCentered;
double bearing = calculateBearing(axisXValue, axisYValue);
QList<int> anglesList = getFourWayDiagonalZoneAngles();
int upRightInitial = anglesList.value(0);
int downRightInitial = anglesList.value(1);
int downLeftInitial = anglesList.value(2);
int upLeftInitial = anglesList.value(3);
if ((bearing >= upRightInitial) && (bearing < downRightInitial))
{
result = StickRightUp;
} else if ((bearing >= downRightInitial) && (bearing < downLeftInitial))
{
result = StickRightDown;
} else if ((bearing >= downLeftInitial) && (bearing < upLeftInitial))
{
result = StickLeftDown;
} else if (bearing >= upLeftInitial)
{
result = StickLeftUp;
}
return result;
}
/**
* @brief Calculate the current direction of the stick based on the values
* of the X and Y axes and the current mode of the stick.
* @return Current direction the stick is positioned.
*/
JoyControlStick::JoyStickDirections JoyControlStick::calculateStickDirection()
{
return calculateStickDirection(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
JoyControlStick::JoyStickDirections JoyControlStick::calculateStickDirection(int axisXValue, int axisYValue)
{
JoyStickDirections result = StickCentered;
switch (currentMode)
{
case StandardMode: {
result = determineStandardModeDirection(axisXValue, axisYValue);
break;
}
case EightWayMode: {
result = determineEightWayModeDirection(axisXValue, axisYValue);
break;
}
case FourWayCardinal: {
result = determineFourWayCardinalDirection(axisXValue, axisYValue);
break;
}
case FourWayDiagonal: {
result = determineFourWayDiagonalDirection(axisXValue, axisYValue);
break;
}
}
return result;
}
void JoyControlStick::establishPropertyUpdatedConnection()
{
connect(this, &JoyControlStick::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited);
}
void JoyControlStick::disconnectPropertyUpdatedConnection()
{
disconnect(this, &JoyControlStick::propertyUpdated, getParentSet()->getInputDevice(), &InputDevice::profileEdited);
}
/**
* @brief Check all stick buttons and see if any have slots assigned.
* @return Status of whether any stick button has a slot assigned.
*/
bool JoyControlStick::hasSlotsAssigned()
{
bool hasSlots = false;
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyButton *button = iter.next().value();
if (button != nullptr)
{
if (button->getAssignedSlots()->count() > 0)
{
hasSlots = true;
iter.toBack();
}
}
}
return hasSlots;
}
void JoyControlStick::setButtonsSpringRelativeStatus(bool value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setSpringRelativeStatus(value);
}
}
bool JoyControlStick::isRelativeSpring()
{
bool relative = false;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return relative;
JoyControlStickButton *button = iter.value();
relative = button->isRelativeSpring();
while (++iter != temphash.cend())
{
button = iter.value();
bool temp = button->isRelativeSpring();
if (temp != relative)
{
relative = false;
break;
}
}
return relative;
}
/**
* @brief Copy slots from all stick buttons and properties from a stick
* onto another.
* @param JoyControlStick object to be modified.
*/
void JoyControlStick::copyAssignments(JoyControlStick *destStick)
{
destStick->reset();
destStick->deadZone = deadZone;
destStick->maxZone = maxZone;
destStick->m_modifier_zone = m_modifier_zone;
destStick->m_modifier_zone_inverted = m_modifier_zone_inverted;
destStick->diagonalRange = diagonalRange;
destStick->currentDirection = currentDirection;
destStick->currentMode = currentMode;
destStick->stickName = stickName;
destStick->circle = circle;
destStick->stickDelay = stickDelay;
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(destStick->buttons);
while (iter.hasNext())
{
JoyControlStickButton *destButton = iter.next().value();
if (destButton != nullptr)
{
JoyControlStickButton *sourceButton = buttons.value(destButton->getDirection());
if (sourceButton != nullptr)
sourceButton->copyAssignments(destButton);
}
}
JoyControlStickModifierButton *destModifierButton = destStick->getModifierButton();
if ((modifierButton != nullptr) && (destModifierButton != nullptr))
{
modifierButton->copyAssignments(destModifierButton);
}
if (!destStick->isDefault())
emit propertyUpdated();
}
/**
* @brief Set the percentage of the outer square that should be ignored
* when performing the final axis calculations.
* @param Percentage represented by the range of 0.0 - 1.0.
*/
void JoyControlStick::setCircleAdjust(double circle)
{
if ((circle >= 0.0) && (circle <= 1.0))
{
this->circle = circle;
emit circleAdjustChange(circle);
emit propertyUpdated();
}
}
/**
* @brief Get the current percentage of the outer square that should be ignored
* when performing the final axis calculations.
* @return Percentage represented by the range of 0.0 - 1.0.
*/
double JoyControlStick::getCircleAdjust() { return circle; }
/**
* @brief Slot called when directionDelayTimer has timed out. The method will
* call createDeskEvent.
*/
void JoyControlStick::stickDirectionChangeEvent() { createDeskEvent(); }
void JoyControlStick::setStickDelay(int value)
{
if (((value >= 10) && (value <= 1000)) || (value == 0))
{
this->stickDelay = value;
emit stickDelayChanged(value);
emit propertyUpdated();
}
}
int JoyControlStick::getStickDelay() { return stickDelay; }
void JoyControlStick::setButtonsEasingDuration(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(buttons);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setEasingDuration(value);
}
}
double JoyControlStick::getButtonsEasingDuration()
{
double result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
result = button->getEasingDuration();
while (++iter != temphash.cend())
{
button = iter.value();
double temp = button->getEasingDuration();
if (!qFuzzyCompare(temp, result))
{
result = GlobalVariables::JoyButton::DEFAULTEASINGDURATION;
break;
}
}
return result;
}
JoyControlStickModifierButton *JoyControlStick::getModifierButton() { return modifierButton; }
void JoyControlStick::queueJoyEvent(bool ignoresets)
{
Q_UNUSED(ignoresets)
pendingStickEvent = true;
}
bool JoyControlStick::hasPendingEvent() { return pendingStickEvent; }
void JoyControlStick::activatePendingEvent()
{
if (pendingStickEvent)
{
bool ignoresets = false;
joyEvent(ignoresets);
pendingStickEvent = false;
}
}
void JoyControlStick::clearPendingEvent() { pendingStickEvent = false; }
void JoyControlStick::setButtonsExtraAccelerationStatus(bool enabled)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
button->setExtraAccelerationStatus(enabled);
}
}
bool JoyControlStick::getButtonsExtraAccelerationStatus()
{
bool result = false;
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
{
bool temp = button->isExtraAccelerationEnabled();
if (!temp)
{
result = false;
iter.toBack();
} else
{
result = temp;
}
}
}
return result;
}
void JoyControlStick::setButtonsExtraAccelerationMultiplier(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
button->setExtraAccelerationMultiplier(value);
}
}
double JoyControlStick::getButtonsExtraAccelerationMultiplier()
{
double result = GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getExtraAccelerationMultiplier();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
double temp = button->getExtraAccelerationMultiplier();
if (!qFuzzyCompare(temp, result))
{
result = GlobalVariables::JoyButton::DEFAULTEXTRACCELVALUE;
break;
}
}
}
return result;
}
void JoyControlStick::setButtonsStartAccelerationMultiplier(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
button->setStartAccelMultiplier(value);
}
}
double JoyControlStick::getButtonsStartAccelerationMultiplier()
{
double result = GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getStartAccelMultiplier();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
double temp = button->getStartAccelMultiplier();
if (!qFuzzyCompare(temp, result))
{
result = GlobalVariables::JoyButton::DEFAULTSTARTACCELMULTIPLIER;
break;
}
}
}
return result;
}
void JoyControlStick::setButtonsMinAccelerationThreshold(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
button->setMinAccelThreshold(value);
}
}
double JoyControlStick::getButtonsMinAccelerationThreshold()
{
double result = GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getMinAccelThreshold();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
double temp = button->getMinAccelThreshold();
if (!qFuzzyCompare(temp, result))
{
result = GlobalVariables::JoyButton::DEFAULTMINACCELTHRESHOLD;
break;
}
}
}
return result;
}
void JoyControlStick::setButtonsMaxAccelerationThreshold(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
button->setMaxAccelThreshold(value);
}
}
double JoyControlStick::getButtonsMaxAccelerationThreshold()
{
double result = GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getMaxAccelThreshold();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
double temp = button->getMaxAccelThreshold();
if (!qFuzzyCompare(temp, result))
{
result = GlobalVariables::JoyButton::DEFAULTMAXACCELTHRESHOLD;
break;
}
}
}
return result;
}
void JoyControlStick::setButtonsAccelerationExtraDuration(double value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
button->setAccelExtraDuration(value);
}
}
double JoyControlStick::getButtonsAccelerationEasingDuration()
{
double result = GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getAccelExtraDuration();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
double temp = button->getAccelExtraDuration();
if (!qFuzzyCompare(temp, result))
{
result = GlobalVariables::JoyButton::DEFAULTACCELEASINGDURATION;
break;
}
}
}
return result;
}
void JoyControlStick::setButtonsSpringDeadCircleMultiplier(int value)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
{
button->setSpringDeadCircleMultiplier(value);
}
}
}
int JoyControlStick::getButtonsSpringDeadCircleMultiplier()
{
int result = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getSpringDeadCircleMultiplier();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
int temp = button->getSpringDeadCircleMultiplier();
if (temp != result)
{
result = GlobalVariables::JoyButton::DEFAULTSPRINGRELEASERADIUS;
break;
}
}
}
return result;
}
double JoyControlStick::calculateAccelerationDistance(JoyControlStickButton *button)
{
double finalDistance = 0.0;
switch (currentDirection)
{
case StickUp: {
if (axisY->getCurrentRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
}
break;
}
case StickRightUp: {
switch (button->getJoyNumber())
{
case 1:
if (axisY->getCurrentRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
}
break;
case 2:
if ((axisX->getCurrentRawValue() <= 0) || (axisY->getCurrentRawValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
break;
case 3:
if (axisX->getCurrentRawValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
}
break;
}
break;
}
case StickRight: {
if (axisX->getCurrentRawValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
}
break;
}
case StickRightDown: {
switch (button->getJoyNumber())
{
case 3:
if (axisX->getCurrentRawValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
}
break;
case 4:
if ((axisX->getCurrentRawValue() <= 0) || (axisY->getCurrentRawValue() <= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
break;
case 5:
if (axisY->getCurrentRawValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
}
break;
}
break;
}
case StickDown: {
if (axisY->getCurrentRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
}
break;
}
case StickLeftDown: {
switch (button->getJoyNumber())
{
case 5:
if (axisY->getCurrentRawValue() < 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
}
break;
case 6:
if ((axisX->getCurrentRawValue() >= 0) || (axisY->getCurrentRawValue() <= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
break;
case 7:
if (axisX->getCurrentRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
}
break;
}
break;
}
case StickLeft: {
if (axisX->getCurrentRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
}
break;
}
case StickLeftUp: {
switch (button->getJoyNumber())
{
case 1:
if (axisY->getCurrentRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
}
break;
case 7:
if (axisX->getCurrentRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
}
break;
case 8:
if ((axisX->getCurrentRawValue() >= 0) || (axisY->getCurrentRawValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
break;
}
break;
}
default:
break;
}
return finalDistance;
}
// TODO: Maybe change method name.
double JoyControlStick::calculateLastAccelerationButtonDistance(JoyControlStickButton *button)
{
double finalDistance = 0.0;
switch (currentDirection)
{
case StickUp: {
if (axisY->getLastKnownRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
}
break;
}
case StickRightUp: {
switch (button->getJoyNumber())
{
case StickRight: {
if (axisX->getLastKnownRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
}
break;
}
case StickUp: {
if (axisY->getLastKnownRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
}
break;
}
case StickRightUp: {
if ((axisX->getLastKnownRawValue() <= 0) || (axisY->getLastKnownRawValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
}
break;
}
}
break;
}
case StickRight: {
if (axisX->getLastKnownRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
}
break;
}
case StickRightDown: {
switch (button->getJoyNumber())
{
case StickRight: {
if (axisX->getLastKnownRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
}
break;
}
case StickDown: {
if (axisY->getLastKnownRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
}
break;
}
case StickRightDown: {
if ((axisX->getLastKnownRawValue() <= 0) || (axisY->getLastKnownRawValue() <= 0))
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
}
break;
}
}
break;
}
case StickDown: {
if (axisY->getLastKnownRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
}
break;
}
case StickLeftDown: {
switch (button->getJoyNumber())
{
case 7: {
if (axisX->getLastKnownRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
}
break;
}
case 5: {
if (axisY->getLastKnownRawValue() <= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
}
break;
}
case 6: {
if ((axisX->getLastKnownRawValue() >= 0) || (axisY->getLastKnownRawValue() <= 0))
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
}
break;
}
}
break;
}
case StickLeft: {
if (axisX->getLastKnownRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
}
break;
}
case StickLeftUp: {
switch (button->getJoyNumber())
{
case 7: {
if (axisX->getLastKnownRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
}
break;
}
case 1: {
if (axisY->getLastKnownRawValue() >= 0)
{
finalDistance = 0.0;
} else
{
finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
}
break;
}
case 8: {
if ((axisX->getLastKnownRawValue() >= 0) || (axisY->getLastKnownRawValue() >= 0))
{
finalDistance = 0.0;
} else
{
finalDistance =
calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
}
break;
}
}
break;
}
default:
break;
}
return finalDistance;
}
double JoyControlStick::calculateXAxisDistance(int axisXValue)
{
int axis1Value = axisXValue;
double distance = axis1Value / static_cast<double>(maxZone);
if (distance < -1.0)
distance = -1.0;
else if (distance > 1.0)
distance = 1.0;
qDebug() << "DISTANCE: " << distance;
return distance;
}
double JoyControlStick::calculateYAxisDistance(int axisYValue)
{
int axis2Value = axisYValue;
double distance = axis2Value / static_cast<double>(maxZone);
if (distance < -1.0)
distance = -1.0;
else if (distance > 1.0)
distance = 1.0;
return distance;
}
double JoyControlStick::calculateEightWayDiagonalDistanceFromDeadZone()
{
return calculateEightWayDiagonalDistanceFromDeadZone(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
}
double JoyControlStick::calculateEightWayDiagonalDistanceFromDeadZone(int axisXValue, int axisYValue)
{
double distance = 0.0;
double radius = getDistanceFromDeadZone(axisXValue, axisYValue);
double bearing = calculateBearing(axisXValue, axisYValue);
int relativeBearing = static_cast<int>(bearing) % 90;
int diagonalAngle = relativeBearing;
if (relativeBearing > 45)
diagonalAngle = 90 - relativeBearing;
distance = radius * (diagonalAngle / 45.0);
return distance;
}
double JoyControlStick::calculateEightWayDiagonalDistance(int axisXValue, int axisYValue)
{
double distance = 0.0;
double radius = getRadialDistance(axisXValue, axisYValue);
double bearing = calculateBearing(axisXValue, axisYValue);
int relativeBearing = static_cast<int>(bearing) % 90;
int diagonalAngle = relativeBearing;
if (relativeBearing > 45)
diagonalAngle = 90 - relativeBearing;
distance = radius * (diagonalAngle / 45.0);
return distance;
}
double JoyControlStick::calculateXDiagonalDeadZone(int axisXValue, int axisYValue)
{
double diagonalDeadZone = 0.0;
JoyStickDirections direction = calculateStickDirection(axisXValue, axisYValue);
if (diagonalRange < 90)
{
if ((direction == StickRightUp) || (direction == StickRight))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(3);
double mindeadX = fabs(deadZone * cos(maxangle * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadX;
} else if ((direction == StickRightDown) || (direction == StickDown))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(5);
double mindeadX = fabs(deadZone * cos((maxangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadX;
} else if ((direction == StickLeftDown) || (direction == StickLeft))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(7);
double mindeadX = fabs(deadZone * cos((maxangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadX;
} else if ((direction == StickLeftUp) || (direction == StickUp))
{
QList<double> tempangles = getDiagonalZoneAngles();
double maxangle = tempangles.at(1);
double mindeadX = fabs(deadZone * cos((maxangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadX;
} else
{
diagonalDeadZone = 0.0;
}
} else
{
diagonalDeadZone = 0.0;
}
return diagonalDeadZone;
}
double JoyControlStick::calculateYDiagonalDeadZone(int axisXValue, int axisYValue)
{
double diagonalDeadZone = 0.0;
JoyStickDirections direction = calculateStickDirection(axisXValue, axisYValue);
if (diagonalRange < 90)
{
if ((direction == StickRightUp) || (direction == StickUp))
{
QList<double> tempangles = getDiagonalZoneAngles();
double minangle = tempangles.at(1);
double mindeadY = fabs(deadZone * sin(minangle * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadY;
} else if ((direction == StickRightDown) || (direction == StickRight))
{
QList<double> tempfuck = getDiagonalZoneAngles();
double minangle = tempfuck.at(4);
double mindeadY = fabs(deadZone * sin((minangle - 90.0) * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadY;
} else if ((direction == StickLeftDown) || (direction == StickDown))
{
QList<double> tempangles = getDiagonalZoneAngles();
double minangle = tempangles.at(6);
double mindeadY = fabs(deadZone * sin((minangle - 180.0) * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadY;
} else if ((direction == StickLeftUp) || (direction == StickLeft))
{
QList<double> tempangles = getDiagonalZoneAngles();
double minangle = tempangles.at(8);
double mindeadY = fabs(deadZone * sin((minangle - 270.0) * GlobalVariables::JoyControlStick::PI / 180.0));
diagonalDeadZone = mindeadY;
} else
{
diagonalDeadZone = 0.0;
}
} else
{
diagonalDeadZone = 0.0;
}
return diagonalDeadZone;
}
double JoyControlStick::getSpringDeadCircleX()
{
double result = 0.0;
double angle2 = 0.0;
int axis1Value = 0;
int axis2Value = 0;
if ((axisX->getCurrentRawValue() == 0) && (axisY->getCurrentRawValue() == 0))
{
// Stick moved back to absolute center. Use previously available values
// to find stick angle.
angle2 = atan2(axisX->getLastKnownRawValue(), -axisY->getLastKnownRawValue());
axis1Value = axisX->getLastKnownRawValue();
axis2Value = axisY->getLastKnownRawValue();
} else
{
// Use current axis values to find stick angle.
angle2 = atan2(axisX->getCurrentRawValue(), -axisY->getCurrentRawValue());
axis1Value = axisX->getCurrentRawValue();
axis2Value = axisY->getCurrentRawValue();
}
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
int deadX = abs(floor(deadZone * ang_sin + 0.5));
double diagonalDeadX = calculateXDiagonalDeadZone(axis1Value, axis2Value);
double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
double adjustedDeadXZone = circleStickFull > 1.0 ? (deadX / circleStickFull) : deadX;
double finalDeadZoneX = adjustedDeadXZone - diagonalDeadX;
double maxRange = static_cast<double>(deadZone) - diagonalDeadX;
if (maxRange != 0.0)
result = finalDeadZoneX / maxRange;
return result;
}
double JoyControlStick::getSpringDeadCircleY()
{
double result = 0.0;
double angle2 = 0.0;
int axis1Value = 0;
int axis2Value = 0;
if ((axisX->getCurrentRawValue() == 0) && (axisY->getCurrentRawValue() == 0))
{
// Stick moved back to absolute center. Use previously available values
// to find stick angle.
angle2 = atan2(axisX->getLastKnownRawValue(), -axisY->getLastKnownRawValue());
axis1Value = axisX->getLastKnownRawValue();
axis2Value = axisY->getLastKnownRawValue();
} else
{
// Use current axis values to find stick angle.
angle2 = atan2(axisX->getCurrentRawValue(), -axisY->getCurrentRawValue());
axis1Value = axisX->getCurrentRawValue();
axis2Value = axisY->getCurrentRawValue();
}
double ang_sin = sin(angle2);
double ang_cos = cos(angle2);
int deadY = abs(floor(deadZone * ang_cos + 0.5));
double diagonalDeadY = calculateYDiagonalDeadZone(axis1Value, axis2Value);
double squareStickFullPhi = qMin(ang_sin != 0.0 ? 1 / fabs(ang_sin) : 2, ang_cos != 0.0 ? 1 / fabs(ang_cos) : 2);
double circle = this->circle;
double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
double adjustedDeadYZone = (circleStickFull > 1.0) ? (deadY / circleStickFull) : deadY;
double finalDeadZoneY = adjustedDeadYZone - diagonalDeadY;
double maxRange = static_cast<double>(deadZone) - diagonalDeadY;
if (maxRange != 0.0)
result = finalDeadZoneY / maxRange;
return result;
}
void JoyControlStick::setButtonsExtraAccelCurve(JoyButton::JoyExtraAccelerationCurve curve)
{
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(getApplicableButtons());
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
if (button != nullptr)
{
button->setExtraAccelerationCurve(curve);
}
}
}
JoyButton::JoyExtraAccelerationCurve JoyControlStick::getButtonsExtraAccelerationCurve()
{
JoyButton::JoyExtraAccelerationCurve result = JoyButton::LinearAccelCurve;
QHash<JoyStickDirections, JoyControlStickButton *> temphash = getApplicableButtons();
auto iter = temphash.cbegin();
if (iter == temphash.cend())
return result;
JoyControlStickButton *button = iter.value();
if (button != nullptr)
result = button->getExtraAccelerationCurve();
while (++iter != temphash.cend())
{
button = iter.value();
if (button != nullptr)
{
JoyButton::JoyExtraAccelerationCurve temp = button->getExtraAccelerationCurve();
if (temp != result)
{
result = JoyButton::LinearAccelCurve;
break;
}
}
}
return result;
}
void JoyControlStick::setDirButtonsUpdateInitAccel(JoyControlStick::JoyStickDirections direction, bool state)
{
QHash<JoyStickDirections, JoyControlStickButton *> apphash = getButtonsForDirection(direction);
// QVERIFY(apphash.isEmpty() == false);
QHashIterator<JoyStickDirections, JoyControlStickButton *> iter(apphash);
// QVERIFY(iter.hasNext() == true);
while (iter.hasNext())
{
JoyControlStickButton *button = iter.next().value();
button->setUpdateInitAccel(state);
}
}
QHash<JoyControlStick::JoyStickDirections, JoyControlStickButton *>
JoyControlStick::getButtonsForDirection(JoyControlStick::JoyStickDirections direction)
{
QHash<JoyStickDirections, JoyControlStickButton *> temphash;
switch (currentMode)
{
case StandardMode: {
if (direction & JoyControlStick::StickUp)
{
JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickUp);
temphash.insert(JoyControlStick::StickUp, button);
}
if (direction & JoyControlStick::StickRight)
{
JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickRight);
temphash.insert(JoyControlStick::StickRight, button);
}
if (direction & JoyControlStick::StickDown)
{
JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickDown);
temphash.insert(JoyControlStick::StickDown, button);
}
if (direction & JoyControlStick::StickLeft)
{
JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickLeft);
temphash.insert(JoyControlStick::StickLeft, button);
}
break;
}
case EightWayMode: {
if ((direction == JoyControlStick::StickUp) || (direction == JoyControlStick::StickDown) ||
(direction == JoyControlStick::StickLeft) || (direction == JoyControlStick::StickRight) ||
(direction == JoyControlStick::StickRightUp) || (direction == JoyControlStick::StickRightDown) ||
(direction == JoyControlStick::StickLeftDown) || (direction == JoyControlStick::StickLeftUp))
{
temphash.insert(direction, buttons.value(direction));
}
break;
}
case FourWayCardinal: {
if ((direction == JoyControlStick::StickUp) || (direction == JoyControlStick::StickDown) ||
(direction == JoyControlStick::StickLeft) || (direction == JoyControlStick::StickRight))
{
temphash.insert(direction, buttons.value(direction));
}
break;
}
case FourWayDiagonal: {
if ((direction == JoyControlStick::StickRightUp) || (direction == JoyControlStick::StickRightDown) ||
(direction == JoyControlStick::StickLeftDown) || (direction == JoyControlStick::StickLeftUp))
{
temphash.insert(direction, buttons.value(direction));
}
break;
}
}
return temphash;
}