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 <cmath>
20 
21 #include "joyaxis.h"
22 #include "joycontrolstick.h"
23 #include "inputdevice.h"
24 #include "event.h"
25 
26 // Set default values for many properties.
27 const int JoyAxis::AXISMIN = -32767;
28 const int JoyAxis::AXISMAX = 32767;
29 const int JoyAxis::AXISDEADZONE = 6000;
30 const int JoyAxis::AXISMAXZONE = 32000;
31 
32 // Speed in pixels/second
33 const float JoyAxis::JOYSPEED = 20.0;
34 
35 const JoyAxis::ThrottleTypes JoyAxis::DEFAULTTHROTTLE = JoyAxis::NormalThrottle;
36 
37 const QString JoyAxis::xmlName = "axis";
38 
JoyAxis(int index,int originset,SetJoystick * parentSet,QObject * parent)39 JoyAxis::JoyAxis(int index, int originset, SetJoystick *parentSet,
40                  QObject *parent) :
41     QObject(parent)
42 {
43     stick = 0;
44     lastKnownThottledValue = 0;
45     lastKnownRawValue = 0;
46     this->originset = originset;
47     this->parentSet = parentSet;
48     naxisbutton = new JoyAxisButton(this, 0, originset, parentSet, this);
49     paxisbutton = new JoyAxisButton(this, 1, originset, parentSet, this);
50 
51     reset();
52     this->index = index;
53 }
54 
~JoyAxis()55 JoyAxis::~JoyAxis()
56 {
57     reset();
58 }
59 
queuePendingEvent(int value,bool ignoresets,bool updateLastValues)60 void JoyAxis::queuePendingEvent(int value, bool ignoresets, bool updateLastValues)
61 {
62     pendingEvent = false;
63     pendingValue = 0;
64     pendingIgnoreSets = false;
65     //pendingUpdateLastValues = true;
66 
67     if (this->stick)
68     {
69         stickPassEvent(value, ignoresets, updateLastValues);
70     }
71     else
72     {
73         pendingEvent = true;
74         pendingValue = value;
75         pendingIgnoreSets = ignoresets;
76         //pendingUpdateLastValues = updateLastValues;
77     }
78 }
79 
activatePendingEvent()80 void JoyAxis::activatePendingEvent()
81 {
82     if (pendingEvent)
83     {
84         joyEvent(pendingValue, pendingIgnoreSets);
85 
86         pendingEvent = false;
87         pendingValue = false;
88         pendingIgnoreSets = false;
89         //pendingUpdateLastValues = true;
90     }
91 }
92 
hasPendingEvent()93 bool JoyAxis::hasPendingEvent()
94 {
95     return pendingEvent;
96 }
97 
clearPendingEvent()98 void JoyAxis::clearPendingEvent()
99 {
100     pendingEvent = false;
101     pendingValue = false;
102     pendingIgnoreSets = false;
103 }
104 
stickPassEvent(int value,bool ignoresets,bool updateLastValues)105 void JoyAxis::stickPassEvent(int value, bool ignoresets, bool updateLastValues)
106 {
107     if (this->stick)
108     {
109         if (updateLastValues)
110         {
111             lastKnownThottledValue = currentThrottledValue;
112             lastKnownRawValue = currentRawValue;
113         }
114 
115         setCurrentRawValue(value);
116         //currentRawValue = value;
117         bool safezone = !inDeadZone(currentRawValue);
118         currentThrottledValue = calculateThrottledValue(value);
119 
120         if (safezone && !isActive)
121         {
122             isActive = eventActive = true;
123             emit active(value);
124         }
125         else if (!safezone && isActive)
126         {
127             isActive = eventActive = false;
128             emit released(value);
129         }
130 
131         if (!ignoresets)
132         {
133             stick->queueJoyEvent(ignoresets);
134         }
135         else
136         {
137             stick->joyEvent(ignoresets);
138         }
139 
140         emit moved(currentRawValue);
141     }
142 }
143 
joyEvent(int value,bool ignoresets,bool updateLastValues)144 void JoyAxis::joyEvent(int value, bool ignoresets, bool updateLastValues)
145 {
146     if (this->stick && !pendingEvent)
147     {
148         stickPassEvent(value, ignoresets, updateLastValues);
149     }
150     else
151     {
152         if (updateLastValues)
153         {
154             lastKnownThottledValue = currentThrottledValue;
155             lastKnownRawValue = currentRawValue;
156         }
157 
158         setCurrentRawValue(value);
159         //currentRawValue = value;
160         bool safezone = !inDeadZone(currentRawValue);
161         currentThrottledValue = calculateThrottledValue(value);
162 
163         // If in joystick mode and this is the first detected event,
164         // use the current value as the axis center point. If the value
165         // is below -30,000 then consider it a trigger.
166         InputDevice *device = parentSet->getInputDevice();
167         if (!device->isGameController() && !device->hasCalibrationThrottle(index))
168         {
169             performCalibration(currentRawValue);
170             safezone = !inDeadZone(currentRawValue);
171             currentThrottledValue = calculateThrottledValue(value);
172         }
173 
174         if (safezone && !isActive)
175         {
176             isActive = eventActive = true;
177             emit active(value);
178             createDeskEvent(ignoresets);
179         }
180         else if (!safezone && isActive)
181         {
182             isActive = eventActive = false;
183             emit released(value);
184 
185             createDeskEvent(ignoresets);
186         }
187         else if (isActive)
188         {
189             createDeskEvent(ignoresets);
190         }
191     }
192 
193     emit moved(currentRawValue);
194 }
195 
inDeadZone(int value)196 bool JoyAxis::inDeadZone(int value)
197 {
198     bool result = false;
199     int temp = calculateThrottledValue(value);
200 
201     if (abs(temp) <= deadZone)
202     {
203         result = true;
204     }
205 
206     return result;
207 }
208 
getName(bool forceFullFormat,bool displayNames)209 QString JoyAxis::getName(bool forceFullFormat, bool displayNames)
210 {
211     QString label = getPartialName(forceFullFormat, displayNames);
212 
213     label.append(": ");
214 
215     if (throttle == NormalThrottle)
216     {
217         label.append("-");
218         if (!naxisbutton->getActionName().isEmpty() && displayNames)
219         {
220             label.append(naxisbutton->getActionName());
221         }
222         else
223         {
224             label.append(naxisbutton->getCalculatedActiveZoneSummary());
225         }
226 
227         label.append(" | +");
228         if (!paxisbutton->getActionName().isEmpty() && displayNames)
229         {
230             label.append(paxisbutton->getActionName());
231         }
232         else
233         {
234             label.append(paxisbutton->getCalculatedActiveZoneSummary());
235         }
236     }
237     else if (throttle == PositiveThrottle || throttle == PositiveHalfThrottle)
238     {
239         label.append("+");
240         if (!paxisbutton->getActionName().isEmpty() && displayNames)
241         {
242             label.append(paxisbutton->getActionName());
243         }
244         else
245         {
246             label.append(paxisbutton->getCalculatedActiveZoneSummary());
247         }
248     }
249     else if (throttle == NegativeThrottle || throttle == NegativeHalfThrottle)
250     {
251         label.append("-");
252         if (!naxisbutton->getActionName().isEmpty() && displayNames)
253         {
254             label.append(naxisbutton->getActionName());
255         }
256         else
257         {
258             label.append(naxisbutton->getCalculatedActiveZoneSummary());
259         }
260     }
261 
262     return label;
263 }
264 
getRealJoyIndex()265 int JoyAxis::getRealJoyIndex()
266 {
267     return index + 1;
268 }
269 
getCurrentThrottledValue()270 int JoyAxis::getCurrentThrottledValue()
271 {
272     return currentThrottledValue;
273 }
274 
calculateThrottledValue(int value)275 int JoyAxis::calculateThrottledValue(int value)
276 {
277     int temp = value;
278 
279     if (throttle == NegativeHalfThrottle)
280     {
281         value = value <= 0 ? value : -value;
282         temp = value;
283     }
284     else if (throttle == NegativeThrottle)
285     {
286         temp = (value + AXISMIN) / 2;
287     }
288     else if (throttle == PositiveThrottle)
289     {
290         temp = (value + AXISMAX) / 2;
291     }
292     else if (throttle == PositiveHalfThrottle)
293     {
294         value = value >= 0 ? value : -value;
295         temp = value;
296     }
297 
298     return temp;
299 }
300 
setIndex(int index)301 void JoyAxis::setIndex(int index)
302 {
303     this->index = index;
304 }
305 
getIndex()306 int JoyAxis::getIndex()
307 {
308     return index;
309 }
310 
311 
createDeskEvent(bool ignoresets)312 void JoyAxis::createDeskEvent(bool ignoresets)
313 {
314     JoyAxisButton *eventbutton = 0;
315     if (currentThrottledValue > deadZone)
316     {
317         eventbutton = paxisbutton;
318     }
319     else if (currentThrottledValue < -deadZone)
320     {
321         eventbutton = naxisbutton;
322     }
323 
324     if (eventbutton && !activeButton)
325     {
326         // There is no active button. Call joyEvent and set current
327         // button as active button
328         eventbutton->joyEvent(eventActive, ignoresets);
329         activeButton = eventbutton;
330     }
331     else if (!eventbutton && activeButton)
332     {
333         // Currently in deadzone. Disable currently active button.
334         activeButton->joyEvent(eventActive, ignoresets);
335         activeButton = 0;
336     }
337     else if (eventbutton && activeButton && eventbutton == activeButton)
338     {
339         //Button is currently active. Just pass current value
340         eventbutton->joyEvent(eventActive, ignoresets);
341     }
342     else if (eventbutton && activeButton && eventbutton != activeButton)
343     {
344         // Deadzone skipped. Button for new event is not the currently
345         // active button. Disable the active button before enabling
346         // the new button
347         activeButton->joyEvent(!eventActive, ignoresets);
348         eventbutton->joyEvent(eventActive, ignoresets);
349         activeButton = eventbutton;
350     }
351 }
352 
setDeadZone(int value)353 void JoyAxis::setDeadZone(int value)
354 {
355     deadZone = abs(value);
356     emit propertyUpdated();
357 }
358 
getDeadZone()359 int JoyAxis::getDeadZone()
360 {
361     return deadZone;
362 }
363 
setMaxZoneValue(int value)364 void JoyAxis::setMaxZoneValue(int value)
365 {
366     value = abs(value);
367     if (value >= AXISMAX)
368     {
369         maxZoneValue = AXISMAX;
370         emit propertyUpdated();
371     }
372     else
373     {
374         maxZoneValue = value;
375         emit propertyUpdated();
376     }
377 }
378 
getMaxZoneValue()379 int JoyAxis::getMaxZoneValue()
380 {
381     return maxZoneValue;
382 }
383 
384 /**
385  * @brief Set throttle value for axis.
386  * @param Current value for axis.
387  */
setThrottle(int value)388 void JoyAxis::setThrottle(int value)
389 {
390     if (value >= JoyAxis::NegativeHalfThrottle && value <= JoyAxis::PositiveHalfThrottle)
391     {
392         if (value != throttle)
393         {
394             throttle = value;
395             adjustRange();
396             emit throttleChanged();
397             emit propertyUpdated();
398         }
399     }
400 }
401 
402 /**
403  * @brief Set the initial calibrated throttle based on the first event
404  *     passed by SDL.
405  * @param Current value for axis.
406  */
setInitialThrottle(int value)407 void JoyAxis::setInitialThrottle(int value)
408 {
409     if (value >= JoyAxis::NegativeHalfThrottle && value <= JoyAxis::PositiveHalfThrottle)
410     {
411         if (value != throttle)
412         {
413             throttle = value;
414             adjustRange();
415             emit throttleChanged();
416         }
417     }
418 }
419 
getThrottle()420 int JoyAxis::getThrottle()
421 {
422     return throttle;
423 }
424 
readConfig(QXmlStreamReader * xml)425 void JoyAxis::readConfig(QXmlStreamReader *xml)
426 {
427     if (xml->isStartElement() && xml->name() == getXmlName())
428     {
429         //reset();
430 
431         xml->readNextStartElement();
432         while (!xml->atEnd() && (!xml->isEndElement() && xml->name() != getXmlName()))
433         {
434             bool found = false;
435             found = readMainConfig(xml);
436             if (!found && xml->name() == naxisbutton->getXmlName() && xml->isStartElement())
437             {
438                 found = true;
439                 readButtonConfig(xml);
440             }
441 
442             if (!found)
443             {
444                 xml->skipCurrentElement();
445             }
446 
447             xml->readNextStartElement();
448         }
449     }
450 }
451 
writeConfig(QXmlStreamWriter * xml)452 void JoyAxis::writeConfig(QXmlStreamWriter *xml)
453 {
454     bool currentlyDefault = isDefault();
455 
456     xml->writeStartElement(getXmlName());
457     xml->writeAttribute("index", QString::number(index+1));
458 
459     if (!currentlyDefault)
460     {
461         if (deadZone != AXISDEADZONE)
462         {
463             xml->writeTextElement("deadZone", QString::number(deadZone));
464         }
465 
466         if (maxZoneValue != AXISMAXZONE)
467         {
468             xml->writeTextElement("maxZone", QString::number(maxZoneValue));
469         }
470     }
471 
472 
473     //if (throttle != DEFAULTTHROTTLE)
474     //{
475         xml->writeStartElement("throttle");
476 
477         if (throttle == JoyAxis::NegativeHalfThrottle)
478         {
479             xml->writeCharacters("negativehalf");
480         }
481         else if (throttle == JoyAxis::NegativeThrottle)
482         {
483             xml->writeCharacters("negative");
484         }
485         else if (throttle == JoyAxis::NormalThrottle)
486         {
487             xml->writeCharacters("normal");
488         }
489         else if (throttle == JoyAxis::PositiveThrottle)
490         {
491             xml->writeCharacters("positive");
492         }
493         else if (throttle == JoyAxis::PositiveHalfThrottle)
494         {
495             xml->writeCharacters("positivehalf");
496         }
497 
498         xml->writeEndElement();
499     //}
500 
501     if (!currentlyDefault)
502     {
503         naxisbutton->writeConfig(xml);
504         paxisbutton->writeConfig(xml);
505     }
506 
507     xml->writeEndElement();
508 }
509 
510 
readMainConfig(QXmlStreamReader * xml)511 bool JoyAxis::readMainConfig(QXmlStreamReader *xml)
512 {
513     bool found = false;
514 
515     if (xml->name() == "deadZone" && xml->isStartElement())
516     {
517         found = true;
518         QString temptext = xml->readElementText();
519         int tempchoice = temptext.toInt();
520         this->setDeadZone(tempchoice);
521     }
522     else if (xml->name() == "maxZone" && xml->isStartElement())
523     {
524         found = true;
525         QString temptext = xml->readElementText();
526         int tempchoice = temptext.toInt();
527         this->setMaxZoneValue(tempchoice);
528     }
529     else if (xml->name() == "throttle" && xml->isStartElement())
530     {
531         found = true;
532         QString temptext = xml->readElementText();
533         if (temptext == "negativehalf")
534         {
535             this->setThrottle(JoyAxis::NegativeHalfThrottle);
536         }
537         else if (temptext == "negative")
538         {
539             this->setThrottle(JoyAxis::NegativeThrottle);
540         }
541         else if (temptext == "normal")
542         {
543             this->setThrottle(JoyAxis::NormalThrottle);
544         }
545         else if (temptext == "positive")
546         {
547             this->setThrottle(JoyAxis::PositiveThrottle);
548         }
549         else if (temptext == "positivehalf")
550         {
551             this->setThrottle(JoyAxis::PositiveHalfThrottle);
552         }
553 
554         InputDevice *device = parentSet->getInputDevice();
555         if (!device->hasCalibrationThrottle(index))
556         {
557             device->setCalibrationStatus(index,
558                                          static_cast<JoyAxis::ThrottleTypes>(throttle));
559         }
560 
561         setCurrentRawValue(currentThrottledDeadValue);
562         //currentRawValue = currentThrottledDeadValue;
563         currentThrottledValue = calculateThrottledValue(currentRawValue);
564     }
565 
566     return found;
567 }
568 
readButtonConfig(QXmlStreamReader * xml)569 bool JoyAxis::readButtonConfig(QXmlStreamReader *xml)
570 {
571     bool found = false;
572 
573     int index = xml->attributes().value("index").toString().toInt();
574     if (index == 1)
575     {
576         found = true;
577         naxisbutton->readConfig(xml);
578     }
579     else if (index == 2)
580     {
581         found = true;
582         paxisbutton->readConfig(xml);
583     }
584 
585     return found;
586 }
587 
reset()588 void JoyAxis::reset()
589 {
590     deadZone = getDefaultDeadZone();
591     isActive = false;
592 
593     eventActive = false;
594     maxZoneValue = getDefaultMaxZone();
595     throttle = getDefaultThrottle();
596 
597     paxisbutton->reset();
598     naxisbutton->reset();
599     activeButton = 0;
600     lastKnownThottledValue = 0;
601     lastKnownRawValue = 0;
602 
603     adjustRange();
604     setCurrentRawValue(currentThrottledDeadValue);
605     currentThrottledValue = calculateThrottledValue(currentRawValue);
606     axisName.clear();
607 
608     pendingEvent = false;
609     pendingValue = currentRawValue;
610     pendingIgnoreSets = false;
611     //pendingUpdateLastValues = true;
612 }
613 
reset(int index)614 void JoyAxis::reset(int index)
615 {
616     reset();
617     this->index = index;
618 }
619 
getPAxisButton()620 JoyAxisButton* JoyAxis::getPAxisButton()
621 {
622     return paxisbutton;
623 }
624 
getNAxisButton()625 JoyAxisButton* JoyAxis::getNAxisButton()
626 {
627     return naxisbutton;
628 }
629 
getCurrentRawValue()630 int JoyAxis::getCurrentRawValue()
631 {
632     return currentRawValue;
633 }
634 
adjustRange()635 void JoyAxis::adjustRange()
636 {
637     if (throttle == JoyAxis::NegativeThrottle)
638     {
639         currentThrottledDeadValue = AXISMAX;
640     }
641     else if (throttle == JoyAxis::NormalThrottle ||
642              throttle == JoyAxis::PositiveHalfThrottle ||
643              throttle == JoyAxis::NegativeHalfThrottle)
644     {
645         currentThrottledDeadValue = 0;
646     }
647     else if (throttle == JoyAxis::PositiveThrottle)
648     {
649         currentThrottledDeadValue = AXISMIN;
650     }
651 
652     currentThrottledValue = calculateThrottledValue(currentRawValue);
653 }
654 
getCurrentThrottledDeadValue()655 int JoyAxis::getCurrentThrottledDeadValue()
656 {
657     return currentThrottledDeadValue;
658 }
659 
getDistanceFromDeadZone()660 double JoyAxis::getDistanceFromDeadZone()
661 {
662     return getDistanceFromDeadZone(currentThrottledValue);
663 }
664 
getDistanceFromDeadZone(int value)665 double JoyAxis::getDistanceFromDeadZone(int value)
666 {
667     double distance = 0.0;
668     int currentValue = value;
669 
670     if (currentValue >= deadZone)
671     {
672         distance = (currentValue - deadZone)/static_cast<double>(maxZoneValue - deadZone);
673     }
674     else if (currentValue <= -deadZone)
675     {
676         distance = (currentValue + deadZone)/static_cast<double>(-maxZoneValue + deadZone);
677     }
678 
679     distance = qBound(0.0, distance, 1.0);
680     return distance;
681 }
682 
683 /**
684  * @brief Get the current value for an axis in either direction converted to
685  *   the range of -1.0 to 1.0.
686  * @param Current interger value of the axis
687  * @return Axis value in the range of -1.0 to 1.0
688  */
getRawDistance(int value)689 double JoyAxis::getRawDistance(int value)
690 {
691     double distance = 0.0;
692     int currentValue = value;
693 
694     distance = currentValue / static_cast<double>(maxZoneValue);
695     distance = qBound(-1.0, distance, 1.0);
696 
697     return distance;
698 }
699 
propogateThrottleChange()700 void JoyAxis::propogateThrottleChange()
701 {
702     emit throttleChangePropogated(this->index);
703 }
704 
getCurrentlyAssignedSet()705 int JoyAxis::getCurrentlyAssignedSet()
706 {
707     return originset;
708 }
709 
setControlStick(JoyControlStick * stick)710 void JoyAxis::setControlStick(JoyControlStick *stick)
711 {
712     removeVDPads();
713     removeControlStick();
714     this->stick = stick;
715     emit propertyUpdated();
716 }
717 
isPartControlStick()718 bool JoyAxis::isPartControlStick()
719 {
720     return (this->stick != 0);
721 }
722 
getControlStick()723 JoyControlStick* JoyAxis::getControlStick()
724 {
725     return this->stick;
726 }
727 
removeControlStick(bool performRelease)728 void JoyAxis::removeControlStick(bool performRelease)
729 {
730     if (stick)
731     {
732         if (performRelease)
733         {
734             stick->releaseButtonEvents();
735         }
736 
737         this->stick = 0;
738         emit propertyUpdated();
739     }
740 }
741 
742 
743 
hasControlOfButtons()744 bool JoyAxis::hasControlOfButtons()
745 {
746     bool value = true;
747     if (paxisbutton->isPartVDPad() || naxisbutton->isPartVDPad())
748     {
749         value = false;
750     }
751 
752     return value;
753 }
754 
removeVDPads()755 void JoyAxis::removeVDPads()
756 {
757     if (paxisbutton->isPartVDPad())
758     {
759         paxisbutton->joyEvent(false, true);
760         paxisbutton->removeVDPad();
761     }
762 
763     if (naxisbutton->isPartVDPad())
764     {
765         naxisbutton->joyEvent(false, true);
766         naxisbutton->removeVDPad();
767     }
768 }
769 
isDefault()770 bool JoyAxis::isDefault()
771 {
772     bool value = true;
773     value = value && (deadZone == getDefaultDeadZone());
774     value = value && (maxZoneValue == getDefaultMaxZone());
775     //value = value && (throttle == getDefaultThrottle());
776     value = value && (paxisbutton->isDefault());
777     value = value && (naxisbutton->isDefault());
778     return value;
779 }
780 
781 /* Use this method to keep currentRawValue in the expected range.
782  * SDL has a minimum axis value of -32768 which should be ignored to
783  * ensure that JoyControlStick will not encounter overflow problems
784  * on a 32 bit machine.
785  */
setCurrentRawValue(int value)786 void JoyAxis::setCurrentRawValue(int value)
787 {
788     if (value >= JoyAxis::AXISMIN && value <= JoyAxis::AXISMAX)
789     {
790         currentRawValue = value;
791     }
792     else if (value > JoyAxis::AXISMAX)
793     {
794         currentRawValue = JoyAxis::AXISMAX;
795     }
796     else if (value < JoyAxis::AXISMIN)
797     {
798         currentRawValue = JoyAxis::AXISMIN;
799     }
800 }
801 
setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode)802 void JoyAxis::setButtonsMouseMode(JoyButton::JoyMouseMovementMode mode)
803 {
804     paxisbutton->setMouseMode(mode);
805     naxisbutton->setMouseMode(mode);
806 }
807 
hasSameButtonsMouseMode()808 bool JoyAxis::hasSameButtonsMouseMode()
809 {
810     bool result = true;
811     if (paxisbutton->getMouseMode() != naxisbutton->getMouseMode())
812     {
813         result = false;
814     }
815 
816     return result;
817 }
818 
getButtonsPresetMouseMode()819 JoyButton::JoyMouseMovementMode JoyAxis::getButtonsPresetMouseMode()
820 {
821     JoyButton::JoyMouseMovementMode resultMode = JoyButton::MouseCursor;
822     if (paxisbutton->getMouseMode() == naxisbutton->getMouseMode())
823     {
824         resultMode = paxisbutton->getMouseMode();
825     }
826 
827     return resultMode;
828 }
829 
setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve)830 void JoyAxis::setButtonsMouseCurve(JoyButton::JoyMouseCurve mouseCurve)
831 {
832     paxisbutton->setMouseCurve(mouseCurve);
833     naxisbutton->setMouseCurve(mouseCurve);
834 }
835 
hasSameButtonsMouseCurve()836 bool JoyAxis::hasSameButtonsMouseCurve()
837 {
838     bool result = true;
839     if (paxisbutton->getMouseCurve() != naxisbutton->getMouseCurve())
840     {
841         result = false;
842     }
843 
844     return result;
845 }
846 
getButtonsPresetMouseCurve()847 JoyButton::JoyMouseCurve JoyAxis::getButtonsPresetMouseCurve()
848 {
849     JoyButton::JoyMouseCurve resultCurve = JoyButton::LinearCurve;
850     if (paxisbutton->getMouseCurve() == naxisbutton->getMouseCurve())
851     {
852         resultCurve = paxisbutton->getMouseCurve();
853     }
854 
855     return resultCurve;
856 }
857 
setButtonsSpringWidth(int value)858 void JoyAxis::setButtonsSpringWidth(int value)
859 {
860     paxisbutton->setSpringWidth(value);
861     naxisbutton->setSpringWidth(value);
862 }
863 
setButtonsSpringHeight(int value)864 void JoyAxis::setButtonsSpringHeight(int value)
865 {
866     paxisbutton->setSpringHeight(value);
867     naxisbutton->setSpringHeight(value);
868 }
869 
getButtonsPresetSpringWidth()870 int JoyAxis::getButtonsPresetSpringWidth()
871 {
872     int presetSpringWidth = 0;
873 
874     if (paxisbutton->getSpringWidth() == naxisbutton->getSpringWidth())
875     {
876         presetSpringWidth = paxisbutton->getSpringWidth();
877     }
878 
879     return presetSpringWidth;
880 }
881 
getButtonsPresetSpringHeight()882 int JoyAxis::getButtonsPresetSpringHeight()
883 {
884     int presetSpringHeight = 0;
885 
886     if (paxisbutton->getSpringHeight() == naxisbutton->getSpringHeight())
887     {
888         presetSpringHeight = paxisbutton->getSpringHeight();
889     }
890 
891     return presetSpringHeight;
892 }
893 
setButtonsSensitivity(double value)894 void JoyAxis::setButtonsSensitivity(double value)
895 {
896     paxisbutton->setSensitivity(value);
897     naxisbutton->setSensitivity(value);
898 }
899 
getButtonsPresetSensitivity()900 double JoyAxis::getButtonsPresetSensitivity()
901 {
902     double presetSensitivity = 1.0;
903 
904     if (paxisbutton->getSensitivity() == naxisbutton->getSensitivity())
905     {
906         presetSensitivity = paxisbutton->getSensitivity();
907     }
908 
909     return presetSensitivity;
910 }
911 
getAxisButtonByValue(int value)912 JoyAxisButton* JoyAxis::getAxisButtonByValue(int value)
913 {
914     JoyAxisButton *eventbutton = 0;
915     int throttledValue = calculateThrottledValue(value);
916     if (throttledValue > deadZone)
917     {
918         eventbutton = paxisbutton;
919     }
920     else if (throttledValue < -deadZone)
921     {
922         eventbutton = naxisbutton;
923     }
924 
925     return eventbutton;
926 }
927 
setAxisName(QString tempName)928 void JoyAxis::setAxisName(QString tempName)
929 {
930     if (tempName.length() <= 20 && tempName != axisName)
931     {
932         axisName = tempName;
933         emit axisNameChanged();
934         emit propertyUpdated();
935     }
936 }
937 
getAxisName()938 QString JoyAxis::getAxisName()
939 {
940     return axisName;
941 }
942 
setButtonsWheelSpeedX(int value)943 void JoyAxis::setButtonsWheelSpeedX(int value)
944 {
945     paxisbutton->setWheelSpeedX(value);
946     naxisbutton->setWheelSpeedX(value);
947 }
948 
setButtonsWheelSpeedY(int value)949 void JoyAxis::setButtonsWheelSpeedY(int value)
950 {
951     paxisbutton->setWheelSpeedY(value);
952     naxisbutton->setWheelSpeedY(value);
953 }
954 
setDefaultAxisName(QString tempname)955 void JoyAxis::setDefaultAxisName(QString tempname)
956 {
957     defaultAxisName = tempname;
958 }
959 
getDefaultAxisName()960 QString JoyAxis::getDefaultAxisName()
961 {
962     return defaultAxisName;
963 }
964 
getPartialName(bool forceFullFormat,bool displayNames)965 QString JoyAxis::getPartialName(bool forceFullFormat, bool displayNames)
966 {
967     QString label;
968 
969     if (!axisName.isEmpty() && displayNames)
970     {
971         if (forceFullFormat)
972         {
973             label.append(tr("Axis")).append(" ");
974         }
975 
976         label.append(axisName);
977     }
978     else if (!defaultAxisName.isEmpty())
979     {
980         if (forceFullFormat)
981         {
982             label.append(tr("Axis")).append(" ");
983         }
984         label.append(defaultAxisName);
985     }
986     else
987     {
988         label.append(tr("Axis")).append(" ");
989         label.append(QString::number(getRealJoyIndex()));
990     }
991 
992     return label;
993 }
994 
getXmlName()995 QString JoyAxis::getXmlName()
996 {
997     return this->xmlName;
998 }
999 
getDefaultDeadZone()1000 int JoyAxis::getDefaultDeadZone()
1001 {
1002     return this->AXISDEADZONE;
1003 }
1004 
getDefaultMaxZone()1005 int JoyAxis::getDefaultMaxZone()
1006 {
1007     return this->AXISMAXZONE;
1008 }
1009 
getDefaultThrottle()1010 JoyAxis::ThrottleTypes JoyAxis::getDefaultThrottle()
1011 {
1012     return this->DEFAULTTHROTTLE;
1013 }
1014 
getParentSet()1015 SetJoystick* JoyAxis::getParentSet()
1016 {
1017     return parentSet;
1018 }
1019 
establishPropertyUpdatedConnection()1020 void JoyAxis::establishPropertyUpdatedConnection()
1021 {
1022     connect(this, SIGNAL(propertyUpdated()), getParentSet()->getInputDevice(), SLOT(profileEdited()));
1023 }
1024 
disconnectPropertyUpdatedConnection()1025 void JoyAxis::disconnectPropertyUpdatedConnection()
1026 {
1027     disconnect(this, SIGNAL(propertyUpdated()), getParentSet()->getInputDevice(), SLOT(profileEdited()));
1028 }
1029 
setButtonsSpringRelativeStatus(bool value)1030 void JoyAxis::setButtonsSpringRelativeStatus(bool value)
1031 {
1032     paxisbutton->setSpringRelativeStatus(value);
1033     naxisbutton->setSpringRelativeStatus(value);
1034 }
1035 
isRelativeSpring()1036 bool JoyAxis::isRelativeSpring()
1037 {
1038     bool relative = false;
1039 
1040     if (paxisbutton->isRelativeSpring() == naxisbutton->isRelativeSpring())
1041     {
1042         relative = paxisbutton->isRelativeSpring();
1043     }
1044 
1045     return relative;
1046 }
1047 
performCalibration(int value)1048 void JoyAxis::performCalibration(int value)
1049 {
1050     InputDevice *device = parentSet->getInputDevice();
1051     if (value <= -30000)
1052     {
1053         // Assume axis is a trigger. Set default throttle to Positive.
1054         device->setCalibrationThrottle(index, PositiveThrottle);
1055     }
1056     else
1057     {
1058         // Ensure that default throttle is used when a device is reset.
1059         device->setCalibrationThrottle(index,
1060                                        static_cast<JoyAxis::ThrottleTypes>(throttle));
1061     }
1062     //else if (value >= -15000 && value <= 15000)
1063     //{
1064     //    device->setCalibrationThrottle(index, NormalThrottle);
1065     //}
1066 }
1067 
copyAssignments(JoyAxis * destAxis)1068 void JoyAxis::copyAssignments(JoyAxis *destAxis)
1069 {
1070     destAxis->reset();
1071     destAxis->deadZone = deadZone;
1072     destAxis->maxZoneValue = maxZoneValue;
1073     destAxis->axisName = axisName;
1074     paxisbutton->copyAssignments(destAxis->paxisbutton);
1075     naxisbutton->copyAssignments(destAxis->naxisbutton);
1076 
1077     if (!destAxis->isDefault())
1078     {
1079         emit propertyUpdated();
1080     }
1081 }
1082 
setButtonsEasingDuration(double value)1083 void JoyAxis::setButtonsEasingDuration(double value)
1084 {
1085     paxisbutton->setEasingDuration(value);
1086     naxisbutton->setEasingDuration(value);
1087 }
1088 
getButtonsEasingDuration()1089 double JoyAxis::getButtonsEasingDuration()
1090 {
1091     double result = JoyButton::DEFAULTEASINGDURATION;
1092     if (paxisbutton->getEasingDuration() == naxisbutton->getEasingDuration())
1093     {
1094         result = paxisbutton->getEasingDuration();
1095     }
1096 
1097     return result;
1098 }
1099 
getLastKnownThrottleValue()1100 int JoyAxis::getLastKnownThrottleValue()
1101 {
1102     return lastKnownThottledValue;
1103 }
1104 
getLastKnownRawValue()1105 int JoyAxis::getLastKnownRawValue()
1106 {
1107     return lastKnownRawValue;
1108 }
1109 
1110 /**
1111  * @brief Determine an appropriate release value for an axis depending
1112  *     on the current throttle setting being used.
1113  * @return Release value for an axis
1114  */
getProperReleaseValue()1115 int JoyAxis::getProperReleaseValue()
1116 {
1117     // Handles NormalThrottle case
1118     int value = 0;
1119 
1120     if (throttle == NegativeHalfThrottle)
1121     {
1122         value = 0;
1123     }
1124     else if (throttle == NegativeThrottle)
1125     {
1126         value = JoyAxis::AXISMAX;
1127     }
1128     else if (throttle == PositiveThrottle)
1129     {
1130         value = JoyAxis::AXISMIN;
1131     }
1132     else if (throttle == PositiveHalfThrottle)
1133     {
1134         value = 0;
1135     }
1136 
1137     return value;
1138 }
1139 
setExtraAccelerationCurve(JoyButton::JoyExtraAccelerationCurve curve)1140 void JoyAxis::setExtraAccelerationCurve(JoyButton::JoyExtraAccelerationCurve curve)
1141 {
1142     paxisbutton->setExtraAccelerationCurve(curve);
1143     naxisbutton->setExtraAccelerationCurve(curve);
1144 }
1145 
getExtraAccelerationCurve()1146 JoyButton::JoyExtraAccelerationCurve JoyAxis::getExtraAccelerationCurve()
1147 {
1148     JoyButton::JoyExtraAccelerationCurve result = JoyButton::LinearAccelCurve;
1149     if (paxisbutton->getExtraAccelerationCurve() == naxisbutton->getExtraAccelerationCurve())
1150     {
1151         result = paxisbutton->getExtraAccelerationCurve();
1152     }
1153 
1154     return result;
1155 }
1156 
copyRawValues(JoyAxis * srcAxis)1157 void JoyAxis::copyRawValues(JoyAxis *srcAxis)
1158 {
1159     this->lastKnownRawValue = srcAxis->lastKnownRawValue;
1160     this->currentRawValue = srcAxis->currentRawValue;
1161 }
1162 
copyThrottledValues(JoyAxis * srcAxis)1163 void JoyAxis::copyThrottledValues(JoyAxis *srcAxis)
1164 {
1165     this->lastKnownThottledValue = srcAxis->lastKnownThottledValue;
1166     this->currentThrottledValue = srcAxis->currentThrottledValue;
1167 }
1168 
eventReset()1169 void JoyAxis::eventReset()
1170 {
1171     naxisbutton->eventReset();
1172     paxisbutton->eventReset();
1173 }
1174