1 /* antimicro Gamepad to KB+M event mapper
2  * Copyright (C) 2015 Travis Nickles <nickles.travis@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 //#include <QDebug>
19 #include <QHashIterator>
20 #include <QStringList>
21 #include <cmath>
22 
23 #include "joycontrolstick.h"
24 #include "inputdevice.h"
25 
26 // Define Pi here.
27 const double JoyControlStick::PI = acos(-1.0);
28 
29 // Set default values used for stick properties.
30 const int JoyControlStick::DEFAULTDEADZONE = 8000;
31 const int JoyControlStick::DEFAULTMAXZONE = JoyAxis::AXISMAXZONE;
32 const int JoyControlStick::DEFAULTDIAGONALRANGE = 45;
33 const JoyControlStick::JoyMode JoyControlStick::DEFAULTMODE = JoyControlStick::StandardMode;
34 const double JoyControlStick::DEFAULTCIRCLE = 0.0;
35 const unsigned int JoyControlStick::DEFAULTSTICKDELAY = 0;
36 
JoyControlStick(JoyAxis * axis1,JoyAxis * axis2,int index,int originset,QObject * parent)37 JoyControlStick::JoyControlStick(JoyAxis *axis1, JoyAxis *axis2,
38                                  int index, int originset, QObject *parent) :
39     QObject(parent)
40 {
41     this->axisX = axis1;
42     this->axisX->setControlStick(this);
43     this->axisY = axis2;
44     this->axisY->setControlStick(this);
45 
46     this->index = index;
47     this->originset = originset;
48     this->modifierButton = 0;
49     reset();
50 
51     populateButtons();
52 
53     directionDelayTimer.setSingleShot(true);
54 
55     connect(&directionDelayTimer, SIGNAL(timeout()), this, SLOT(stickDirectionChangeEvent()));
56 }
57 
~JoyControlStick()58 JoyControlStick::~JoyControlStick()
59 {
60     axisX->removeControlStick(false);
61     axisY->removeControlStick(false);
62 
63     deleteButtons();
64 }
65 
66 /**
67  * @brief Take the input value for the two axes that make up a stick and
68  *   activate the proper event based on the current values.
69  * @param Should set changing routines be ignored.
70  */
joyEvent(bool ignoresets)71 void JoyControlStick::joyEvent(bool ignoresets)
72 {
73     safezone = !inDeadZone();
74 
75     if (safezone && !isActive)
76     {
77         isActive = true;
78         emit active(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
79         if (ignoresets || stickDelay == 0)
80         {
81             if (directionDelayTimer.isActive())
82             {
83                 directionDelayTimer.stop();
84             }
85 
86             createDeskEvent(ignoresets);
87         }
88         else
89         {
90             if (!directionDelayTimer.isActive())
91             {
92                 directionDelayTimer.start(stickDelay);
93             }
94         }
95     }
96     else if (!safezone && isActive)
97     {
98         isActive = false;
99         emit released(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
100         if (ignoresets || stickDelay == 0)
101         {
102             if (directionDelayTimer.isActive())
103             {
104                 directionDelayTimer.stop();
105             }
106 
107             createDeskEvent(ignoresets);
108         }
109         else
110         {
111             if (!directionDelayTimer.isActive())
112             {
113                 directionDelayTimer.start(stickDelay);
114             }
115         }
116     }
117     else if (isActive)
118     {
119         if (ignoresets || stickDelay == 0)
120         {
121             if (directionDelayTimer.isActive())
122             {
123                 directionDelayTimer.stop();
124             }
125 
126             createDeskEvent(ignoresets);
127         }
128         else
129         {
130             JoyStickDirections pendingDirection = calculateStickDirection();
131             if (currentDirection != pendingDirection)
132             {
133                 if (!directionDelayTimer.isActive())
134                 {
135                     directionDelayTimer.start(stickDelay);
136                 }
137             }
138             else
139             {
140                 if (directionDelayTimer.isActive())
141                 {
142                     directionDelayTimer.stop();
143                 }
144 
145                 createDeskEvent(ignoresets);
146             }
147         }
148     }
149 
150     emit moved(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
151 
152     pendingStickEvent = false;
153 }
154 
155 /**
156  * @brief Check the current stick position to see if it lies in
157  *   the assigned dead zone.
158  * @return If stick position is in the assigned dead zone
159  */
inDeadZone()160 bool JoyControlStick::inDeadZone()
161 {
162     int axis1Value = axisX->getCurrentRawValue();
163     int axis2Value = axisY->getCurrentRawValue();
164 
165     unsigned int squareDist = static_cast<unsigned int>(axis1Value*axis1Value) +
166             static_cast<unsigned int>(axis2Value*axis2Value);
167 
168     return squareDist <= static_cast<unsigned int>(deadZone*deadZone);
169 }
170 
171 /**
172  * @brief Populate the virtual buttons assigned to an analog stick.
173  */
populateButtons()174 void JoyControlStick::populateButtons()
175 {
176     JoyControlStickButton *button = new JoyControlStickButton(this, StickUp,
177                                                               originset, getParentSet(), this);
178     buttons.insert(StickUp, button);
179 
180     button = new JoyControlStickButton(this, StickDown, originset,
181                                        getParentSet(), this);
182     buttons.insert(StickDown, button);
183 
184     button = new JoyControlStickButton(this, StickLeft, originset,
185                                        getParentSet(), this);
186     buttons.insert(StickLeft, button);
187 
188     button = new JoyControlStickButton(this, StickRight, originset,
189                                        getParentSet(), this);
190     buttons.insert(StickRight, button);
191 
192     button = new JoyControlStickButton(this, StickLeftUp, originset,
193                                        getParentSet(), this);
194     buttons.insert(StickLeftUp, button);
195 
196     button = new JoyControlStickButton(this, StickLeftDown, originset,
197                                        getParentSet(), this);
198     buttons.insert(StickLeftDown, button);
199 
200     button = new JoyControlStickButton(this, StickRightDown, originset,
201                                        getParentSet(), this);
202     buttons.insert(StickRightDown, button);
203 
204     button = new JoyControlStickButton(this, StickRightUp, originset,
205                                        getParentSet(), this);
206     buttons.insert(StickRightUp, button);
207 
208     modifierButton = new JoyControlStickModifierButton(this, originset,
209                                                        getParentSet(), this);
210 }
211 
212 /**
213  * @brief Get the assigned dead zone value.
214  * @return Assigned dead zone value
215  */
getDeadZone()216 int JoyControlStick::getDeadZone()
217 {
218     return deadZone;
219 }
220 
221 /**
222  * @brief Get the assigned diagonal range value.
223  * @return Assigned diagonal range.
224  */
getDiagonalRange()225 int JoyControlStick::getDiagonalRange()
226 {
227     return diagonalRange;
228 }
229 
230 /**
231  * @brief Find the position of the two stick axes, deactivate no longer used
232  *   stick direction button and then activate direction buttons for new
233  *   direction.
234  * @param Should set changing operations be ignored. Necessary in the middle
235  *   of a set change.
236  */
createDeskEvent(bool ignoresets)237 void JoyControlStick::createDeskEvent(bool ignoresets)
238 {
239     JoyControlStickButton *eventbutton1 = 0;
240     JoyControlStickButton *eventbutton2 = 0;
241     JoyControlStickButton *eventbutton3 = 0;
242 
243     if (safezone)
244     {
245         if (currentMode == StandardMode)
246         {
247             determineStandardModeEvent(eventbutton1, eventbutton2);
248         }
249         else if (currentMode == EightWayMode)
250         {
251             determineEightWayModeEvent(eventbutton1, eventbutton2, eventbutton3);
252         }
253         else if (currentMode == FourWayCardinal)
254         {
255             determineFourWayCardinalEvent(eventbutton1, eventbutton2);
256         }
257         else if (currentMode == FourWayDiagonal)
258         {
259             determineFourWayDiagonalEvent(eventbutton3);
260         }
261     }
262     else
263     {
264         currentDirection = StickCentered;
265     }
266 
267     /*
268      * Release any currently active stick buttons.
269      */
270     if (!eventbutton1 && activeButton1)
271     {
272         // Currently in deadzone. Disable currently active button.
273         performButtonRelease(activeButton1, ignoresets);
274     }
275     else if (eventbutton1 && activeButton1 && eventbutton1 != activeButton1)
276     {
277         // Deadzone skipped. Button for new event is not the currently
278         // active button. Disable the active button.
279         performButtonRelease(activeButton1, ignoresets);
280     }
281 
282     if (!eventbutton2 && activeButton2)
283     {
284         // Currently in deadzone. Disable currently active button.
285         performButtonRelease(activeButton2, ignoresets);
286     }
287     else if (eventbutton2 && activeButton2 && eventbutton2 != activeButton2)
288     {
289         // Deadzone skipped. Button for new event is not the currently
290         // active button. Disable the active button.
291         performButtonRelease(activeButton2, ignoresets);
292     }
293 
294     if (!eventbutton3 && activeButton3)
295     {
296         // Currently in deadzone. Disable currently active button.
297         performButtonRelease(activeButton3, ignoresets);
298     }
299     else if (eventbutton3 && activeButton3 && eventbutton3 != activeButton3)
300     {
301         // Deadzone skipped. Button for new event is not the currently
302         // active button. Disable the active button.
303         performButtonRelease(activeButton3, ignoresets);
304     }
305 
306     if (safezone)
307     {
308         // Activate modifier button before activating directional buttons.
309         // Value from the new stick event will be used to determine
310         // distance events.
311         modifierButton->joyEvent(true, ignoresets);
312     }
313     else
314     {
315         // Release modifier button after releasing directional buttons.
316         modifierButton->joyEvent(false, ignoresets);
317     }
318 
319     /*
320      * Enable stick buttons.
321      */
322     if (eventbutton1 && !activeButton1)
323     {
324         // There is no active button. Call joyEvent and set current
325         // button as active button
326         performButtonPress(eventbutton1, activeButton1, ignoresets);
327     }
328     else if (eventbutton1 && activeButton1 && eventbutton1 == activeButton1)
329     {
330         // Button is currently active. Just pass current value
331         performButtonPress(eventbutton1, activeButton1, ignoresets);
332     }
333 
334     if (eventbutton2 && !activeButton2)
335     {
336         // There is no active button. Call joyEvent and set current
337         // button as active button
338         performButtonPress(eventbutton2, activeButton2, ignoresets);
339     }
340     else if (eventbutton2 && activeButton2 && eventbutton2 == activeButton2)
341     {
342         // Button is currently active. Just pass current value
343         performButtonPress(eventbutton2, activeButton2, ignoresets);
344     }
345 
346     if (eventbutton3 && !activeButton3)
347     {
348         // There is no active button. Call joyEvent and set current
349         // button as active button
350         performButtonPress(eventbutton3, activeButton3, ignoresets);
351     }
352     else if (eventbutton3 && activeButton3 && eventbutton3 == activeButton3)
353     {
354         // Button is currently active. Just pass current value
355         performButtonPress(eventbutton3, activeButton3, ignoresets);
356     }
357 }
358 
359 /**
360  * @brief Calculate the bearing (in degrees) corresponding to the current
361  *   position of the X and Y axes of a stick.
362  * @return Bearing (in degrees)
363  */
calculateBearing()364 double JoyControlStick::calculateBearing()
365 {
366     return calculateBearing(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
367 }
368 
369 /**
370  * @brief Calculate the bearing (in degrees) corresponding to the
371  *   passed X and Y axes values associated with the stick.
372  * @param X axis value
373  * @param Y axis value
374  * @return Bearing (in degrees)
375  */
calculateBearing(int axisXValue,int axisYValue)376 double JoyControlStick::calculateBearing(int axisXValue, int axisYValue)
377 {
378     double finalAngle = 0.0;
379     int axis1Value = axisXValue;
380     int axis2Value = axisYValue;
381 
382     if (axis1Value == 0 && axis2Value == 0)
383     {
384         finalAngle = 0.0;
385     }
386     else
387     {
388         double temp1 = axis1Value;
389         double temp2 = axis2Value;
390 
391         double angle = (atan2(temp1, -temp2) * 180) / PI;
392 
393         if (axis1Value >= 0 && axis2Value <= 0)
394         {
395             // NE Quadrant
396             finalAngle = angle;
397         }
398         else if (axis1Value >= 0 && axis2Value >= 0)
399         {
400             // SE Quadrant (angle will be positive)
401             finalAngle = angle;
402         }
403         else if (axis1Value <= 0 && axis2Value >= 0)
404         {
405             // SW Quadrant (angle will be negative)
406             finalAngle = 360.0 + angle;
407         }
408         else if (axis1Value <= 0 && axis2Value <= 0)
409         {
410             // NW Quadrant (angle will be negative)
411             finalAngle = 360.0 + angle;
412         }
413     }
414 
415     return finalAngle;
416 }
417 
418 /**
419  * @brief Get current radial distance of the stick position past the assigned
420  *   dead zone.
421  * @return Distance percentage in the range of 0.0 - 1.0.
422  */
getDistanceFromDeadZone()423 double JoyControlStick::getDistanceFromDeadZone()
424 {
425     return getDistanceFromDeadZone(axisX->getCurrentRawValue(),
426                                    axisY->getCurrentRawValue());
427 }
428 
429 /**
430  * @brief Get radial distance of the stick position past the assigned dead zone
431  *   based on the passed X and Y axes values associated with the stick.
432  * @param X axis value
433  * @param Y axis value
434  * @return Distance percentage in the range of 0.0 - 1.0.
435  */
getDistanceFromDeadZone(int axisXValue,int axisYValue)436 double JoyControlStick::getDistanceFromDeadZone(int axisXValue, int axisYValue)
437 {
438     double distance = 0.0;
439 
440     int axis1Value = axisXValue;
441     int axis2Value = axisYValue;
442 
443     double angle2 = atan2(axis1Value, -axis2Value);
444     double ang_sin = sin(angle2);
445     double ang_cos = cos(angle2);
446 
447     unsigned int squared_dist = static_cast<unsigned int>(axis1Value*axis1Value)
448             + static_cast<unsigned int>(axis2Value*axis2Value);
449     unsigned int dist = sqrt(squared_dist);
450 
451     double squareStickFullPhi = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
452     double circle = this->circle;
453     double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
454 
455     double adjustedDist = circleStickFull > 1.0 ? (dist / circleStickFull) : dist;
456     double adjustedDeadZone = circleStickFull > 1.0 ? (deadZone / circleStickFull) : deadZone;
457 
458     distance = (adjustedDist - adjustedDeadZone)/(double)(maxZone - adjustedDeadZone);
459     distance = qBound(0.0, distance, 1.0);
460     return distance;
461 }
462 
463 /**
464  * @brief Get distance of the Y axis past the assigned dead zone.
465  * @param Should interpolation be performed along the diagonal regions.
466  * @return Distance percentage in the range of 0.0 - 1.0.
467  */
calculateYDistanceFromDeadZone(bool interpolate)468 double JoyControlStick::calculateYDistanceFromDeadZone(bool interpolate)
469 {
470     return calculateYDistanceFromDeadZone(axisX->getCurrentRawValue(),
471                                           axisY->getCurrentRawValue(),
472                                           interpolate);
473 }
474 
475 /**
476  * @brief Get distance of the Y axis past the assigned dead zone based
477  *   on the passed X and Y axis values for the analog stick.
478  * @param X axis value
479  * @param Y axis value
480  * @param Should interpolation be performed along the diagonal regions.
481  * @return Distance percentage in the range of 0.0 - 1.0.
482  */
calculateYDistanceFromDeadZone(int axisXValue,int axisYValue,bool interpolate)483 double JoyControlStick::calculateYDistanceFromDeadZone(int axisXValue,
484                                                        int axisYValue, bool interpolate)
485 {
486     double distance = 0.0;
487 
488     int axis1Value = axisXValue;
489     int axis2Value = axisYValue;
490     //unsigned int square_dist = (unsigned int)(axis1Value*axis1Value) + (unsigned int)(axis2Value*axis2Value);
491 
492     double angle2 = atan2(axis1Value, -axis2Value);
493     double ang_sin = sin(angle2);
494     double ang_cos = cos(angle2);
495 
496     int deadY = abs(floor(deadZone * ang_cos + 0.5));
497     //int axis2ValueCircleFull = (int)floor(JoyAxis::AXISMAX * fabs(ang_cos) + 0.5);
498     double squareStickFullPhi = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
499     double circle = this->circle;
500     double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
501     //double circleToSquareTest = axis2Value * squareStickFullPhi;
502 
503     double adjustedAxis2Value = circleStickFull > 1.0 ? (axis2Value / circleStickFull) : axis2Value;
504     double adjustedDeadYZone = circleStickFull > 1.0 ? (deadY / circleStickFull) : deadY;
505 
506     // Interpolation would return the correct value if diagonalRange is 90 but
507     // the routine gets skipped to save time.
508     if (interpolate && diagonalRange < 90)
509     {
510         JoyStickDirections direction = calculateStickDirection(axis1Value, axis2Value);
511         if (direction == StickRightUp || direction == StickUp)
512         {
513             QList<double> tempangles = getDiagonalZoneAngles();
514             double maxangle = tempangles.at(3);
515             double minangle = tempangles.at(1);
516             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
517             double mindeadY = fabs(square_dist * sin(minangle * PI / 180.0));
518             double currentDeadY = qMax(static_cast<double>(adjustedDeadYZone), mindeadY);
519             double maxRange = static_cast<double>(maxZone - currentDeadY);
520             double tempdist4 = 0.0;
521             if (maxRange != 0.0)
522             {
523                 tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
524             }
525 
526             distance = tempdist4;
527         }
528         else if (direction == StickRightDown || direction == StickRight)
529         {
530             QList<double> tempfuck = getDiagonalZoneAngles();
531             double maxangle = tempfuck.at(5);
532             double minangle = tempfuck.at(4);
533             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
534             double mindeadY = fabs(square_dist * sin((minangle - 90.0) * PI / 180.0));
535             double currentDeadY = qMax(static_cast<double>(adjustedDeadYZone), mindeadY);
536             double maxRange = static_cast<double>(maxZone - currentDeadY);
537             double tempdist4 = 0.0;
538             if (maxRange != 0.0)
539             {
540                 tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
541             }
542 
543             distance = tempdist4;
544         }
545         else if (direction == StickLeftDown || direction == StickDown)
546         {
547             QList<double> tempangles = getDiagonalZoneAngles();
548             double maxangle = tempangles.at(7);
549             double minangle = tempangles.at(6);
550             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
551             double mindeadY = fabs(square_dist * sin((minangle - 180.0) * PI / 180.0));
552             double currentDeadY = qMax(static_cast<double>(adjustedDeadYZone), mindeadY);
553             double maxRange = static_cast<double>(maxZone - currentDeadY);
554             double tempdist4 = 0.0;
555             if (maxRange != 0.0)
556             {
557                 tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
558             }
559 
560             distance = tempdist4;
561         }
562         else if (direction == StickLeftUp || direction == StickLeft)
563         {
564             QList<double> tempangles = getDiagonalZoneAngles();
565             double maxangle = tempangles.at(1);
566             double minangle = tempangles.at(8);
567             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
568             double mindeadY = fabs(square_dist * sin((minangle - 270.0) * PI / 180.0));
569             double currentDeadY = qMax(static_cast<double>(adjustedDeadYZone), mindeadY);
570             double maxRange = static_cast<double>(maxZone - currentDeadY);
571             double tempdist4 = 0.0;
572             if (maxRange != 0.0)
573             {
574                 tempdist4 = (fabs(adjustedAxis2Value) - currentDeadY) / maxRange;
575             }
576 
577             distance = tempdist4;
578         }
579         else
580         {
581             // Backup plan. Should not arrive here.
582             double maxRange = static_cast<double>(maxZone - adjustedDeadYZone);
583             double tempdist4 = 0.0;
584             if (maxRange != 0.0)
585             {
586                 tempdist4 = (fabs(adjustedAxis2Value) - adjustedDeadYZone) / maxRange;
587             }
588 
589             distance = tempdist4;
590         }
591     }
592     else
593     {
594         // No interpolation desired or diagonal range is 90 degrees.
595         double maxRange = static_cast<double>(maxZone - adjustedDeadYZone);
596         double tempdist4 = 0.0;
597         if (maxRange != 0.0)
598         {
599             tempdist4 = (fabs(adjustedAxis2Value) - adjustedDeadYZone) / maxRange;
600         }
601 
602         distance = tempdist4;
603     }
604 
605     distance = qBound(0.0, distance, 1.0);
606     return distance;
607 }
608 
609 /**
610  * @brief Get distance of the X axis past the assigned dead zone.
611  * @param Should interpolation be performed along the diagonal regions.
612  * @return Distance percentage in the range of 0.0 - 1.0.
613  */
calculateXDistanceFromDeadZone(bool interpolate)614 double JoyControlStick::calculateXDistanceFromDeadZone(bool interpolate)
615 {
616     return calculateXDistanceFromDeadZone(axisX->getCurrentRawValue(),
617                                           axisY->getCurrentRawValue(),
618                                           interpolate);
619 }
620 
621 /**
622  * @brief Get distance of the X axis past the assigned dead zone based
623  *   on the passed X and Y axis values for the analog stick.
624  * @param X axis value
625  * @param Y axis value
626  * @param Should interpolation be performed along the diagonal regions.
627  * @return Distance percentage in the range of 0.0 - 1.0.
628  */
calculateXDistanceFromDeadZone(int axisXValue,int axisYValue,bool interpolate)629 double JoyControlStick::calculateXDistanceFromDeadZone(int axisXValue,
630                                                        int axisYValue, bool interpolate)
631 {
632     double distance = 0.0;
633 
634     int axis1Value = axisXValue;
635     int axis2Value = axisYValue;
636     //unsigned int square_dist = (unsigned int)(axis1Value*axis1Value) + (unsigned int)(axis2Value*axis2Value);
637 
638     double angle2 = atan2(axis1Value, -axis2Value);
639     double ang_sin = sin(angle2);
640     double ang_cos = cos(angle2);
641 
642     int deadX = abs((int)floor(deadZone * ang_sin + 0.5));
643     //int axis1ValueCircleFull = (int)floor(JoyAxis::AXISMAX * fabs(ang_sin) + 0.5);
644     double squareStickFullPhi = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
645     double circle = this->circle;
646     double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
647     //double alternateStickFullValue = circleStickFull * abs(axis1ValueCircleFull);
648 
649     double adjustedAxis1Value = circleStickFull > 1.0 ? (axis1Value / circleStickFull) : axis1Value;
650     double adjustedDeadXZone = circleStickFull > 1.0 ? (deadX / circleStickFull) : deadX;
651 
652     // Interpolation would return the correct value if diagonalRange is 90 but
653     // the routine gets skipped to save time.
654     if (interpolate && diagonalRange < 90)
655     {
656         JoyStickDirections direction = calculateStickDirection(axis1Value, axis2Value);
657         if (direction == StickRightUp || direction == StickRight)
658         {
659             QList<double> tempangles = getDiagonalZoneAngles();
660             double maxangle = tempangles.at(3);
661             double minangle = tempangles.at(1);
662             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
663             double mindeadX = fabs(square_dist * cos(maxangle * PI / 180.0));
664             double currentDeadX = qMax(mindeadX, static_cast<double>(adjustedDeadXZone));
665             double maxRange = static_cast<double>(maxZone - currentDeadX);
666             double tempdist4 = 0.0;
667             if (maxRange != 0.0)
668             {
669                 tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
670             }
671 
672             distance = tempdist4;
673         }
674         else if (direction == StickRightDown || direction == StickDown)
675         {
676             QList<double> tempangles = getDiagonalZoneAngles();
677             double maxangle = tempangles.at(5);
678             double minangle = tempangles.at(4);
679             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
680             double mindeadX = fabs(square_dist * cos((maxangle - 90.0) * PI / 180.0));
681             double currentDeadX = qMax(mindeadX, static_cast<double>(adjustedDeadXZone));
682             double maxRange = static_cast<double>(maxZone - currentDeadX);
683             double tempdist4 = 0.0;
684             if (maxRange != 0.0)
685             {
686                 tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
687             }
688 
689             distance = tempdist4;
690         }
691         else if (direction == StickLeftDown || direction == StickLeft)
692         {
693             QList<double> tempangles = getDiagonalZoneAngles();
694             double maxangle = tempangles.at(7);
695             double minangle = tempangles.at(6);
696             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
697             double mindeadX = fabs(square_dist * cos((maxangle - 180.0) * PI / 180.0));
698             double currentDeadX = qMax(mindeadX, static_cast<double>(adjustedDeadXZone));
699             double maxRange = static_cast<double>(maxZone - currentDeadX);
700             double tempdist4 = 0.0;
701             if (maxRange != 0.0)
702             {
703                 tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
704             }
705 
706             distance = tempdist4;
707         }
708         else if (direction == StickLeftUp || direction == StickUp)
709         {
710             QList<double> tempangles = getDiagonalZoneAngles();
711             double maxangle = tempangles.at(1);
712             double minangle = tempangles.at(8);
713             double square_dist = getAbsoluteRawDistance(axis1Value, axis2Value);
714             double mindeadX = fabs(square_dist * cos((maxangle - 270.0) * PI / 180.0));
715             double currentDeadX = qMax(mindeadX, static_cast<double>(adjustedDeadXZone));
716             double maxRange = static_cast<double>(maxZone - currentDeadX);
717             double tempdist4 = 0.0;
718             if (maxRange != 0.0)
719             {
720                 tempdist4 = (fabs(adjustedAxis1Value) - currentDeadX) / maxRange;
721             }
722 
723             distance = tempdist4;
724         }
725         else
726         {
727             // Backup plan. Should not arrive here.
728             double maxRange = static_cast<double>(maxZone - adjustedDeadXZone);
729             double tempdist4 = 0.0;
730             if (maxRange != 0.0)
731             {
732                 tempdist4 = (fabs(adjustedAxis1Value) - adjustedDeadXZone) / maxRange;
733             }
734 
735             distance = tempdist4;
736         }
737     }
738     else
739     {
740         // No interpolation desired or diagonal range is 90 degrees.
741         double maxRange = static_cast<double>(maxZone - adjustedDeadXZone);
742         double tempdist4 = 0.0;
743         if (maxRange != 0.0)
744         {
745             tempdist4 = (fabs(adjustedAxis1Value) - adjustedDeadXZone) / maxRange;
746         }
747 
748         distance = tempdist4;
749     }
750 
751     distance = qBound(0.0, distance, 1.0);
752     return distance;
753 }
754 
755 
756 /**
757  * @brief Get the raw radial distance of the stick. Values will be between 0 - 32,767.
758  * @return Radial distance in the range of 0 - 32,767.
759  */
getAbsoluteRawDistance()760 double JoyControlStick::getAbsoluteRawDistance()
761 {
762     double temp = getAbsoluteRawDistance(axisX->getCurrentRawValue(),
763                                          axisY->getCurrentRawValue());
764     return temp;
765 }
766 
getAbsoluteRawDistance(int axisXValue,int axisYValue)767 double JoyControlStick::getAbsoluteRawDistance(int axisXValue, int axisYValue)
768 {
769     double distance = 0.0;
770 
771     int axis1Value = axisXValue;
772     int axis2Value = axisYValue;
773 
774     unsigned int square_dist = static_cast<unsigned int>(axis1Value*axis1Value) +
775             static_cast<unsigned int>(axis2Value*axis2Value);
776 
777     distance = sqrt(square_dist);
778     return distance;
779 }
780 
getNormalizedAbsoluteDistance()781 double JoyControlStick::getNormalizedAbsoluteDistance()
782 {
783     double distance = 0.0;
784 
785     int axis1Value = axisX->getCurrentRawValue();
786     int axis2Value = axisY->getCurrentRawValue();
787 
788     unsigned int square_dist = static_cast<unsigned int>(axis1Value*axis1Value)
789             + static_cast<unsigned int>(axis2Value*axis2Value);
790 
791     distance = sqrt(square_dist)/static_cast<double>(maxZone);
792     if (distance > 1.0)
793     {
794         distance = 1.0;
795     }
796     else if (distance < 0.0)
797     {
798         distance = 0.0;
799     }
800 
801     return distance;
802 }
803 
getRadialDistance(int axisXValue,int axisYValue)804 double JoyControlStick::getRadialDistance(int axisXValue, int axisYValue)
805 {
806     double distance = 0.0;
807 
808     int axis1Value = axisXValue;
809     int axis2Value = axisYValue;
810 
811     unsigned int square_dist = static_cast<unsigned int>(axis1Value*axis1Value)
812             + static_cast<unsigned int>(axis2Value*axis2Value);
813 
814     distance = sqrt(square_dist)/static_cast<double>(maxZone);
815     if (distance > 1.0)
816     {
817         distance = 1.0;
818     }
819     else if (distance < 0.0)
820     {
821         distance = 0.0;
822     }
823 
824     return distance;
825 }
826 
setIndex(int index)827 void JoyControlStick::setIndex(int index)
828 {
829     this->index = index;
830 }
831 
getIndex()832 int JoyControlStick::getIndex()
833 {
834     return index;
835 }
836 
getRealJoyIndex()837 int JoyControlStick::getRealJoyIndex()
838 {
839     return index + 1;
840 }
841 
getName(bool forceFullFormat,bool displayNames)842 QString JoyControlStick::getName(bool forceFullFormat, bool displayNames)
843 {
844     QString label = getPartialName(forceFullFormat, displayNames);
845 
846     label.append(": ");
847     QStringList tempList;
848     if (buttons.contains(StickUp))
849     {
850         JoyControlStickButton *button = buttons.value(StickUp);
851         if (!button->getButtonName().isEmpty())
852         {
853             tempList.append(button->getButtonName());
854         }
855         else
856         {
857             tempList.append(button->getSlotsSummary());
858         }
859     }
860 
861     if (buttons.contains(StickLeft))
862     {
863         JoyControlStickButton *button = buttons.value(StickLeft);
864         if (!button->getButtonName().isEmpty())
865         {
866             tempList.append(button->getButtonName());
867         }
868         else
869         {
870             tempList.append(button->getSlotsSummary());
871         }
872     }
873 
874     if (buttons.contains(StickDown))
875     {
876         JoyControlStickButton *button = buttons.value(StickDown);
877         if (!button->getButtonName().isEmpty())
878         {
879             tempList.append(button->getButtonName());
880         }
881         else
882         {
883             tempList.append(button->getSlotsSummary());
884         }
885     }
886 
887     if (buttons.contains(StickRight))
888     {
889         JoyControlStickButton *button = buttons.value(StickRight);
890         if (!button->getButtonName().isEmpty())
891         {
892             tempList.append(button->getButtonName());
893         }
894         else
895         {
896             tempList.append(button->getSlotsSummary());
897         }
898     }
899 
900     label.append(tempList.join(", "));
901     return label;
902 }
903 
getPartialName(bool forceFullFormat,bool displayNames)904 QString JoyControlStick::getPartialName(bool forceFullFormat, bool displayNames)
905 {
906     QString label;
907 
908     if (!stickName.isEmpty() && displayNames)
909     {
910         if (forceFullFormat)
911         {
912             label.append(tr("Stick")).append(" ");
913         }
914 
915         label.append(stickName);
916     }
917     else if (!defaultStickName.isEmpty())
918     {
919         if (forceFullFormat)
920         {
921             label.append(tr("Stick")).append(" ");
922         }
923 
924         label.append(defaultStickName);
925     }
926     else
927     {
928         label.append(tr("Stick")).append(" ");
929         label.append(QString::number(getRealJoyIndex()));
930     }
931 
932     return label;
933 }
934 
setDefaultStickName(QString tempname)935 void JoyControlStick::setDefaultStickName(QString tempname)
936 {
937     defaultStickName = tempname;
938     emit stickNameChanged();
939 }
940 
getDefaultStickName()941 QString JoyControlStick::getDefaultStickName()
942 {
943     return defaultStickName;
944 }
945 
getMaxZone()946 int JoyControlStick::getMaxZone()
947 {
948     return maxZone;
949 }
950 
getCurrentlyAssignedSet()951 int JoyControlStick::getCurrentlyAssignedSet()
952 {
953     return originset;
954 }
955 
reset()956 void JoyControlStick::reset()
957 {
958     deadZone = 8000;
959     maxZone = JoyAxis::AXISMAXZONE;
960     diagonalRange = 45;
961     isActive = false;
962     pendingStickEvent = false;
963 
964     /*if (activeButton1)
965     {
966         activeButton1->reset();
967     }
968     activeButton1 = 0;
969 
970     if (activeButton2)
971     {
972         activeButton2->reset();
973     }
974 
975     activeButton2 = 0;*/
976 
977     activeButton1 = 0;
978     activeButton2 = 0;
979     activeButton3 = 0;
980     safezone = false;
981     currentDirection = StickCentered;
982     currentMode = StandardMode;
983     stickName.clear();
984     circle = DEFAULTCIRCLE;
985     stickDelay = DEFAULTSTICKDELAY;
986     resetButtons();
987 }
988 
setDeadZone(int value)989 void JoyControlStick::setDeadZone(int value)
990 {
991     value = abs(value);
992     if (value > JoyAxis::AXISMAX)
993     {
994         value = JoyAxis::AXISMAX;
995     }
996 
997     if (value != deadZone && value < maxZone)
998     {
999         deadZone = value;
1000         emit deadZoneChanged(value);
1001         emit propertyUpdated();
1002     }
1003 }
1004 
setMaxZone(int value)1005 void JoyControlStick::setMaxZone(int value)
1006 {
1007     value = abs(value);
1008     if (value >= JoyAxis::AXISMAX)
1009     {
1010         value = JoyAxis::AXISMAX;
1011     }
1012 
1013     if (value != maxZone && value > deadZone)
1014     {
1015         maxZone = value;
1016         emit maxZoneChanged(value);
1017         emit propertyUpdated();
1018     }
1019 }
1020 
1021 /**
1022  * @brief Set the diagonal range value for a stick.
1023  * @param Value between 1 - 90.
1024  */
setDiagonalRange(int value)1025 void JoyControlStick::setDiagonalRange(int value)
1026 {
1027     if (value < 1)
1028     {
1029         value = 1;
1030     }
1031     else if (value > 90)
1032     {
1033         value = 90;
1034     }
1035 
1036     if (value != diagonalRange)
1037     {
1038         diagonalRange = value;
1039         emit diagonalRangeChanged(value);
1040         emit propertyUpdated();
1041     }
1042 }
1043 
1044 /**
1045  * @brief Delete old stick direction buttons and create new stick direction
1046  *     buttons.
1047  */
refreshButtons()1048 void JoyControlStick::refreshButtons()
1049 {
1050     deleteButtons();
1051     populateButtons();
1052 }
1053 
1054 /**
1055  * @brief Delete stick direction buttons and stick modifier button.
1056  */
deleteButtons()1057 void JoyControlStick::deleteButtons()
1058 {
1059     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
1060     while (iter.hasNext())
1061     {
1062         JoyButton *button = iter.next().value();
1063         if (button)
1064         {
1065             delete button;
1066             button = 0;
1067         }
1068     }
1069 
1070     buttons.clear();
1071 
1072     if (modifierButton)
1073     {
1074         delete modifierButton;
1075         modifierButton = 0;
1076     }
1077 }
1078 
1079 /**
1080  * @brief Take a XML stream and set the stick and direction button properties
1081  *     according to the values contained within the stream.
1082  * @param QXmlStreamReader instance that will be used to read property values.
1083  */
readConfig(QXmlStreamReader * xml)1084 void JoyControlStick::readConfig(QXmlStreamReader *xml)
1085 {
1086     if (xml->isStartElement() && xml->name() == "stick")
1087     {
1088         xml->readNextStartElement();
1089 
1090         while (!xml->atEnd() && (!xml->isEndElement() && xml->name() != "stick"))
1091         {
1092             if (xml->name() == "deadZone" && xml->isStartElement())
1093             {
1094                 QString temptext = xml->readElementText();
1095                 int tempchoice = temptext.toInt();
1096                 this->setDeadZone(tempchoice);
1097             }
1098             else if (xml->name() == "maxZone" && xml->isStartElement())
1099             {
1100                 QString temptext = xml->readElementText();
1101                 int tempchoice = temptext.toInt();
1102                 this->setMaxZone(tempchoice);
1103             }
1104             else if (xml->name() == "diagonalRange" && xml->isStartElement())
1105             {
1106                 QString temptext = xml->readElementText();
1107                 int tempchoice = temptext.toInt();
1108                 this->setDiagonalRange(tempchoice);
1109             }
1110             else if (xml->name() == "mode" && xml->isStartElement())
1111             {
1112                 QString temptext = xml->readElementText();
1113                 if (temptext == "eight-way")
1114                 {
1115                     this->setJoyMode(EightWayMode);
1116                 }
1117                 else if (temptext == "four-way")
1118                 {
1119                     this->setJoyMode(FourWayCardinal);
1120                 }
1121                 else if (temptext == "diagonal")
1122                 {
1123                     this->setJoyMode(FourWayDiagonal);
1124                 }
1125             }
1126             else if (xml->name() == "squareStick" && xml->isStartElement())
1127             {
1128                 QString temptext = xml->readElementText();
1129                 int tempchoice = temptext.toInt();
1130                 if (tempchoice > 0 && tempchoice <= 100)
1131                 {
1132                     this->setCircleAdjust(tempchoice / 100.0);
1133                 }
1134             }
1135             else if (xml->name() == JoyControlStickButton::xmlName && xml->isStartElement())
1136             {
1137                 int index = xml->attributes().value("index").toString().toInt();
1138                 JoyControlStickButton *button = buttons.value((JoyStickDirections)index);
1139                 if (button)
1140                 {
1141                     button->readConfig(xml);
1142                 }
1143                 else
1144                 {
1145                     xml->skipCurrentElement();
1146                 }
1147             }
1148             else if (xml->name() == JoyControlStickModifierButton::xmlName && xml->isStartElement())
1149             {
1150                 modifierButton->readConfig(xml);
1151             }
1152             else if (xml->name() == "stickDelay" && xml->isStartElement())
1153             {
1154                 QString temptext = xml->readElementText();
1155                 int tempchoice = temptext.toInt();
1156                 this->setStickDelay(tempchoice);
1157             }
1158             else
1159             {
1160                 xml->skipCurrentElement();
1161             }
1162 
1163             xml->readNextStartElement();
1164         }
1165     }
1166 }
1167 
1168 /**
1169  * @brief Write the status of the properties of a stick and direction buttons
1170  *     to an XML stream.
1171  * @param QXmlStreamWriter instance that will be used to write a profile.
1172  */
writeConfig(QXmlStreamWriter * xml)1173 void JoyControlStick::writeConfig(QXmlStreamWriter *xml)
1174 {
1175     if (!isDefault())
1176     {
1177         xml->writeStartElement("stick");
1178         xml->writeAttribute("index", QString::number(index+1));
1179 
1180         if (deadZone != DEFAULTDEADZONE)
1181         {
1182             xml->writeTextElement("deadZone", QString::number(deadZone));
1183         }
1184 
1185         if (maxZone != DEFAULTMAXZONE)
1186         {
1187             xml->writeTextElement("maxZone", QString::number(maxZone));
1188         }
1189 
1190         if (currentMode == StandardMode || currentMode == EightWayMode)
1191         {
1192             if (diagonalRange != DEFAULTDIAGONALRANGE)
1193             {
1194                 xml->writeTextElement("diagonalRange", QString::number(diagonalRange));
1195             }
1196         }
1197 
1198         if (currentMode == EightWayMode)
1199         {
1200             xml->writeTextElement("mode", "eight-way");
1201         }
1202         else if (currentMode == FourWayCardinal)
1203         {
1204             xml->writeTextElement("mode", "four-way");
1205         }
1206         else if (currentMode == FourWayDiagonal)
1207         {
1208             xml->writeTextElement("mode", "diagonal");
1209         }
1210 
1211         if (circle > DEFAULTCIRCLE)
1212         {
1213             xml->writeTextElement("squareStick", QString::number(circle * 100));
1214         }
1215 
1216         if (stickDelay > DEFAULTSTICKDELAY)
1217         {
1218             xml->writeTextElement("stickDelay", QString::number(stickDelay));
1219         }
1220 
1221         QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
1222         while (iter.hasNext())
1223         {
1224             JoyControlStickButton *button = iter.next().value();
1225             button->writeConfig(xml);
1226         }
1227 
1228         if (!modifierButton->isDefault())
1229         {
1230             modifierButton->writeConfig(xml);
1231         }
1232 
1233         xml->writeEndElement();
1234     }
1235 }
1236 
1237 /**
1238  * @brief Reset all the properties of the stick direction buttons and the
1239  *     stick modifier button.
1240  */
resetButtons()1241 void JoyControlStick::resetButtons()
1242 {
1243     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
1244     while (iter.hasNext())
1245     {
1246         JoyButton *button = iter.next().value();
1247         if (button)
1248         {
1249             button->reset();
1250         }
1251     }
1252 
1253     if (modifierButton)
1254     {
1255         modifierButton->reset();
1256     }
1257 }
1258 
1259 /**
1260  * @brief Get a pointer to the stick direction button for the desired
1261  *     direction.
1262  * @param Value of the direction of the stick.
1263  * @return Pointer to the stick direction button for the stick
1264  *     direction.
1265  */
getDirectionButton(JoyStickDirections direction)1266 JoyControlStickButton* JoyControlStick::getDirectionButton(JoyStickDirections direction)
1267 {
1268     JoyControlStickButton *button = buttons.value(direction);
1269     return button;
1270 }
1271 
1272 /**
1273  * @brief Used to calculate the distance value that should be used for mouse
1274  *     movement.
1275  * @param button
1276  * @return Distance factor that should be used for mouse movement
1277  */
calculateMouseDirectionalDistance(JoyControlStickButton * button)1278 double JoyControlStick::calculateMouseDirectionalDistance(JoyControlStickButton *button)
1279 {
1280     double finalDistance = 0.0;
1281 
1282     if (currentDirection == StickUp)
1283     {
1284         finalDistance = calculateYDistanceFromDeadZone(true);
1285     }
1286     else if (currentDirection == StickRightUp)
1287     {
1288         if (activeButton1 && activeButton1 == button)
1289         {
1290             finalDistance = calculateXDistanceFromDeadZone(true);
1291         }
1292         else if (activeButton2 && activeButton2 == button)
1293         {
1294             finalDistance = calculateYDistanceFromDeadZone(true);
1295         }
1296         else if (activeButton3 && activeButton3 == button)
1297         {
1298             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
1299         }
1300     }
1301     else if (currentDirection == StickRight)
1302     {
1303         finalDistance = calculateXDistanceFromDeadZone(true);
1304     }
1305     else if (currentDirection  == StickRightDown)
1306     {
1307         if (activeButton1 && activeButton1 == button)
1308         {
1309             finalDistance = calculateXDistanceFromDeadZone(true);
1310         }
1311         else if (activeButton2 && activeButton2 == button)
1312         {
1313             finalDistance = calculateYDistanceFromDeadZone(true);
1314         }
1315         else if (activeButton3 && activeButton3 == button)
1316         {
1317             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
1318         }
1319     }
1320     else if (currentDirection == StickDown)
1321     {
1322         finalDistance = calculateYDistanceFromDeadZone(true);
1323     }
1324     else if (currentDirection == StickLeftDown)
1325     {
1326         if (activeButton1 && activeButton1 == button)
1327         {
1328             finalDistance = calculateXDistanceFromDeadZone(true);
1329         }
1330         else if (activeButton2 && activeButton2 == button)
1331         {
1332             finalDistance = calculateYDistanceFromDeadZone(true);
1333         }
1334         else if (activeButton3 && activeButton3 == button)
1335         {
1336             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
1337         }
1338     }
1339     else if (currentDirection == StickLeft)
1340     {
1341         finalDistance = calculateXDistanceFromDeadZone(true);
1342     }
1343     else if (currentDirection == StickLeftUp)
1344     {
1345         if (activeButton1 && activeButton1 == button)
1346         {
1347             finalDistance = calculateXDistanceFromDeadZone(true);
1348         }
1349         else if (activeButton2 && activeButton2 == button)
1350         {
1351             finalDistance = calculateYDistanceFromDeadZone(true);
1352         }
1353         else if (activeButton3 && activeButton3 == button)
1354         {
1355             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone();
1356         }
1357     }
1358 
1359     return finalDistance;
1360 }
1361 
1362 
calculateLastMouseDirectionalDistance(JoyControlStickButton * button)1363 double JoyControlStick::calculateLastMouseDirectionalDistance(JoyControlStickButton *button)
1364 {
1365     double finalDistance = 0.0;
1366 
1367     JoyStickDirections direction = calculateStickDirection(axisX->getLastKnownThrottleValue(),
1368                                                            axisY->getLastKnownThrottleValue());
1369     if (direction == StickUp && button->getJoyNumber() == StickUp)
1370     {
1371         if (axisY->getLastKnownThrottleValue() >= 0)
1372         {
1373             finalDistance = 0.0;
1374         }
1375         else
1376         {
1377             finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1378                                                            axisY->getLastKnownThrottleValue(),
1379                                                            true);
1380         }
1381     }
1382     else if (direction == StickRightUp)
1383     {
1384         if (button->getJoyNumber() == StickRight)
1385         {
1386             if (axisX->getLastKnownThrottleValue() < 0)
1387             {
1388                 finalDistance = 0.0;
1389             }
1390             else
1391             {
1392                 finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1393                                                                axisY->getLastKnownThrottleValue(),
1394                                                                true);
1395             }
1396         }
1397         else if (button->getJoyNumber() == StickUp)
1398         {
1399             if (axisY->getLastKnownThrottleValue() >= 0)
1400             {
1401                 finalDistance = 0.0;
1402             }
1403             else
1404             {
1405                 finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1406                                                                axisY->getLastKnownThrottleValue(),
1407                                                                true);
1408             }
1409         }
1410         else if (button->getJoyNumber() == StickRightUp)
1411         {
1412             if (axisX->getLastKnownThrottleValue() <= 0 || axisY->getLastKnownThrottleValue() >= 0)
1413             {
1414                 finalDistance = 0.0;
1415             }
1416             else
1417             {
1418                 finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1419                                                                               axisY->getLastKnownThrottleValue());
1420             }
1421         }
1422     }
1423     else if (direction == StickRight && button->getJoyNumber() == StickRight)
1424     {
1425         if (axisX->getLastKnownThrottleValue() < 0)
1426         {
1427             finalDistance = 0.0;
1428         }
1429         else
1430         {
1431             finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1432                                                            axisY->getLastKnownThrottleValue(),
1433                                                            true);
1434         }
1435     }
1436     else if (direction  == StickRightDown)
1437     {
1438         if (button->getJoyNumber() == StickRight)
1439         {
1440             if (axisX->getLastKnownThrottleValue() < 0)
1441             {
1442                 finalDistance = 0.0;
1443             }
1444             else
1445             {
1446                 finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1447                                                                axisY->getLastKnownThrottleValue(),
1448                                                                true);
1449             }
1450         }
1451         else if (button->getJoyNumber() == StickDown)
1452         {
1453             if (axisY->getLastKnownThrottleValue() < 0)
1454             {
1455                 finalDistance = 0.0;
1456             }
1457             else
1458             {
1459                 finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1460                                                                axisY->getLastKnownThrottleValue(),
1461                                                                true);
1462             }
1463         }
1464         else if (button->getJoyNumber() == StickRightDown)
1465         {
1466             if (axisX->getLastKnownThrottleValue() <= 0 || axisY->getLastKnownThrottleValue() >= 0)
1467             {
1468                 finalDistance = 0.0;
1469             }
1470             else
1471             {
1472                 finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1473                                                                               axisY->getLastKnownThrottleValue());
1474             }
1475         }
1476     }
1477     else if (direction == StickDown && button->getJoyNumber() == StickDown)
1478     {
1479         if (axisY->getLastKnownThrottleValue() >= 0)
1480         {
1481             finalDistance = 0.0;
1482         }
1483         else
1484         {
1485             finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1486                                                            axisY->getLastKnownThrottleValue(),
1487                                                            true);
1488         }
1489     }
1490     else if (direction == StickLeftDown)
1491     {
1492         if (button->getJoyNumber() == StickLeft)
1493         {
1494             if (axisX->getLastKnownThrottleValue() >= 0)
1495             {
1496                 finalDistance = 0.0;
1497             }
1498             else
1499             {
1500                 finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1501                                                                axisY->getLastKnownThrottleValue(),
1502                                                                true);
1503             }
1504         }
1505         else if (button->getJoyNumber() == StickDown)
1506         {
1507             if (axisY->getLastKnownThrottleValue() < 0)
1508             {
1509                 finalDistance = 0.0;
1510             }
1511             else
1512             {
1513                 finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1514                                                                axisY->getLastKnownThrottleValue(),
1515                                                                true);
1516             }
1517         }
1518         else if (button->getJoyNumber() == StickLeftDown)
1519         {
1520             if (axisX->getLastKnownThrottleValue() >= 0 || axisY->getLastKnownThrottleValue() <= 0)
1521             {
1522                 finalDistance = 0.0;
1523             }
1524             else
1525             {
1526                 finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1527                                                                               axisY->getLastKnownThrottleValue());
1528             }
1529         }
1530     }
1531     else if (direction == StickLeft && button->getJoyNumber() == StickLeft)
1532     {
1533         if (axisX->getLastKnownThrottleValue() >= 0)
1534         {
1535             finalDistance = 0.0;
1536         }
1537         else
1538         {
1539             finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1540                                                            axisY->getLastKnownThrottleValue(),
1541                                                            true);
1542         }
1543     }
1544     else if (direction == StickLeftUp)
1545     {
1546         if (button->getJoyNumber() == StickLeft)
1547         {
1548             if (axisX->getLastKnownThrottleValue() >= 0)
1549             {
1550                 finalDistance = 0.0;
1551             }
1552             else
1553             {
1554                 finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1555                                                                axisY->getLastKnownThrottleValue(),
1556                                                                true);
1557             }
1558         }
1559         else if (button->getJoyNumber() == StickUp)
1560         {
1561             if (axisY->getLastKnownThrottleValue() >= 0)
1562             {
1563                 finalDistance = 0.0;
1564             }
1565             else
1566             {
1567                 finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1568                                                                axisY->getLastKnownThrottleValue(),
1569                                                                true);
1570             }
1571         }
1572         else if (button->getJoyNumber() == StickLeftUp)
1573         {
1574             if (axisX->getLastKnownThrottleValue() >= 0 || axisY->getLastKnownThrottleValue() >= 0)
1575             {
1576                 finalDistance = 0.0;
1577             }
1578             else
1579             {
1580                 finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1581                                                                               axisY->getLastKnownThrottleValue());
1582             }
1583         }
1584     }
1585 
1586     return finalDistance;
1587 }
1588 
calculateLastDirectionalDistance()1589 double JoyControlStick::calculateLastDirectionalDistance()
1590 {
1591     double finalDistance = 0.0;
1592 
1593     JoyStickDirections direction = calculateStickDirection(axisX->getLastKnownThrottleValue(),
1594                                                            axisY->getLastKnownThrottleValue());
1595     if (direction == StickUp)
1596     {
1597         if (!axisX->getLastKnownThrottleValue() >= 0)
1598         {
1599             finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1600                                                            axisY->getLastKnownThrottleValue());
1601         }
1602     }
1603     else if (direction == StickRightUp)
1604     {
1605         if (!axisY->getLastKnownThrottleValue() <= 0 && !axisY->getLastKnownThrottleValue() >= 0)
1606         {
1607             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1608                                                                           axisY->getLastKnownThrottleValue());
1609         }
1610     }
1611     else if (direction == StickRight)
1612     {
1613         if (!axisX->getLastKnownThrottleValue() <= 0)
1614         {
1615             finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1616                                                            axisY->getLastKnownThrottleValue());
1617         }
1618     }
1619     else if (direction  == StickRightDown)
1620     {
1621         if (!axisY->getLastKnownThrottleValue() <= 0 && !axisY->getLastKnownThrottleValue() <= 0)
1622         {
1623             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1624                                                                           axisY->getLastKnownThrottleValue());
1625         }
1626     }
1627     else if (direction == StickDown)
1628     {
1629         if (!axisY->getLastKnownThrottleValue() <= 0)
1630         {
1631             finalDistance = calculateYDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1632                                                            axisY->getLastKnownThrottleValue());
1633         }
1634     }
1635     else if (direction == StickLeftDown)
1636     {
1637         if (!axisY->getLastKnownThrottleValue() >= 0 && !axisY->getLastKnownThrottleValue() <= 0)
1638         {
1639             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1640                                                                           axisY->getLastKnownThrottleValue());
1641         }
1642     }
1643     else if (direction == StickLeft)
1644     {
1645         if (!axisX->getLastKnownThrottleValue() >= 0)
1646         {
1647             finalDistance = calculateXDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1648                                                            axisY->getLastKnownThrottleValue());
1649         }
1650     }
1651     else if (direction == StickLeftUp)
1652     {
1653         if (!axisY->getLastKnownThrottleValue() >= 0 && !axisY->getLastKnownThrottleValue() >= 0)
1654         {
1655             finalDistance = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getLastKnownThrottleValue(),
1656                                                                           axisY->getLastKnownThrottleValue());
1657         }
1658     }
1659 
1660     return finalDistance;
1661 }
1662 
calculateLastAccelerationDirectionalDistance()1663 double JoyControlStick::calculateLastAccelerationDirectionalDistance()
1664 {
1665     double finalDistance = 0.0;
1666 
1667     if (currentDirection == StickUp)
1668     {
1669         if (!axisX->getLastKnownRawValue() >= 0)
1670         {
1671             finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
1672         }
1673     }
1674     else if (currentDirection == StickRightUp)
1675     {
1676         if (!axisY->getLastKnownRawValue() <= 0 && !axisY->getLastKnownRawValue() >= 0)
1677         {
1678             finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
1679         }
1680     }
1681     else if (currentDirection == StickRight)
1682     {
1683         if (!axisX->getLastKnownRawValue() <= 0)
1684         {
1685             finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
1686         }
1687     }
1688     else if (currentDirection  == StickRightDown)
1689     {
1690         if (!axisY->getLastKnownRawValue() <= 0 && !axisY->getLastKnownRawValue() <= 0)
1691         {
1692             finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
1693         }
1694     }
1695     else if (currentDirection == StickDown)
1696     {
1697         if (!axisY->getLastKnownRawValue() <= 0)
1698         {
1699             finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
1700         }
1701     }
1702     else if (currentDirection == StickLeftDown)
1703     {
1704         if (!axisY->getLastKnownRawValue() >= 0 && !axisY->getLastKnownRawValue() <= 0)
1705         {
1706             finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
1707         }
1708     }
1709     else if (currentDirection == StickLeft)
1710     {
1711         if (!axisX->getLastKnownRawValue() >= 0)
1712         {
1713             finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
1714         }
1715     }
1716     else if (currentDirection == StickLeftUp)
1717     {
1718         if (!axisY->getLastKnownRawValue() >= 0 && !axisY->getLastKnownRawValue() >= 0)
1719         {
1720             finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
1721         }
1722     }
1723 
1724     return finalDistance;
1725 }
1726 
1727 /**
1728  * @brief Used to calculate the distance value that should be used for keyboard
1729  *     events and distance slots
1730  * @return Distance factor that should be used for keyboard events and
1731  *     distance slots
1732  */
calculateDirectionalDistance()1733 double JoyControlStick::calculateDirectionalDistance()
1734 {
1735     double finalDistance = 0.0;
1736 
1737     if (currentDirection == StickUp)
1738     {
1739         finalDistance = calculateYDistanceFromDeadZone();
1740     }
1741     else if (currentDirection == StickRightUp)
1742     {
1743         finalDistance = getDistanceFromDeadZone();
1744     }
1745     else if (currentDirection == StickRight)
1746     {
1747         finalDistance = calculateXDistanceFromDeadZone();
1748     }
1749     else if (currentDirection  == StickRightDown)
1750     {
1751         finalDistance = getDistanceFromDeadZone();
1752     }
1753     else if (currentDirection == StickDown)
1754     {
1755         finalDistance = calculateYDistanceFromDeadZone();
1756     }
1757     else if (currentDirection == StickLeftDown)
1758     {
1759         finalDistance = getDistanceFromDeadZone();
1760     }
1761     else if (currentDirection == StickLeft)
1762     {
1763         finalDistance = calculateXDistanceFromDeadZone();
1764     }
1765     else if (currentDirection == StickLeftUp)
1766     {
1767         finalDistance = getDistanceFromDeadZone();
1768     }
1769 
1770     return finalDistance;
1771 }
1772 
1773 /**
1774  * @brief Get the value for the currently active stick direction.
1775  * @return Value of the corresponding active stick direction.
1776  */
getCurrentDirection()1777 JoyControlStick::JoyStickDirections JoyControlStick::getCurrentDirection()
1778 {
1779     return currentDirection;
1780 }
1781 
1782 /**
1783  * @brief Get the value for the corresponding X axis.
1784  * @return X axis value.
1785  */
getXCoordinate()1786 int JoyControlStick::getXCoordinate()
1787 {
1788     return axisX->getCurrentRawValue();
1789 }
1790 
1791 /**
1792  * @brief Get the value for the corresponding Y axis.
1793  * @return Y axis value.
1794  */
getYCoordinate()1795 int JoyControlStick::getYCoordinate()
1796 {
1797     return axisY->getCurrentRawValue();
1798 }
1799 
getCircleXCoordinate()1800 int JoyControlStick::getCircleXCoordinate()
1801 {
1802     int axisXValue = axisX->getCurrentRawValue();
1803     int axisYValue = axisX->getCurrentRawValue();
1804     if (this->circle > 0.0)
1805     {
1806         axisXValue = calculateCircleXValue(axisXValue, axisYValue);
1807     }
1808 
1809     return axisXValue;
1810 }
1811 
getCircleYCoordinate()1812 int JoyControlStick::getCircleYCoordinate()
1813 {
1814     int axisXValue = axisX->getCurrentRawValue();
1815     int axisYValue = axisY->getCurrentRawValue();
1816     if (this->circle > 0.0)
1817     {
1818         axisYValue = calculateCircleYValue(axisXValue, axisYValue);
1819     }
1820 
1821     return axisYValue;
1822 }
1823 
calculateCircleXValue(int axisXValue,int axisYValue)1824 int JoyControlStick::calculateCircleXValue(int axisXValue, int axisYValue)
1825 {
1826     int value = axisXValue;
1827     if (this->circle > 0.0)
1828     {
1829         int axis1Value = axisXValue;
1830         int axis2Value = axisYValue;
1831 
1832         double angle2 = atan2(axis1Value, -axis2Value);
1833         double ang_sin = sin(angle2);
1834         double ang_cos = cos(angle2);
1835 
1836         //int axisXValueCircleFull = static_cast<int>(floor(JoyAxis::AXISMAX * fabs(ang_sin) + 0.5));
1837         double squareStickFull = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
1838         double circle = this->circle;
1839         double circleStickFull = (squareStickFull - 1) * circle + 1;
1840         //double alternateStickFullValue = circleStickFull * abs(axisXValueCircleFull);
1841 
1842         //value = circleStickFull > 1.0 ? static_cast<int>(floor((axisXValue / alternateStickFullValue) * abs(axisXValueCircleFull) + 0.5)) : value;
1843         value = circleStickFull > 1.0 ? static_cast<int>(floor((axisXValue / circleStickFull) + 0.5)) : value;
1844     }
1845 
1846     return value;
1847 }
1848 
calculateCircleYValue(int axisXValue,int axisYValue)1849 int JoyControlStick::calculateCircleYValue(int axisXValue, int axisYValue)
1850 {
1851     int value = axisYValue;
1852     if (this->circle > 0.0)
1853     {
1854         int axis1Value = axisXValue;
1855         int axis2Value = axisYValue;
1856 
1857         double angle2 = atan2(axis1Value, -axis2Value);
1858         double ang_sin = sin(angle2);
1859         double ang_cos = cos(angle2);
1860 
1861         //int axisYValueCircleFull = static_cast<int>(floor(JoyAxis::AXISMAX * fabs(ang_cos) + 0.5));
1862         double squareStickFull = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
1863         double circle = this->circle;
1864         double circleStickFull = (squareStickFull - 1) * circle + 1;
1865         //double alternateStickFullValue = circleStickFull * abs(axisYValueCircleFull);
1866 
1867         //value = circleStickFull > 1.0 ? static_cast<int>(floor((axisYValue / alternateStickFullValue) * abs(axisYValueCircleFull) + 0.5)) : value;
1868         value = circleStickFull > 1.0 ? static_cast<int>(floor((axisYValue / circleStickFull) + 0.5)) : value;
1869     }
1870 
1871     return value;
1872 }
1873 
getDiagonalZoneAngles()1874 QList<double> JoyControlStick::getDiagonalZoneAngles()
1875 {
1876     QList<double> anglesList;
1877 
1878     int diagonalAngle = diagonalRange;
1879 
1880     double cardinalAngle = (360 - (diagonalAngle * 4)) / 4.0;
1881 
1882     double initialLeft = 360 - ((cardinalAngle) / 2.0);
1883     double initialRight = ((cardinalAngle)/ 2.0);
1884     /*if ((int)(cardinalAngle - 1) % 2 != 0)
1885     {
1886         initialLeft = 360 - (cardinalAngle / 2.0);
1887         initialRight = (cardinalAngle / 2.0) - 1;
1888     }
1889     */
1890 
1891     double upRightInitial = initialRight;
1892     double rightInitial = upRightInitial + diagonalAngle;
1893     double downRightInitial = rightInitial + cardinalAngle;
1894     double downInitial = downRightInitial + diagonalAngle;
1895     double downLeftInitial = downInitial + cardinalAngle;
1896     double leftInitial = downLeftInitial + diagonalAngle;
1897     double upLeftInitial = leftInitial + cardinalAngle;
1898 
1899     anglesList.append(initialLeft);
1900     anglesList.append(initialRight);
1901     anglesList.append(upRightInitial);
1902     anglesList.append(rightInitial);
1903     anglesList.append(downRightInitial);
1904     anglesList.append(downInitial);
1905     anglesList.append(downLeftInitial);
1906     anglesList.append(leftInitial);
1907     anglesList.append(upLeftInitial);
1908 
1909     return anglesList;
1910 }
1911 
getFourWayCardinalZoneAngles()1912 QList<int> JoyControlStick::getFourWayCardinalZoneAngles()
1913 {
1914     QList<int> anglesList;
1915 
1916     int zoneRange = 90;
1917 
1918     int rightInitial = 45;
1919     int downInitial = rightInitial + zoneRange;
1920     int leftInitial = downInitial + zoneRange;
1921     int upInitial = leftInitial + zoneRange;
1922 
1923     anglesList.append(rightInitial);
1924     anglesList.append(downInitial);
1925     anglesList.append(leftInitial);
1926     anglesList.append(upInitial);
1927     return anglesList;
1928 }
1929 
getFourWayDiagonalZoneAngles()1930 QList<int> JoyControlStick::getFourWayDiagonalZoneAngles()
1931 {
1932     QList<int> anglesList;
1933 
1934     int zoneRange = 90;
1935 
1936     int upRightInitial = 0;
1937     int downRightInitial = zoneRange;
1938     int downLeftInitial = downRightInitial + zoneRange;
1939     int upLeftInitial = downLeftInitial + zoneRange;
1940 
1941     anglesList.append(upRightInitial);
1942     anglesList.append(downRightInitial);
1943     anglesList.append(downLeftInitial);
1944     anglesList.append(upLeftInitial);
1945     return anglesList;
1946 }
1947 
getButtons()1948 QHash<JoyControlStick::JoyStickDirections, JoyControlStickButton*>* JoyControlStick::getButtons()
1949 {
1950     return &buttons;
1951 }
1952 
getAxisX()1953 JoyAxis* JoyControlStick::getAxisX()
1954 {
1955     return axisX;
1956 }
1957 
getAxisY()1958 JoyAxis* JoyControlStick::getAxisY()
1959 {
1960     return axisY;
1961 }
1962 
replaceXAxis(JoyAxis * axis)1963 void JoyControlStick::replaceXAxis(JoyAxis *axis)
1964 {
1965     if (axis->getParentSet() == axisY->getParentSet())
1966     {
1967         axisX->removeControlStick();
1968         this->axisX = axis;
1969         this->axisX->setControlStick(this);
1970     }
1971 }
1972 
replaceYAxis(JoyAxis * axis)1973 void JoyControlStick::replaceYAxis(JoyAxis *axis)
1974 {
1975     if (axis->getParentSet() == axisX->getParentSet())
1976     {
1977         axisY->removeControlStick();
1978         this->axisY = axis;
1979         this->axisY->setControlStick(this);
1980     }
1981 }
1982 
replaceAxes(JoyAxis * axisX,JoyAxis * axisY)1983 void JoyControlStick::replaceAxes(JoyAxis *axisX, JoyAxis *axisY)
1984 {
1985     if (axisX->getParentSet() == axisY->getParentSet())
1986     {
1987         this->axisX->removeControlStick();
1988         this->axisY->removeControlStick();
1989 
1990         this->axisX = axisX;
1991         this->axisY = axisY;
1992 
1993         this->axisX->setControlStick(this);
1994         this->axisY->setControlStick(this);
1995     }
1996 }
1997 
setJoyMode(JoyMode mode)1998 void JoyControlStick::setJoyMode(JoyMode mode)
1999 {
2000     currentMode = mode;
2001     emit joyModeChanged();
2002     emit propertyUpdated();
2003 }
2004 
getJoyMode()2005 JoyControlStick::JoyMode JoyControlStick::getJoyMode()
2006 {
2007     return currentMode;
2008 }
2009 
releaseButtonEvents()2010 void JoyControlStick::releaseButtonEvents()
2011 {
2012     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2013     while (iter.hasNext())
2014     {
2015         JoyControlStickButton *button = iter.next().value();
2016         button->joyEvent(false, true);
2017     }
2018 }
2019 
isDefault()2020 bool JoyControlStick::isDefault()
2021 {
2022     bool value = true;
2023     value = value && (deadZone == DEFAULTDEADZONE);
2024     value = value && (maxZone == DEFAULTMAXZONE);
2025     value = value && (diagonalRange == DEFAULTDIAGONALRANGE);
2026     value = value && (currentMode == DEFAULTMODE);
2027     value = value && (circle == DEFAULTCIRCLE);
2028     value = value && (stickDelay == DEFAULTSTICKDELAY);
2029 
2030     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2031     while (iter.hasNext())
2032     {
2033         JoyControlStickButton *button = iter.next().value();
2034         value = value && (button->isDefault());
2035     }
2036 
2037     if (modifierButton)
2038     {
2039         value = value && modifierButton->isDefault();
2040     }
2041 
2042     return value;
2043 }
2044 
setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode)2045 void JoyControlStick::setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode)
2046 {
2047     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2048     while (iter.hasNext())
2049     {
2050         JoyControlStickButton *button = iter.next().value();
2051         button->setMouseMode(mode);
2052     }
2053 }
2054 
hasSameButtonsMouseMode()2055 bool JoyControlStick::hasSameButtonsMouseMode()
2056 {
2057     bool result = true;
2058 
2059     JoyButton::JoyMouseMovementMode initialMode = JoyButton::MouseCursor;
2060 
2061     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2062     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2063     while (iter.hasNext())
2064     {
2065         if (!iter.hasPrevious())
2066         {
2067             JoyControlStickButton *button = iter.next().value();
2068             initialMode = button->getMouseMode();
2069         }
2070         else
2071         {
2072             JoyControlStickButton *button = iter.next().value();
2073             JoyButton::JoyMouseMovementMode temp = button->getMouseMode();
2074             if (temp != initialMode)
2075             {
2076                 result = false;
2077                 iter.toBack();
2078             }
2079         }
2080     }
2081 
2082     return result;
2083 }
2084 
getButtonsPresetMouseMode()2085 JoyButton::JoyMouseMovementMode JoyControlStick::getButtonsPresetMouseMode()
2086 {
2087     JoyButton::JoyMouseMovementMode resultMode = JoyButton::MouseCursor;
2088 
2089     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2090     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2091     while (iter.hasNext())
2092     {
2093         if (!iter.hasPrevious())
2094         {
2095             JoyControlStickButton *button = iter.next().value();
2096             resultMode = button->getMouseMode();
2097         }
2098         else
2099         {
2100             JoyControlStickButton *button = iter.next().value();
2101             JoyButton::JoyMouseMovementMode temp = button->getMouseMode();
2102             if (temp != resultMode)
2103             {
2104                 resultMode = JoyButton::MouseCursor;
2105                 iter.toBack();
2106             }
2107         }
2108     }
2109 
2110     return resultMode;
2111 }
2112 
setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve)2113 void JoyControlStick::setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve)
2114 {
2115     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2116     while (iter.hasNext())
2117     {
2118         JoyControlStickButton *button = iter.next().value();
2119         button->setMouseCurve(mouseCurve);
2120     }
2121 }
2122 
hasSameButtonsMouseCurve()2123 bool JoyControlStick::hasSameButtonsMouseCurve()
2124 {
2125     bool result = true;
2126 
2127     JoyButton::JoyMouseCurve initialCurve = JoyButton::LinearCurve;
2128 
2129     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2130     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2131     while (iter.hasNext())
2132     {
2133         if (!iter.hasPrevious())
2134         {
2135             JoyControlStickButton *button = iter.next().value();
2136             initialCurve = button->getMouseCurve();
2137         }
2138         else
2139         {
2140             JoyControlStickButton *button = iter.next().value();
2141             JoyButton::JoyMouseCurve temp = button->getMouseCurve();
2142             if (temp != initialCurve)
2143             {
2144                 result = false;
2145                 iter.toBack();
2146             }
2147         }
2148     }
2149 
2150     return result;
2151 }
2152 
getButtonsPresetMouseCurve()2153 JoyButton::JoyMouseCurve JoyControlStick::getButtonsPresetMouseCurve()
2154 {
2155     JoyButton::JoyMouseCurve resultCurve = JoyButton::LinearCurve;
2156 
2157     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2158     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2159     while (iter.hasNext())
2160     {
2161         if (!iter.hasPrevious())
2162         {
2163             JoyControlStickButton *button = iter.next().value();
2164             resultCurve = button->getMouseCurve();
2165         }
2166         else
2167         {
2168             JoyControlStickButton *button = iter.next().value();
2169             JoyButton::JoyMouseCurve temp = button->getMouseCurve();
2170             if (temp != resultCurve)
2171             {
2172                 resultCurve = JoyButton::LinearCurve;
2173                 iter.toBack();
2174             }
2175         }
2176     }
2177 
2178     return resultCurve;
2179 }
2180 
setButtonsSpringWidth(int value)2181 void JoyControlStick::setButtonsSpringWidth(int value)
2182 {
2183     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2184     while (iter.hasNext())
2185     {
2186         JoyControlStickButton *button = iter.next().value();
2187         button->setSpringWidth(value);
2188     }
2189 }
2190 
setButtonsSpringHeight(int value)2191 void JoyControlStick::setButtonsSpringHeight(int value)
2192 {
2193     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2194     while (iter.hasNext())
2195     {
2196         JoyControlStickButton *button = iter.next().value();
2197         button->setSpringHeight(value);
2198     }
2199 }
2200 
getButtonsPresetSpringWidth()2201 int JoyControlStick::getButtonsPresetSpringWidth()
2202 {
2203     int presetSpringWidth = 0;
2204 
2205     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2206     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2207     while (iter.hasNext())
2208     {
2209         if (!iter.hasPrevious())
2210         {
2211             JoyControlStickButton *button = iter.next().value();
2212             presetSpringWidth = button->getSpringWidth();
2213         }
2214         else
2215         {
2216             JoyControlStickButton *button = iter.next().value();
2217             int temp = button->getSpringWidth();
2218             if (temp != presetSpringWidth)
2219             {
2220                 presetSpringWidth = 0;
2221                 iter.toBack();
2222             }
2223         }
2224     }
2225 
2226     return presetSpringWidth;
2227 }
2228 
getButtonsPresetSpringHeight()2229 int JoyControlStick::getButtonsPresetSpringHeight()
2230 {
2231     int presetSpringHeight = 0;
2232 
2233     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2234     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2235     while (iter.hasNext())
2236     {
2237         if (!iter.hasPrevious())
2238         {
2239             JoyControlStickButton *button = iter.next().value();
2240             presetSpringHeight = button->getSpringHeight();
2241         }
2242         else
2243         {
2244             JoyControlStickButton *button = iter.next().value();
2245             int temp = button->getSpringHeight();
2246             if (temp != presetSpringHeight)
2247             {
2248                 presetSpringHeight = 0;
2249                 iter.toBack();
2250             }
2251         }
2252     }
2253 
2254     return presetSpringHeight;
2255 }
2256 
setButtonsSensitivity(double value)2257 void JoyControlStick::setButtonsSensitivity(double value)
2258 {
2259     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2260     while (iter.hasNext())
2261     {
2262         JoyControlStickButton *button = iter.next().value();
2263         button->setSensitivity(value);
2264     }
2265 }
2266 
getButtonsPresetSensitivity()2267 double JoyControlStick::getButtonsPresetSensitivity()
2268 {
2269     double presetSensitivity = 1.0;
2270 
2271     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2272     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2273     while (iter.hasNext())
2274     {
2275         if (!iter.hasPrevious())
2276         {
2277             JoyControlStickButton *button = iter.next().value();
2278             presetSensitivity = button->getSensitivity();
2279         }
2280         else
2281         {
2282             JoyControlStickButton *button = iter.next().value();
2283             double temp = button->getSensitivity();
2284             if (temp != presetSensitivity)
2285             {
2286                 presetSensitivity = 1.0;
2287                 iter.toBack();
2288             }
2289         }
2290     }
2291 
2292     return presetSensitivity;
2293 }
2294 
getApplicableButtons()2295 QHash<JoyControlStick::JoyStickDirections, JoyControlStickButton*> JoyControlStick::getApplicableButtons()
2296 {
2297     QHash<JoyStickDirections, JoyControlStickButton*> temphash;
2298 
2299     if (currentMode == StandardMode || currentMode == EightWayMode ||
2300         currentMode == FourWayCardinal)
2301     {
2302         temphash.insert(StickUp, buttons.value(StickUp));
2303         temphash.insert(StickDown, buttons.value(StickDown));
2304         temphash.insert(StickLeft, buttons.value(StickLeft));
2305         temphash.insert(StickRight, buttons.value(StickRight));
2306     }
2307 
2308     if (currentMode == EightWayMode || currentMode == FourWayDiagonal)
2309     {
2310         temphash.insert(StickLeftUp, buttons.value(StickLeftUp));
2311         temphash.insert(StickRightUp, buttons.value(StickRightUp));
2312         temphash.insert(StickRightDown, buttons.value(StickRightDown));
2313         temphash.insert(StickLeftDown, buttons.value(StickLeftDown));
2314     }
2315 
2316     return temphash;
2317 }
2318 
setStickName(QString tempName)2319 void JoyControlStick::setStickName(QString tempName)
2320 {
2321     if (tempName.length() <= 20 && tempName != stickName)
2322     {
2323         stickName = tempName;
2324         emit stickNameChanged();
2325         emit propertyUpdated();
2326     }
2327 }
2328 
getStickName()2329 QString JoyControlStick::getStickName()
2330 {
2331     return stickName;
2332 }
2333 
setButtonsWheelSpeedX(int value)2334 void JoyControlStick::setButtonsWheelSpeedX(int value)
2335 {
2336     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2337     while (iter.hasNext())
2338     {
2339         JoyControlStickButton *button = iter.next().value();
2340         button->setWheelSpeedX(value);
2341     }
2342 }
2343 
setButtonsWheelSpeedY(int value)2344 void JoyControlStick::setButtonsWheelSpeedY(int value)
2345 {
2346     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2347     while (iter.hasNext())
2348     {
2349         JoyControlStickButton *button = iter.next().value();
2350         button->setWheelSpeedY(value);
2351     }
2352 }
2353 
2354 /**
2355  * @brief Get pointer to the set that a stick belongs to.
2356  * @return Pointer to the set that a stick belongs to.
2357  */
getParentSet()2358 SetJoystick* JoyControlStick::getParentSet()
2359 {
2360     SetJoystick *temp = 0;
2361     if (axisX)
2362     {
2363         temp = axisX->getParentSet();
2364     }
2365     else if (axisY)
2366     {
2367         temp = axisY->getParentSet();
2368     }
2369     return temp;
2370 }
2371 
2372 /**
2373  * @brief Activate a stick direction button.
2374  * @param Stick direction button that will be activated.
2375  * @param [out] Pointer to the currently active button.
2376  * @param Should set changing routines be ignored.
2377  */
performButtonPress(JoyControlStickButton * eventbutton,JoyControlStickButton * & activebutton,bool ignoresets)2378 void JoyControlStick::performButtonPress(JoyControlStickButton *eventbutton, JoyControlStickButton *&activebutton, bool ignoresets)
2379 {
2380     activebutton = eventbutton;
2381     eventbutton->joyEvent(true, ignoresets);
2382 }
2383 
2384 /**
2385  * @brief Stick direction button to release.
2386  * @param Stick direction button that will be released.
2387  * @param Should set changing routines be ignored.
2388  */
performButtonRelease(JoyControlStickButton * & eventbutton,bool ignoresets)2389 void JoyControlStick::performButtonRelease(JoyControlStickButton *&eventbutton, bool ignoresets)
2390 {
2391     eventbutton->joyEvent(false, ignoresets);
2392     eventbutton = 0;
2393 }
2394 
2395 /**
2396  * @brief Determine which stick direction buttons should be active for a
2397  *     standard mode stick.
2398  * @param [out] Pointer to an X axis stick direction button that should be active.
2399  * @param [out] Pointer to a Y axis stick direction button that should be active.
2400  */
determineStandardModeEvent(JoyControlStickButton * & eventbutton1,JoyControlStickButton * & eventbutton2)2401 void JoyControlStick::determineStandardModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2)
2402 {
2403     double bearing = calculateBearing();
2404 
2405     QList<double> anglesList = getDiagonalZoneAngles();
2406     double initialLeft = anglesList.value(0);
2407     double initialRight = anglesList.value(1);
2408     double upRightInitial = anglesList.value(2);
2409     double rightInitial = anglesList.value(3);
2410     double downRightInitial = anglesList.value(4);
2411     double downInitial = anglesList.value(5);
2412     double downLeftInitial = anglesList.value(6);
2413     double leftInitial = anglesList.value(7);
2414     double upLeftInitial = anglesList.value(8);
2415 
2416     //bearing = floor(bearing + 0.5);
2417     if (bearing <= initialRight || bearing >= initialLeft)
2418     {
2419         currentDirection = StickUp;
2420         eventbutton2 = buttons.value(StickUp);
2421     }
2422     else if (bearing >= upRightInitial && bearing < rightInitial)
2423     {
2424         currentDirection = StickRightUp;
2425         eventbutton1 = buttons.value(StickRight);
2426         eventbutton2 = buttons.value(StickUp);
2427     }
2428     else if (bearing >= rightInitial && bearing < downRightInitial)
2429     {
2430         currentDirection = StickRight;
2431         eventbutton1 = buttons.value(StickRight);
2432     }
2433     else if (bearing >= downRightInitial && bearing < downInitial)
2434     {
2435         currentDirection = StickRightDown;
2436         eventbutton1 = buttons.value(StickRight);
2437         eventbutton2 = buttons.value(StickDown);
2438     }
2439     else if (bearing >= downInitial && bearing < downLeftInitial)
2440     {
2441         currentDirection = StickDown;
2442         eventbutton2 = buttons.value(StickDown);
2443     }
2444     else if (bearing >= downLeftInitial && bearing < leftInitial)
2445     {
2446         currentDirection = StickLeftDown;
2447         eventbutton1 = buttons.value(StickLeft);
2448         eventbutton2 = buttons.value(StickDown);
2449     }
2450     else if (bearing >= leftInitial && bearing < upLeftInitial)
2451     {
2452         currentDirection = StickLeft;
2453         eventbutton1 = buttons.value(StickLeft);
2454     }
2455     else if (bearing >= upLeftInitial && bearing < initialLeft)
2456     {
2457         currentDirection = StickLeftUp;
2458         eventbutton1 = buttons.value(StickLeft);
2459         eventbutton2 = buttons.value(StickUp);
2460     }
2461 }
2462 
2463 /**
2464  * @brief Determine which stick direction button should be active for a 8 way
2465  *     mode stick.
2466  * @param [out] Pointer to an X axis stick direction button that should be active.
2467  * @param [out] Pointer to a Y axis stick direction button that should be active.
2468  * @param [out] Pointer to a diagonal stick direction button that should be active.
2469  */
determineEightWayModeEvent(JoyControlStickButton * & eventbutton1,JoyControlStickButton * & eventbutton2,JoyControlStickButton * & eventbutton3)2470 void JoyControlStick::determineEightWayModeEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2, JoyControlStickButton *&eventbutton3)
2471 {
2472     double bearing = calculateBearing();
2473 
2474     QList<double> anglesList = getDiagonalZoneAngles();
2475     double initialLeft = anglesList.value(0);
2476     double initialRight = anglesList.value(1);
2477     double upRightInitial = anglesList.value(2);
2478     double rightInitial = anglesList.value(3);
2479     double downRightInitial = anglesList.value(4);
2480     double downInitial = anglesList.value(5);
2481     double downLeftInitial = anglesList.value(6);
2482     double leftInitial = anglesList.value(7);
2483     double upLeftInitial = anglesList.value(8);
2484 
2485     //bearing = floor(bearing + 0.5);
2486     if (bearing <= initialRight || bearing >= initialLeft)
2487     {
2488         currentDirection = StickUp;
2489         eventbutton2 = buttons.value(StickUp);
2490     }
2491     else if (bearing >= upRightInitial && bearing < rightInitial)
2492     {
2493         currentDirection = StickRightUp;
2494         eventbutton3 = buttons.value(StickRightUp);
2495     }
2496     else if (bearing >= rightInitial && bearing < downRightInitial)
2497     {
2498         currentDirection = StickRight;
2499         eventbutton1 = buttons.value(StickRight);
2500     }
2501     else if (bearing >= downRightInitial && bearing < downInitial)
2502     {
2503         currentDirection = StickRightDown;
2504         eventbutton3 = buttons.value(StickRightDown);
2505     }
2506     else if (bearing >= downInitial && bearing < downLeftInitial)
2507     {
2508         currentDirection = StickDown;
2509         eventbutton2 = buttons.value(StickDown);
2510     }
2511     else if (bearing >= downLeftInitial && bearing < leftInitial)
2512     {
2513         currentDirection = StickLeftDown;
2514         eventbutton3 = buttons.value(StickLeftDown);
2515     }
2516     else if (bearing >= leftInitial && bearing < upLeftInitial)
2517     {
2518         currentDirection = StickLeft;
2519         eventbutton1 = buttons.value(StickLeft);
2520     }
2521     else if (bearing >= upLeftInitial && bearing < initialLeft)
2522     {
2523         currentDirection = StickLeftUp;
2524         eventbutton3 = buttons.value(StickLeftUp);
2525     }
2526 }
2527 
2528 /**
2529  * @brief Determine which cardinal stick direction button should be active
2530  *     when using a four way cardinal stick.
2531  * @param [out] Pointer to an X axis stick direction button that should be active.
2532  * @param [out] Pointer to a Y axis stick direction button that should be active.
2533  */
determineFourWayCardinalEvent(JoyControlStickButton * & eventbutton1,JoyControlStickButton * & eventbutton2)2534 void JoyControlStick::determineFourWayCardinalEvent(JoyControlStickButton *&eventbutton1, JoyControlStickButton *&eventbutton2)
2535 {
2536     double bearing = calculateBearing();
2537 
2538     QList<int> anglesList = getFourWayCardinalZoneAngles();
2539     int rightInitial = anglesList.value(0);
2540     int downInitial = anglesList.value(1);
2541     int leftInitial = anglesList.value(2);
2542     int upInitial = anglesList.value(3);
2543 
2544     //bearing = floor(bearing + 0.5);
2545     if (bearing < rightInitial || bearing >= upInitial)
2546     {
2547         currentDirection = StickUp;
2548         eventbutton2 = buttons.value(StickUp);
2549     }
2550     else if (bearing >= rightInitial && bearing < downInitial)
2551     {
2552         currentDirection = StickRight;
2553         eventbutton1 = buttons.value(StickRight);
2554     }
2555     else if (bearing >= downInitial && bearing < leftInitial)
2556     {
2557         currentDirection = StickDown;
2558         eventbutton2 = buttons.value(StickDown);
2559     }
2560     else if (bearing >= leftInitial && bearing < upInitial)
2561     {
2562         currentDirection = StickLeft;
2563         eventbutton1 = buttons.value(StickLeft);
2564     }
2565 }
2566 
2567 /**
2568  * @brief Determine which stick direction button should be active when using 4 way
2569  *     diagonal mode.
2570  * @param [out] pointer to a diagonal stick direction button that should be active.
2571  */
determineFourWayDiagonalEvent(JoyControlStickButton * & eventbutton3)2572 void JoyControlStick::determineFourWayDiagonalEvent(JoyControlStickButton *&eventbutton3)
2573 {
2574     double bearing = calculateBearing();
2575 
2576     QList<int> anglesList = getFourWayDiagonalZoneAngles();
2577     int upRightInitial = anglesList.value(0);
2578     int downRightInitial = anglesList.value(1);
2579     int downLeftInitial = anglesList.value(2);
2580     int upLeftInitial = anglesList.value(3);
2581 
2582     //bearing = floor(bearing + 0.5);
2583     if (bearing >= upRightInitial && bearing < downRightInitial)
2584     {
2585         currentDirection = StickRightUp;
2586         eventbutton3 = buttons.value(StickRightUp);
2587     }
2588     else if (bearing >= downRightInitial && bearing < downLeftInitial)
2589     {
2590         currentDirection = StickRightDown;
2591         eventbutton3 = buttons.value(StickRightDown);
2592     }
2593     else if (bearing >= downLeftInitial && bearing < upLeftInitial)
2594     {
2595         currentDirection = StickLeftDown;
2596         eventbutton3 = buttons.value(StickLeftDown);
2597     }
2598     else if (bearing >= upLeftInitial)
2599     {
2600         currentDirection = StickLeftUp;
2601         eventbutton3 = buttons.value(StickLeftUp);
2602     }
2603 }
2604 
2605 /**
2606  * @brief Find the current stick direction based on a Standard mode stick.
2607  * @return Current direction the stick is positioned.
2608  */
determineStandardModeDirection()2609 JoyControlStick::JoyStickDirections JoyControlStick::determineStandardModeDirection()
2610 {
2611     return determineStandardModeDirection(axisX->getCurrentRawValue(),
2612                                           axisY->getCurrentRawValue());
2613 }
2614 
2615 JoyControlStick::JoyStickDirections
determineStandardModeDirection(int axisXValue,int axisYValue)2616 JoyControlStick::determineStandardModeDirection(int axisXValue, int axisYValue)
2617 {
2618     JoyStickDirections result = StickCentered;
2619 
2620     double bearing = calculateBearing(axisXValue, axisYValue);
2621     //bearing = floor(bearing + 0.5);
2622 
2623     QList<double> anglesList = getDiagonalZoneAngles();
2624     int initialLeft = anglesList.value(0);
2625     int initialRight = anglesList.value(1);
2626     int upRightInitial = anglesList.value(2);
2627     int rightInitial = anglesList.value(3);
2628     int downRightInitial = anglesList.value(4);
2629     int downInitial = anglesList.value(5);
2630     int downLeftInitial = anglesList.value(6);
2631     int leftInitial = anglesList.value(7);
2632     int upLeftInitial = anglesList.value(8);
2633 
2634     if (bearing <= initialRight || bearing >= initialLeft)
2635     {
2636         result = StickUp;
2637     }
2638     else if (bearing >= upRightInitial && bearing < rightInitial)
2639     {
2640         result = StickRightUp;
2641     }
2642     else if (bearing >= rightInitial && bearing < downRightInitial)
2643     {
2644         result = StickRight;
2645     }
2646     else if (bearing >= downRightInitial && bearing < downInitial)
2647     {
2648         result = StickRightDown;
2649     }
2650     else if (bearing >= downInitial && bearing < downLeftInitial)
2651     {
2652         result = StickDown;
2653     }
2654     else if (bearing >= downLeftInitial && bearing < leftInitial)
2655     {
2656         result = StickLeftDown;
2657     }
2658     else if (bearing >= leftInitial && bearing < upLeftInitial)
2659     {
2660         result = StickLeft;
2661     }
2662     else if (bearing >= upLeftInitial && bearing < initialLeft)
2663     {
2664         result = StickLeftUp;
2665     }
2666 
2667     return result;
2668 }
2669 
2670 /**
2671  * @brief Find the current stick direction based on a Eight Way mode stick.
2672  * @return Current direction the stick is positioned.
2673  */
2674 JoyControlStick::JoyStickDirections
determineEightWayModeDirection()2675 JoyControlStick::determineEightWayModeDirection()
2676 {
2677     return determineStandardModeDirection(axisX->getCurrentRawValue(),
2678                                           axisY->getCurrentRawValue());
2679 }
2680 
2681 JoyControlStick::JoyStickDirections
determineEightWayModeDirection(int axisXValue,int axisYValue)2682 JoyControlStick::determineEightWayModeDirection(int axisXValue, int axisYValue)
2683 {
2684     return determineStandardModeDirection(axisXValue, axisYValue);
2685 }
2686 
2687 /**
2688  * @brief Find the current stick direction based on a Four Way Cardinal mode
2689  *     stick.
2690  * @return Current direction the stick is positioned.
2691  */
2692 JoyControlStick::JoyStickDirections
determineFourWayCardinalDirection()2693 JoyControlStick::determineFourWayCardinalDirection()
2694 {
2695     return determineFourWayCardinalDirection(axisX->getCurrentRawValue(),
2696                                              axisY->getCurrentRawValue());
2697 }
2698 
2699 JoyControlStick::JoyStickDirections
determineFourWayCardinalDirection(int axisXValue,int axisYValue)2700 JoyControlStick::determineFourWayCardinalDirection(int axisXValue, int axisYValue)
2701 {
2702     JoyStickDirections result = StickCentered;
2703 
2704     double bearing = calculateBearing(axisXValue, axisYValue);
2705     //bearing = floor(bearing + 0.5);
2706 
2707     QList<int> anglesList = getFourWayCardinalZoneAngles();
2708     int rightInitial = anglesList.value(0);
2709     int downInitial = anglesList.value(1);
2710     int leftInitial = anglesList.value(2);
2711     int upInitial = anglesList.value(3);
2712 
2713     if (bearing < rightInitial || bearing >= upInitial)
2714     {
2715         result = StickUp;
2716     }
2717     else if (bearing >= rightInitial && bearing < downInitial)
2718     {
2719         result = StickRight;
2720     }
2721     else if (bearing >= downInitial && bearing < leftInitial)
2722     {
2723         result = StickDown;
2724     }
2725     else if (bearing >= leftInitial && bearing < upInitial)
2726     {
2727         result = StickLeft;
2728     }
2729 
2730     return result;
2731 }
2732 
2733 /**
2734  * @brief Find the current stick direction based on a Four Way Diagonal mode
2735  *     stick.
2736  * @return Current direction the stick is positioned.
2737  */
2738 JoyControlStick::JoyStickDirections
determineFourWayDiagonalDirection()2739 JoyControlStick::determineFourWayDiagonalDirection()
2740 {
2741     return determineFourWayDiagonalDirection(axisX->getCurrentRawValue(),
2742                                              axisY->getCurrentRawValue());
2743 }
2744 
2745 JoyControlStick::JoyStickDirections
determineFourWayDiagonalDirection(int axisXValue,int axisYValue)2746 JoyControlStick::determineFourWayDiagonalDirection(int axisXValue, int axisYValue)
2747 {
2748     JoyStickDirections result = StickCentered;
2749 
2750     double bearing = calculateBearing(axisXValue, axisYValue);
2751     //bearing = floor(bearing + 0.5);
2752 
2753     QList<int> anglesList = getFourWayDiagonalZoneAngles();
2754     int upRightInitial = anglesList.value(0);
2755     int downRightInitial = anglesList.value(1);
2756     int downLeftInitial = anglesList.value(2);
2757     int upLeftInitial = anglesList.value(3);
2758 
2759     if (bearing >= upRightInitial && bearing < downRightInitial)
2760     {
2761         result = StickRightUp;
2762     }
2763     else if (bearing >= downRightInitial && bearing < downLeftInitial)
2764     {
2765         result = StickRightDown;
2766     }
2767     else if (bearing >= downLeftInitial && bearing < upLeftInitial)
2768     {
2769         result = StickLeftDown;
2770     }
2771     else if (bearing >= upLeftInitial)
2772     {
2773         result = StickLeftUp;
2774     }
2775 
2776     return result;
2777 }
2778 
2779 /**
2780  * @brief Calculate the current direction of the stick based on the values
2781  *     of the X and Y axes and the current mode of the stick.
2782  * @return Current direction the stick is positioned.
2783  */
2784 JoyControlStick::JoyStickDirections
calculateStickDirection()2785 JoyControlStick::calculateStickDirection()
2786 {
2787     return calculateStickDirection(axisX->getCurrentRawValue(),
2788                                    axisY->getCurrentRawValue());
2789 }
2790 
2791 JoyControlStick::JoyStickDirections
calculateStickDirection(int axisXValue,int axisYValue)2792 JoyControlStick::calculateStickDirection(int axisXValue, int axisYValue)
2793 {
2794     JoyStickDirections result = StickCentered;
2795 
2796     if (currentMode == StandardMode)
2797     {
2798         result = determineStandardModeDirection(axisXValue, axisYValue);
2799     }
2800     else if (currentMode == EightWayMode)
2801     {
2802         result = determineEightWayModeDirection(axisXValue, axisYValue);
2803     }
2804     else if (currentMode == FourWayCardinal)
2805     {
2806         result = determineFourWayCardinalDirection(axisXValue, axisYValue);
2807     }
2808     else if (currentMode == FourWayDiagonal)
2809     {
2810         result = determineFourWayDiagonalDirection(axisXValue, axisYValue);
2811     }
2812 
2813     return result;
2814 }
2815 
establishPropertyUpdatedConnection()2816 void JoyControlStick::establishPropertyUpdatedConnection()
2817 {
2818     connect(this, SIGNAL(propertyUpdated()), getParentSet()->getInputDevice(), SLOT(profileEdited()));
2819 }
2820 
disconnectPropertyUpdatedConnection()2821 void JoyControlStick::disconnectPropertyUpdatedConnection()
2822 {
2823     disconnect(this, SIGNAL(propertyUpdated()), getParentSet()->getInputDevice(), SLOT(profileEdited()));
2824 }
2825 
2826 /**
2827  * @brief Check all stick buttons and see if any have slots assigned.
2828  * @return Status of whether any stick button has a slot assigned.
2829  */
hasSlotsAssigned()2830 bool JoyControlStick::hasSlotsAssigned()
2831 {
2832     bool hasSlots = false;
2833 
2834     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2835     while (iter.hasNext())
2836     {
2837         JoyButton *button = iter.next().value();
2838         if (button)
2839         {
2840             if (button->getAssignedSlots()->count() > 0)
2841             {
2842                 hasSlots = true;
2843                 iter.toBack();
2844             }
2845         }
2846     }
2847 
2848     return hasSlots;
2849 }
2850 
setButtonsSpringRelativeStatus(bool value)2851 void JoyControlStick::setButtonsSpringRelativeStatus(bool value)
2852 {
2853     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2854     while (iter.hasNext())
2855     {
2856         JoyControlStickButton *button = iter.next().value();
2857         button->setSpringRelativeStatus(value);
2858     }
2859 }
2860 
isRelativeSpring()2861 bool JoyControlStick::isRelativeSpring()
2862 {
2863     bool relative = false;
2864 
2865     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2866     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2867     while (iter.hasNext())
2868     {
2869         if (!iter.hasPrevious())
2870         {
2871             JoyControlStickButton *button = iter.next().value();
2872             relative = button->isRelativeSpring();
2873         }
2874         else
2875         {
2876             JoyControlStickButton *button = iter.next().value();
2877             bool temp = button->isRelativeSpring();
2878             if (temp != relative)
2879             {
2880                 relative = false;
2881                 iter.toBack();
2882             }
2883         }
2884     }
2885 
2886     return relative;
2887 }
2888 
2889 /**
2890  * @brief Copy slots from all stick buttons and properties from a stick
2891  *     onto another.
2892  * @param JoyControlStick object to be modified.
2893  */
copyAssignments(JoyControlStick * destStick)2894 void JoyControlStick::copyAssignments(JoyControlStick *destStick)
2895 {
2896     destStick->reset();
2897     destStick->deadZone = deadZone;
2898     destStick->maxZone = maxZone;
2899     destStick->diagonalRange = diagonalRange;
2900     destStick->currentDirection = currentDirection;
2901     destStick->currentMode = currentMode;
2902     destStick->stickName = stickName;
2903     destStick->circle = circle;
2904     destStick->stickDelay = stickDelay;
2905 
2906     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(destStick->buttons);
2907     while (iter.hasNext())
2908     {
2909         JoyControlStickButton *destButton = iter.next().value();
2910         if (destButton)
2911         {
2912             JoyControlStickButton *sourceButton = buttons.value(destButton->getDirection());
2913             if (sourceButton)
2914             {
2915                 sourceButton->copyAssignments(destButton);
2916             }
2917         }
2918     }
2919 
2920     JoyControlStickModifierButton *destModifierButton = destStick->getModifierButton();
2921     if (modifierButton && destModifierButton)
2922     {
2923         modifierButton->copyAssignments(destModifierButton);
2924     }
2925 
2926     if (!destStick->isDefault())
2927     {
2928         emit propertyUpdated();
2929     }
2930 }
2931 
2932 /**
2933  * @brief Set the percentage of the outer square that should be ignored
2934  *     when performing the final axis calculations.
2935  * @param Percentage represented by the range of 0.0 - 1.0.
2936  */
setCircleAdjust(double circle)2937 void JoyControlStick::setCircleAdjust(double circle)
2938 {
2939     if (circle >= 0.0 && circle <= 1.0)
2940     {
2941         this->circle = circle;
2942         emit circleAdjustChange(circle);
2943         emit propertyUpdated();
2944     }
2945 }
2946 
2947 /**
2948  * @brief Get the current percentage of the outer square that should be ignored
2949  *     when performing the final axis calculations.
2950  * @return Percentage represented by the range of 0.0 - 1.0.
2951  */
getCircleAdjust()2952 double JoyControlStick::getCircleAdjust()
2953 {
2954     return circle;
2955 }
2956 
2957 /**
2958  * @brief Slot called when directionDelayTimer has timed out. The method will
2959  *     call createDeskEvent.
2960  */
stickDirectionChangeEvent()2961 void JoyControlStick::stickDirectionChangeEvent()
2962 {
2963     createDeskEvent();
2964 }
2965 
setStickDelay(int value)2966 void JoyControlStick::setStickDelay(int value)
2967 {
2968     if ((value >= 10 && value <= 1000) || (value == 0))
2969     {
2970         this->stickDelay = value;
2971         emit stickDelayChanged(value);
2972         emit propertyUpdated();
2973     }
2974 }
2975 
getStickDelay()2976 unsigned int JoyControlStick::getStickDelay()
2977 {
2978     return stickDelay;
2979 }
2980 
setButtonsEasingDuration(double value)2981 void JoyControlStick::setButtonsEasingDuration(double value)
2982 {
2983     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(buttons);
2984     while (iter.hasNext())
2985     {
2986         JoyControlStickButton *button = iter.next().value();
2987         button->setEasingDuration(value);
2988     }
2989 }
2990 
getButtonsEasingDuration()2991 double JoyControlStick::getButtonsEasingDuration()
2992 {
2993     double result = JoyButton::DEFAULTEASINGDURATION;
2994 
2995     QHash<JoyStickDirections, JoyControlStickButton*> temphash = getApplicableButtons();
2996     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(temphash);
2997     while (iter.hasNext())
2998     {
2999         if (!iter.hasPrevious())
3000         {
3001             JoyControlStickButton *button = iter.next().value();
3002             result = button->getEasingDuration();
3003         }
3004         else
3005         {
3006             JoyControlStickButton *button = iter.next().value();
3007             double temp = button->getEasingDuration();
3008             if (temp != result)
3009             {
3010                 result = JoyButton::DEFAULTEASINGDURATION;
3011                 iter.toBack();
3012             }
3013         }
3014     }
3015 
3016     return result;
3017 }
3018 
getModifierButton()3019 JoyControlStickModifierButton *JoyControlStick::getModifierButton()
3020 {
3021     return modifierButton;
3022 }
3023 
queueJoyEvent(bool ignoresets)3024 void JoyControlStick::queueJoyEvent(bool ignoresets)
3025 {
3026     Q_UNUSED(ignoresets);
3027 
3028     pendingStickEvent = true;
3029 }
3030 
hasPendingEvent()3031 bool JoyControlStick::hasPendingEvent()
3032 {
3033     return pendingStickEvent;
3034 }
3035 
activatePendingEvent()3036 void JoyControlStick::activatePendingEvent()
3037 {
3038     if (pendingStickEvent)
3039     {
3040         bool ignoresets = false;
3041         joyEvent(ignoresets);
3042 
3043         pendingStickEvent = false;
3044     }
3045 }
3046 
clearPendingEvent()3047 void JoyControlStick::clearPendingEvent()
3048 {
3049     pendingStickEvent = false;
3050 }
3051 
setButtonsExtraAccelerationStatus(bool enabled)3052 void JoyControlStick::setButtonsExtraAccelerationStatus(bool enabled)
3053 {
3054     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3055     while (iter.hasNext())
3056     {
3057         JoyControlStickButton *button = iter.next().value();
3058         if (button)
3059         {
3060             button->setExtraAccelerationStatus(enabled);
3061         }
3062     }
3063 }
3064 
getButtonsExtraAccelerationStatus()3065 bool JoyControlStick::getButtonsExtraAccelerationStatus()
3066 {
3067     bool result = false;
3068 
3069     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3070     while (iter.hasNext())
3071     {
3072         JoyControlStickButton *button = iter.next().value();
3073         if (button)
3074         {
3075             bool temp = button->isExtraAccelerationEnabled();
3076             if (!temp)
3077             {
3078                 result = false;
3079                 iter.toBack();
3080             }
3081             else
3082             {
3083                 result = temp;
3084             }
3085         }
3086     }
3087 
3088     return result;
3089 }
3090 
setButtonsExtraAccelerationMultiplier(double value)3091 void JoyControlStick::setButtonsExtraAccelerationMultiplier(double value)
3092 {
3093     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3094     while (iter.hasNext())
3095     {
3096         JoyControlStickButton *button = iter.next().value();
3097         if (button)
3098         {
3099             button->setExtraAccelerationMultiplier(value);
3100         }
3101     }
3102 }
3103 
getButtonsExtraAccelerationMultiplier()3104 double JoyControlStick::getButtonsExtraAccelerationMultiplier()
3105 {
3106     double result = JoyButton::DEFAULTEXTRACCELVALUE;
3107 
3108     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3109     while (iter.hasNext())
3110     {
3111         if (!iter.hasPrevious())
3112         {
3113             JoyControlStickButton *button = iter.next().value();
3114             if (button)
3115             {
3116                 result = button->getExtraAccelerationMultiplier();
3117             }
3118         }
3119         else
3120         {
3121             JoyControlStickButton *button = iter.next().value();
3122             if (button)
3123             {
3124                 double temp = button->getExtraAccelerationMultiplier();
3125                 if (temp != result)
3126                 {
3127                     result = JoyButton::DEFAULTEXTRACCELVALUE;
3128                     iter.toBack();
3129                 }
3130             }
3131         }
3132     }
3133 
3134     return result;
3135 }
3136 
3137 
setButtonsStartAccelerationMultiplier(double value)3138 void JoyControlStick::setButtonsStartAccelerationMultiplier(double value)
3139 {
3140     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3141     while (iter.hasNext())
3142     {
3143         JoyControlStickButton *button = iter.next().value();
3144         if (button)
3145         {
3146             button->setStartAccelMultiplier(value);
3147         }
3148     }
3149 }
3150 
getButtonsStartAccelerationMultiplier()3151 double JoyControlStick::getButtonsStartAccelerationMultiplier()
3152 {
3153     double result = JoyButton::DEFAULTSTARTACCELMULTIPLIER;
3154 
3155     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3156     while (iter.hasNext())
3157     {
3158         if (!iter.hasPrevious())
3159         {
3160             JoyControlStickButton *button = iter.next().value();
3161             if (button)
3162             {
3163                 result = button->getStartAccelMultiplier();
3164             }
3165         }
3166         else
3167         {
3168             JoyControlStickButton *button = iter.next().value();
3169             if (button)
3170             {
3171                 double temp = button->getStartAccelMultiplier();
3172                 if (temp != result)
3173                 {
3174                     result = JoyButton::DEFAULTSTARTACCELMULTIPLIER;
3175                     iter.toBack();
3176                 }
3177             }
3178         }
3179     }
3180 
3181     return result;
3182 }
3183 
setButtonsMinAccelerationThreshold(double value)3184 void JoyControlStick::setButtonsMinAccelerationThreshold(double value)
3185 {
3186     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3187     while (iter.hasNext())
3188     {
3189         JoyControlStickButton *button = iter.next().value();
3190         if (button)
3191         {
3192             button->setMinAccelThreshold(value);
3193         }
3194     }
3195 }
3196 
getButtonsMinAccelerationThreshold()3197 double JoyControlStick::getButtonsMinAccelerationThreshold()
3198 {
3199     double result = JoyButton::DEFAULTMINACCELTHRESHOLD;
3200 
3201     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3202     while (iter.hasNext())
3203     {
3204         if (!iter.hasPrevious())
3205         {
3206             JoyControlStickButton *button = iter.next().value();
3207             if (button)
3208             {
3209                 result = button->getMinAccelThreshold();
3210             }
3211         }
3212         else
3213         {
3214             JoyControlStickButton *button = iter.next().value();
3215             if (button)
3216             {
3217                 double temp = button->getMinAccelThreshold();
3218                 if (temp != result)
3219                 {
3220                     result = JoyButton::DEFAULTMINACCELTHRESHOLD;
3221                     iter.toBack();
3222                 }
3223             }
3224         }
3225     }
3226 
3227     return result;
3228 }
3229 
setButtonsMaxAccelerationThreshold(double value)3230 void JoyControlStick::setButtonsMaxAccelerationThreshold(double value)
3231 {
3232     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3233     while (iter.hasNext())
3234     {
3235         JoyControlStickButton *button = iter.next().value();
3236         if (button)
3237         {
3238             button->setMaxAccelThreshold(value);
3239         }
3240     }
3241 }
3242 
getButtonsMaxAccelerationThreshold()3243 double JoyControlStick::getButtonsMaxAccelerationThreshold()
3244 {
3245     double result = JoyButton::DEFAULTMAXACCELTHRESHOLD;
3246 
3247     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3248     while (iter.hasNext())
3249     {
3250         if (!iter.hasPrevious())
3251         {
3252             JoyControlStickButton *button = iter.next().value();
3253             if (button)
3254             {
3255                 result = button->getMaxAccelThreshold();
3256             }
3257         }
3258         else
3259         {
3260             JoyControlStickButton *button = iter.next().value();
3261             if (button)
3262             {
3263                 double temp = button->getMaxAccelThreshold();
3264                 if (temp != result)
3265                 {
3266                     result = JoyButton::DEFAULTMAXACCELTHRESHOLD;
3267                     iter.toBack();
3268                 }
3269             }
3270         }
3271     }
3272 
3273     return result;
3274 }
3275 
3276 
setButtonsAccelerationExtraDuration(double value)3277 void JoyControlStick::setButtonsAccelerationExtraDuration(double value)
3278 {
3279     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3280     while (iter.hasNext())
3281     {
3282         JoyControlStickButton *button = iter.next().value();
3283         if (button)
3284         {
3285             button->setAccelExtraDuration(value);
3286         }
3287     }
3288 }
3289 
getButtonsAccelerationEasingDuration()3290 double JoyControlStick::getButtonsAccelerationEasingDuration()
3291 {
3292     double result = JoyButton::DEFAULTACCELEASINGDURATION;
3293 
3294     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3295     while (iter.hasNext())
3296     {
3297         if (!iter.hasPrevious())
3298         {
3299             JoyControlStickButton *button = iter.next().value();
3300             if (button)
3301             {
3302                 result = button->getAccelExtraDuration();
3303             }
3304         }
3305         else
3306         {
3307             JoyControlStickButton *button = iter.next().value();
3308             if (button)
3309             {
3310                 double temp = button->getAccelExtraDuration();
3311                 if (temp != result)
3312                 {
3313                     result = JoyButton::DEFAULTACCELEASINGDURATION;
3314                     iter.toBack();
3315                 }
3316             }
3317         }
3318     }
3319 
3320     return result;
3321 }
3322 
setButtonsSpringDeadCircleMultiplier(int value)3323 void JoyControlStick::setButtonsSpringDeadCircleMultiplier(int value)
3324 {
3325     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3326     while (iter.hasNext())
3327     {
3328         JoyControlStickButton *button = iter.next().value();
3329         if (button)
3330         {
3331             button->setSpringDeadCircleMultiplier(value);
3332         }
3333     }
3334 }
3335 
getButtonsSpringDeadCircleMultiplier()3336 int JoyControlStick::getButtonsSpringDeadCircleMultiplier()
3337 {
3338     int result = JoyButton::DEFAULTSPRINGRELEASERADIUS;
3339 
3340     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
3341     while (iter.hasNext())
3342     {
3343         if (!iter.hasPrevious())
3344         {
3345             JoyControlStickButton *button = iter.next().value();
3346             if (button)
3347             {
3348                 result = button->getSpringDeadCircleMultiplier();
3349             }
3350         }
3351         else
3352         {
3353             JoyControlStickButton *button = iter.next().value();
3354             if (button)
3355             {
3356                 int temp = button->getSpringDeadCircleMultiplier();
3357                 if (temp != result)
3358                 {
3359                     result = JoyButton::DEFAULTSPRINGRELEASERADIUS;
3360                     iter.toBack();
3361                 }
3362             }
3363         }
3364     }
3365 
3366     return result;
3367 }
3368 
calculateAccelerationDistance(JoyControlStickButton * button)3369 double JoyControlStick::calculateAccelerationDistance(JoyControlStickButton *button)
3370 {
3371     double finalDistance = 0.0;
3372 
3373     if (currentDirection == StickUp)
3374     {
3375         if (axisY->getCurrentRawValue() >= 0)
3376         {
3377             finalDistance = 0.0;
3378         }
3379         else
3380         {
3381             finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
3382         }
3383     }
3384     else if (currentDirection == StickRightUp)
3385     {
3386         if (button->getJoyNumber() == StickRight)
3387         {
3388             if (axisX->getCurrentRawValue() < 0)
3389             {
3390                 finalDistance = 0.0;
3391             }
3392             else
3393             {
3394                 finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
3395             }
3396 
3397         }
3398         else if (button->getJoyNumber() == StickUp)
3399         {
3400             if (axisY->getCurrentRawValue() >= 0)
3401             {
3402                 finalDistance = 0.0;
3403             }
3404             else
3405             {
3406                 finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
3407             }
3408         }
3409         else if (button->getJoyNumber() == StickRightUp)
3410         {
3411             if (axisX->getCurrentRawValue() <= 0 || axisY->getCurrentRawValue() >= 0)
3412             {
3413                 finalDistance = 0.0;
3414             }
3415             else
3416             {
3417                 finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
3418             }
3419         }
3420     }
3421     else if (currentDirection == StickRight)
3422     {
3423         if (axisX->getCurrentRawValue() < 0)
3424         {
3425             finalDistance = 0.0;
3426         }
3427         else
3428         {
3429             finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
3430         }
3431     }
3432     else if (currentDirection  == StickRightDown)
3433     {
3434         if (button->getJoyNumber() == StickRight)
3435         {
3436             if (axisX->getCurrentRawValue() < 0)
3437             {
3438                 finalDistance = 0.0;
3439             }
3440             else
3441             {
3442                 finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
3443             }
3444         }
3445         else if (button->getJoyNumber() == StickDown)
3446         {
3447             if (axisY->getCurrentRawValue() < 0)
3448             {
3449                 finalDistance = 0.0;
3450             }
3451             else
3452             {
3453                 finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
3454             }
3455         }
3456         else if (button->getJoyNumber() == StickRightDown)
3457         {
3458             if (axisX->getCurrentRawValue() <= 0 || axisY->getCurrentRawValue() <= 0)
3459             {
3460                 finalDistance = 0.0;
3461             }
3462             else
3463             {
3464                 finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
3465             }
3466         }
3467     }
3468     else if (currentDirection == StickDown)
3469     {
3470         if (axisY->getCurrentRawValue() <= 0)
3471         {
3472             finalDistance = 0.0;
3473         }
3474         else
3475         {
3476             finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
3477         }
3478     }
3479     else if (currentDirection == StickLeftDown)
3480     {
3481         if (button->getJoyNumber() == StickLeft)
3482         {
3483             if (axisX->getCurrentRawValue() >= 0)
3484             {
3485                 finalDistance = 0.0;
3486             }
3487             else
3488             {
3489                 finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
3490             }
3491         }
3492         else if (button->getJoyNumber() == StickDown)
3493         {
3494             if (axisY->getCurrentRawValue() < 0)
3495             {
3496                 finalDistance = 0.0;
3497             }
3498             else
3499             {
3500                 finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
3501             }
3502         }
3503         else if (button->getJoyNumber() == StickLeftDown)
3504         {
3505             if (axisX->getCurrentRawValue() >= 0 || axisY->getCurrentRawValue() <= 0)
3506             {
3507                 finalDistance = 0.0;
3508             }
3509             else
3510             {
3511                 finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
3512             }
3513         }
3514     }
3515     else if (currentDirection == StickLeft)
3516     {
3517         if (axisX->getCurrentRawValue() >= 0)
3518         {
3519             finalDistance = 0.0;
3520         }
3521         else
3522         {
3523             finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
3524         }
3525     }
3526     else if (currentDirection == StickLeftUp)
3527     {
3528         if (button->getJoyNumber() == StickLeft)
3529         {
3530             if (axisX->getCurrentRawValue() >= 0)
3531             {
3532                 finalDistance = 0.0;
3533             }
3534             else
3535             {
3536                 finalDistance = calculateXAxisDistance(axisX->getCurrentRawValue());
3537             }
3538         }
3539         else if (button->getJoyNumber() == StickUp)
3540         {
3541             if (axisY->getCurrentRawValue() >= 0)
3542             {
3543                 finalDistance = 0.0;
3544             }
3545             else
3546             {
3547                 finalDistance = calculateYAxisDistance(axisY->getCurrentRawValue());
3548             }
3549         }
3550         else if (button->getJoyNumber() == StickLeftUp)
3551         {
3552             if (axisX->getCurrentRawValue() >= 0 || axisY->getCurrentRawValue() >= 0)
3553             {
3554                 finalDistance = 0.0;
3555             }
3556             else
3557             {
3558                 finalDistance = calculateEightWayDiagonalDistance(axisX->getCurrentRawValue(), axisY->getCurrentRawValue());
3559             }
3560         }
3561     }
3562 
3563     return finalDistance;
3564 }
3565 
3566 // TODO: Maybe change method name.
calculateLastAccelerationButtonDistance(JoyControlStickButton * button)3567 double JoyControlStick::calculateLastAccelerationButtonDistance(JoyControlStickButton *button)
3568 {
3569     double finalDistance = 0.0;
3570 
3571     if (currentDirection == StickUp)
3572     {
3573         if (axisY->getLastKnownRawValue() >= 0)
3574         {
3575             finalDistance = 0.0;
3576         }
3577         else
3578         {
3579             finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
3580         }
3581     }
3582     else if (currentDirection == StickRightUp)
3583     {
3584         if (button->getJoyNumber() == StickRight)
3585         {
3586             if (axisX->getLastKnownRawValue() <= 0)
3587             {
3588                 finalDistance = 0.0;
3589             }
3590             else
3591             {
3592                 finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
3593             }
3594 
3595         }
3596         else if (button->getJoyNumber() == StickUp)
3597         {
3598             if (axisY->getLastKnownRawValue() >= 0)
3599             {
3600                 finalDistance = 0.0;
3601             }
3602             else
3603             {
3604                 finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
3605             }
3606         }
3607         else if (button->getJoyNumber() == StickRightUp)
3608         {
3609             if (axisX->getLastKnownRawValue() <= 0 || axisY->getLastKnownRawValue() >= 0)
3610             {
3611                 finalDistance = 0.0;
3612             }
3613             else
3614             {
3615                 finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
3616             }
3617         }
3618     }
3619     else if (currentDirection == StickRight)
3620     {
3621         if (axisX->getLastKnownRawValue() <= 0)
3622         {
3623             finalDistance = 0.0;
3624         }
3625         else
3626         {
3627             finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
3628         }
3629     }
3630     else if (currentDirection  == StickRightDown)
3631     {
3632         if (button->getJoyNumber() == StickRight)
3633         {
3634             if (axisX->getLastKnownRawValue() <= 0)
3635             {
3636                 finalDistance = 0.0;
3637             }
3638             else
3639             {
3640                 finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
3641             }
3642         }
3643         else if (button->getJoyNumber() == StickDown)
3644         {
3645             if (axisY->getLastKnownRawValue() <= 0)
3646             {
3647                 finalDistance = 0.0;
3648             }
3649             else
3650             {
3651                 finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
3652             }
3653         }
3654         else if (button->getJoyNumber() == StickRightDown)
3655         {
3656             if (axisX->getLastKnownRawValue() <= 0 || axisY->getLastKnownRawValue() <= 0)
3657             {
3658                 finalDistance = 0.0;
3659             }
3660             else
3661             {
3662                 finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
3663             }
3664         }
3665     }
3666     else if (currentDirection == StickDown)
3667     {
3668         if (axisY->getLastKnownRawValue() <= 0)
3669         {
3670             finalDistance = 0.0;
3671         }
3672         else
3673         {
3674             finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
3675         }
3676     }
3677     else if (currentDirection == StickLeftDown)
3678     {
3679         if (button->getJoyNumber() == StickLeft)
3680         {
3681             if (axisX->getLastKnownRawValue() >= 0)
3682             {
3683                 finalDistance = 0.0;
3684             }
3685             else
3686             {
3687                 finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
3688             }
3689         }
3690         else if (button->getJoyNumber() == StickDown)
3691         {
3692             if (axisY->getLastKnownRawValue() <= 0)
3693             {
3694                 finalDistance = 0.0;
3695             }
3696             else
3697             {
3698                 finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
3699             }
3700         }
3701         else if (button->getJoyNumber() == StickLeftDown)
3702         {
3703             if (axisX->getLastKnownRawValue() >= 0 || axisY->getLastKnownRawValue() <= 0)
3704             {
3705                 finalDistance = 0.0;
3706             }
3707             else
3708             {
3709                 finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
3710             }
3711         }
3712     }
3713     else if (currentDirection == StickLeft)
3714     {
3715         if (axisX->getLastKnownRawValue() >= 0)
3716         {
3717             finalDistance = 0.0;
3718         }
3719         else
3720         {
3721             finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
3722         }
3723     }
3724     else if (currentDirection == StickLeftUp)
3725     {
3726         if (button->getJoyNumber() == StickLeft)
3727         {
3728             if (axisX->getLastKnownRawValue() >= 0)
3729             {
3730                 finalDistance = 0.0;
3731             }
3732             else
3733             {
3734                 finalDistance = calculateXAxisDistance(axisX->getLastKnownRawValue());
3735             }
3736         }
3737         else if (button->getJoyNumber() == StickUp)
3738         {
3739             if (axisY->getLastKnownRawValue() >= 0)
3740             {
3741                 finalDistance = 0.0;
3742             }
3743             else
3744             {
3745                 finalDistance = calculateYAxisDistance(axisY->getLastKnownRawValue());
3746             }
3747         }
3748         else if (button->getJoyNumber() == StickLeftUp)
3749         {
3750             if (axisX->getLastKnownRawValue() >= 0 || axisY->getLastKnownRawValue() >= 0)
3751             {
3752                 finalDistance = 0.0;
3753             }
3754             else
3755             {
3756                 finalDistance = calculateEightWayDiagonalDistance(axisX->getLastKnownRawValue(), axisY->getLastKnownRawValue());
3757             }
3758         }
3759     }
3760 
3761     return finalDistance;
3762 }
3763 
calculateXAxisDistance(int axisXValue)3764 double JoyControlStick::calculateXAxisDistance(int axisXValue)
3765 {
3766     double distance = 0.0;
3767     int axis1Value = axisXValue;
3768 
3769     distance = axis1Value / (double)(maxZone);
3770     if (distance < -1.0)
3771     {
3772         distance = -1.0;
3773     }
3774     else if (distance > 1.0)
3775     {
3776         distance = 1.0;
3777     }
3778 
3779     //qDebug() << "DISTANCE: " << distance;
3780 
3781     return distance;
3782 }
3783 
calculateYAxisDistance(int axisYValue)3784 double JoyControlStick::calculateYAxisDistance(int axisYValue)
3785 {
3786     double distance = 0.0;
3787     int axis2Value = axisYValue;
3788 
3789     distance = axis2Value / (double)(maxZone);
3790     if (distance < -1.0)
3791     {
3792         distance = -1.0;
3793     }
3794     else if (distance > 1.0)
3795     {
3796         distance = 1.0;
3797     }
3798 
3799     return distance;
3800 }
3801 
calculateEightWayDiagonalDistanceFromDeadZone()3802 double JoyControlStick::calculateEightWayDiagonalDistanceFromDeadZone()
3803 {
3804     double temp = calculateEightWayDiagonalDistanceFromDeadZone(axisX->getCurrentRawValue(),
3805                                                                 axisY->getCurrentRawValue());
3806     return temp;
3807 }
3808 
calculateEightWayDiagonalDistanceFromDeadZone(int axisXValue,int axisYValue)3809 double JoyControlStick::calculateEightWayDiagonalDistanceFromDeadZone(int axisXValue, int axisYValue)
3810 {
3811     double distance = 0.0;
3812 
3813     double radius = getDistanceFromDeadZone(axisXValue, axisYValue);
3814     double bearing = calculateBearing(axisXValue, axisYValue);
3815     int relativeBearing = static_cast<int>(bearing) % 90;
3816 
3817     int diagonalAngle = relativeBearing;
3818     if (relativeBearing > 45)
3819     {
3820         diagonalAngle = 90 - relativeBearing;
3821     }
3822 
3823     distance = radius * (diagonalAngle / 45.0);
3824 
3825     return distance;
3826 }
3827 
calculateEightWayDiagonalDistance(int axisXValue,int axisYValue)3828 double JoyControlStick::calculateEightWayDiagonalDistance(int axisXValue, int axisYValue)
3829 {
3830     double distance = 0.0;
3831 
3832     double radius = getRadialDistance(axisXValue, axisYValue);
3833     double bearing = calculateBearing(axisXValue, axisYValue);
3834     int relativeBearing = static_cast<int>(bearing) % 90;
3835 
3836     int diagonalAngle = relativeBearing;
3837     if (relativeBearing > 45)
3838     {
3839         diagonalAngle = 90 - relativeBearing;
3840     }
3841 
3842     distance = radius * (diagonalAngle / 45.0);
3843 
3844     return distance;
3845 }
3846 
calculateXDiagonalDeadZone(int axisXValue,int axisYValue)3847 double JoyControlStick::calculateXDiagonalDeadZone(int axisXValue, int axisYValue)
3848 {
3849     double diagonalDeadZone = 0.0;
3850     JoyStickDirections direction = calculateStickDirection(axisXValue, axisYValue);
3851     //double angle2 = atan2(axisXValue, -axisYValue);
3852     //double ang_sin = sin(angle2);
3853     //double ang_cos = cos(angle2);
3854     //int deadX = abs((int)floor(deadZone * ang_sin + 0.5));
3855 
3856     if (diagonalRange < 90)
3857     {
3858         if (direction == StickRightUp || direction == StickRight)
3859         {
3860             QList<double> tempangles = getDiagonalZoneAngles();
3861             double maxangle = tempangles.at(3);
3862             //double minangle = tempangles.at(1);
3863             double mindeadX = fabs(deadZone * cos(maxangle * PI / 180.0));
3864             //double currentDeadX = qMax(mindeadX, static_cast<double>(deadX));
3865             diagonalDeadZone = mindeadX;
3866         }
3867         else if (direction == StickRightDown || direction == StickDown)
3868         {
3869             QList<double> tempangles = getDiagonalZoneAngles();
3870             double maxangle = tempangles.at(5);
3871             //double minangle = tempangles.at(4);
3872             double mindeadX = fabs(deadZone * cos((maxangle - 90.0) * PI / 180.0));
3873             //double currentDeadX = qMax(mindeadX, static_cast<double>(deadX));
3874             diagonalDeadZone = mindeadX;
3875         }
3876         else if (direction == StickLeftDown || direction == StickLeft)
3877         {
3878             QList<double> tempangles = getDiagonalZoneAngles();
3879             double maxangle = tempangles.at(7);
3880             //double minangle = tempangles.at(6);
3881             double mindeadX = fabs(deadZone * cos((maxangle - 180.0) * PI / 180.0));
3882             //double currentDeadX = qMax(mindeadX, static_cast<double>(deadX));
3883             diagonalDeadZone = mindeadX;
3884         }
3885         else if (direction == StickLeftUp || direction == StickUp)
3886         {
3887             QList<double> tempangles = getDiagonalZoneAngles();
3888             double maxangle = tempangles.at(1);
3889             //double minangle = tempangles.at(8);
3890             double mindeadX = fabs(deadZone * cos((maxangle - 270.0) * PI / 180.0));
3891             //double currentDeadX = qMax(mindeadX, static_cast<double>(deadX));
3892             diagonalDeadZone = mindeadX;
3893         }
3894         else
3895         {
3896             diagonalDeadZone = 0.0;
3897         }
3898     }
3899     else
3900     {
3901         diagonalDeadZone = 0.0;
3902     }
3903 
3904     return diagonalDeadZone;
3905 }
3906 
calculateYDiagonalDeadZone(int axisXValue,int axisYValue)3907 double JoyControlStick::calculateYDiagonalDeadZone(int axisXValue, int axisYValue)
3908 {
3909     double diagonalDeadZone = 0.0;
3910     JoyStickDirections direction = calculateStickDirection(axisXValue, axisYValue);
3911     //double angle2 = atan2(axisXValue, -axisYValue);
3912     //double ang_sin = sin(angle2);
3913     //double ang_cos = cos(angle2);
3914     //int deadY = abs(floor(deadZone * ang_cos + 0.5));
3915 
3916     if (diagonalRange < 90)
3917     {
3918         if (direction == StickRightUp || direction == StickUp)
3919         {
3920             QList<double> tempangles = getDiagonalZoneAngles();
3921             //double maxangle = tempangles.at(3);
3922             double minangle = tempangles.at(1);
3923             double mindeadY = fabs(deadZone * sin(minangle * PI / 180.0));
3924             //double currentDeadY = qMax(static_cast<double>(deadY), mindeadY);
3925             diagonalDeadZone = mindeadY;
3926         }
3927         else if (direction == StickRightDown || direction == StickRight)
3928         {
3929             QList<double> tempfuck = getDiagonalZoneAngles();
3930             //double maxangle = tempfuck.at(5);
3931             double minangle = tempfuck.at(4);
3932             double mindeadY = fabs(deadZone * sin((minangle - 90.0) * PI / 180.0));
3933             //double currentDeadY = qMax(static_cast<double>(deadY), mindeadY);
3934             diagonalDeadZone = mindeadY;
3935         }
3936         else if (direction == StickLeftDown || direction == StickDown)
3937         {
3938             QList<double> tempangles = getDiagonalZoneAngles();
3939             //double maxangle = tempangles.at(7);
3940             double minangle = tempangles.at(6);
3941             double mindeadY = fabs(deadZone * sin((minangle - 180.0) * PI / 180.0));
3942             //double currentDeadY = qMax(static_cast<double>(deadY), mindeadY);
3943             diagonalDeadZone = mindeadY;
3944         }
3945         else if (direction == StickLeftUp || direction == StickLeft)
3946         {
3947             QList<double> tempangles = getDiagonalZoneAngles();
3948             //double maxangle = tempangles.at(1);
3949             double minangle = tempangles.at(8);
3950             double mindeadY = fabs(deadZone * sin((minangle - 270.0) * PI / 180.0));
3951             //double currentDeadY = qMax(static_cast<double>(deadY), mindeadY);
3952             diagonalDeadZone = mindeadY;
3953         }
3954         else
3955         {
3956             diagonalDeadZone = 0.0;
3957         }
3958     }
3959     else
3960     {
3961         diagonalDeadZone = 0.0;
3962     }
3963 
3964     return diagonalDeadZone;
3965 }
3966 
getSpringDeadCircleX()3967 double JoyControlStick::getSpringDeadCircleX()
3968 {
3969     double result = 0.0;
3970 
3971     double angle2 = 0.0;
3972     int axis1Value = 0;
3973     int axis2Value = 0;
3974 
3975     if (axisX->getCurrentRawValue() == 0 && axisY->getCurrentRawValue() == 0)
3976     {
3977         // Stick moved back to absolute center. Use previously available values
3978         // to find stick angle.
3979         angle2 = atan2(axisX->getLastKnownRawValue(), -axisY->getLastKnownRawValue());
3980         axis1Value = axisX->getLastKnownRawValue();
3981         axis2Value = axisY->getLastKnownRawValue();
3982     }
3983     else
3984     {
3985         // Use current axis values to find stick angle.
3986         angle2 = atan2(axisX->getCurrentRawValue(), -axisY->getCurrentRawValue());
3987         axis1Value = axisX->getCurrentRawValue();
3988         axis2Value = axisY->getCurrentRawValue();
3989     }
3990 
3991     double ang_sin = sin(angle2);
3992     double ang_cos = cos(angle2);
3993 
3994     int deadX = abs((int)floor(deadZone * ang_sin + 0.5));
3995     double diagonalDeadX = calculateXDiagonalDeadZone(axis1Value, axis2Value);
3996 
3997     double squareStickFullPhi = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
3998     double circle = this->circle;
3999     double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
4000 
4001     double adjustedDeadXZone = circleStickFull > 1.0 ? (deadX / circleStickFull) : deadX;
4002     //result = adjustedDeadXZone / static_cast<double>(deadZone);
4003     double finalDeadZoneX = adjustedDeadXZone - diagonalDeadX;
4004     double maxRange = static_cast<double>(deadZone - diagonalDeadX);
4005 
4006     if (maxRange != 0.0)
4007     {
4008         result = finalDeadZoneX / maxRange;
4009     }
4010 
4011     return result;
4012 }
4013 
getSpringDeadCircleY()4014 double JoyControlStick::getSpringDeadCircleY()
4015 {
4016     double result = 0.0;
4017 
4018     double angle2 = 0.0;
4019     int axis1Value = 0;
4020     int axis2Value = 0;
4021 
4022     if (axisX->getCurrentRawValue() == 0 && axisY->getCurrentRawValue() == 0)
4023     {
4024         // Stick moved back to absolute center. Use previously available values
4025         // to find stick angle.
4026         angle2 = atan2(axisX->getLastKnownRawValue(), -axisY->getLastKnownRawValue());
4027         axis1Value = axisX->getLastKnownRawValue();
4028         axis2Value = axisY->getLastKnownRawValue();
4029     }
4030     else
4031     {
4032         // Use current axis values to find stick angle.
4033         angle2 = atan2(axisX->getCurrentRawValue(), -axisY->getCurrentRawValue());
4034         axis1Value = axisX->getCurrentRawValue();
4035         axis2Value = axisY->getCurrentRawValue();
4036     }
4037 
4038     double ang_sin = sin(angle2);
4039     double ang_cos = cos(angle2);
4040 
4041     int deadY = abs((int)floor(deadZone * ang_cos + 0.5));
4042     double diagonalDeadY = calculateYDiagonalDeadZone(axis1Value, axis2Value);
4043 
4044     double squareStickFullPhi = qMin(ang_sin ? 1/fabs(ang_sin) : 2, ang_cos ? 1/fabs(ang_cos) : 2);
4045     double circle = this->circle;
4046     double circleStickFull = (squareStickFullPhi - 1) * circle + 1;
4047 
4048     double adjustedDeadYZone = circleStickFull > 1.0 ? (deadY / circleStickFull) : deadY;
4049     //result = adjustedDeadYZone / static_cast<double>(deadZone);
4050     double finalDeadZoneY = adjustedDeadYZone - diagonalDeadY;
4051     double maxRange = static_cast<double>(deadZone - diagonalDeadY);
4052 
4053     if (maxRange != 0.0)
4054     {
4055         result = finalDeadZoneY / maxRange;
4056     }
4057 
4058     return result;
4059 }
4060 
setButtonsExtraAccelCurve(JoyButton::JoyExtraAccelerationCurve curve)4061 void JoyControlStick::setButtonsExtraAccelCurve(JoyButton::JoyExtraAccelerationCurve curve)
4062 {
4063     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
4064     while (iter.hasNext())
4065     {
4066         JoyControlStickButton *button = iter.next().value();
4067         if (button)
4068         {
4069             button->setExtraAccelerationCurve(curve);
4070         }
4071     }
4072 }
4073 
getButtonsExtraAccelerationCurve()4074 JoyButton::JoyExtraAccelerationCurve JoyControlStick::getButtonsExtraAccelerationCurve()
4075 {
4076     JoyButton::JoyExtraAccelerationCurve result = JoyButton::LinearAccelCurve;
4077 
4078     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(getApplicableButtons());
4079     while (iter.hasNext())
4080     {
4081         if (!iter.hasPrevious())
4082         {
4083             JoyControlStickButton *button = iter.next().value();
4084             if (button)
4085             {
4086                 result = button->getExtraAccelerationCurve();
4087             }
4088         }
4089         else
4090         {
4091             JoyControlStickButton *button = iter.next().value();
4092             if (button)
4093             {
4094                 JoyButton::JoyExtraAccelerationCurve temp = button->getExtraAccelerationCurve();
4095                 if (temp != result)
4096                 {
4097                     result = JoyButton::LinearAccelCurve;
4098                     iter.toBack();
4099                 }
4100             }
4101         }
4102     }
4103 
4104     return result;
4105 }
4106 
4107 void
setDirButtonsUpdateInitAccel(JoyControlStick::JoyStickDirections direction,bool state)4108 JoyControlStick::setDirButtonsUpdateInitAccel(JoyControlStick::JoyStickDirections direction, bool state)
4109 {
4110     QHash<JoyStickDirections, JoyControlStickButton*> apphash = getButtonsForDirection(direction);
4111     QHashIterator<JoyStickDirections, JoyControlStickButton*> iter(apphash);
4112     while (iter.hasNext())
4113     {
4114         JoyControlStickButton *button = iter.next().value();
4115         button->setUpdateInitAccel(state);
4116     }
4117 }
4118 
4119 
4120 QHash<JoyControlStick::JoyStickDirections, JoyControlStickButton*>
getButtonsForDirection(JoyControlStick::JoyStickDirections direction)4121 JoyControlStick::getButtonsForDirection(JoyControlStick::JoyStickDirections direction)
4122 {
4123     QHash<JoyStickDirections, JoyControlStickButton*> temphash;
4124     if (currentMode == StandardMode)
4125     {
4126         if (direction & JoyControlStick::StickUp)
4127         {
4128             JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickUp);
4129             temphash.insert(JoyControlStick::StickUp, button);
4130         }
4131 
4132         if (direction & JoyControlStick::StickRight)
4133         {
4134             JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickRight);
4135             temphash.insert(JoyControlStick::StickRight, button);
4136         }
4137 
4138         if (direction & JoyControlStick::StickDown)
4139         {
4140             JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickDown);
4141             temphash.insert(JoyControlStick::StickDown, button);
4142         }
4143 
4144         if (direction & JoyControlStick::StickLeft)
4145         {
4146             JoyControlStickButton *button = this->buttons.value(JoyControlStick::StickLeft);
4147             temphash.insert(JoyControlStick::StickLeft, button);
4148         }
4149     }
4150     else if (currentMode == EightWayMode)
4151     {
4152         temphash.insert(direction, buttons.value(direction));
4153     }
4154     else if (currentMode == FourWayCardinal)
4155     {
4156         if (direction == JoyControlStick::StickUp ||
4157             direction == JoyControlStick::StickDown ||
4158             direction == JoyControlStick::StickLeft ||
4159             direction == JoyControlStick::StickRight)
4160         {
4161             temphash.insert(direction, buttons.value(direction));
4162         }
4163 
4164     }
4165     else if (currentMode == FourWayDiagonal)
4166     {
4167         if (direction == JoyControlStick::StickRightUp ||
4168             direction == JoyControlStick::StickRightDown ||
4169             direction == JoyControlStick::StickLeftDown ||
4170             direction == JoyControlStick::StickLeftUp)
4171         {
4172             temphash.insert(direction, buttons.value(direction));
4173         }
4174     }
4175 
4176     return temphash;
4177 }
4178