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