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 #ifndef JOYBUTTON_H
19 #define JOYBUTTON_H
20 
21 #include <QObject>
22 #include <QTimer>
23 #include <QElapsedTimer>
24 #include <QTime>
25 #include <QList>
26 #include <QListIterator>
27 #include <QHash>
28 #include <QQueue>
29 #include <QReadWriteLock>
30 #include <QXmlStreamReader>
31 #include <QXmlStreamWriter>
32 
33 #include "joybuttonslot.h"
34 #include "springmousemoveinfo.h"
35 #include "joybuttonmousehelper.h"
36 
37 #ifdef Q_OS_WIN
38   #include "joykeyrepeathelper.h"
39 #endif
40 
41 class VDPad;
42 class SetJoystick;
43 
44 class JoyButton : public QObject
45 {
46     Q_OBJECT
47 public:
48     explicit JoyButton(int index, int originset, SetJoystick *parentSet, QObject *parent=0);
49     ~JoyButton();
50 
51     enum SetChangeCondition {SetChangeDisabled=0, SetChangeOneWay,
52                              SetChangeTwoWay, SetChangeWhileHeld};
53 
54     enum JoyMouseMovementMode {MouseCursor=0, MouseSpring};
55     enum JoyMouseCurve {EnhancedPrecisionCurve=0, LinearCurve, QuadraticCurve,
56                         CubicCurve, QuadraticExtremeCurve, PowerCurve,
57                         EasingQuadraticCurve, EasingCubicCurve};
58     enum JoyExtraAccelerationCurve {LinearAccelCurve, EaseOutSineCurve,
59                                     EaseOutQuadAccelCurve, EaseOutCubicAccelCurve};
60     enum TurboMode {NormalTurbo=0, GradientTurbo, PulseTurbo};
61 
62     void joyEvent(bool pressed, bool ignoresets=false);
63     void queuePendingEvent(bool pressed, bool ignoresets=false);
64     void activatePendingEvent();
65     bool hasPendingEvent();
66     void clearPendingEvent();
67 
68     int getJoyNumber();
69     virtual int getRealJoyNumber();
70     void setJoyNumber(int index);
71 
72     bool getToggleState();
73     int getTurboInterval();
74     bool isUsingTurbo();
75     void setCustomName(QString name);
76     QString getCustomName();
77 
78     QList<JoyButtonSlot*> *getAssignedSlots();
79 
80     virtual void readConfig(QXmlStreamReader *xml);
81     virtual void writeConfig(QXmlStreamWriter *xml);
82 
83     virtual QString getPartialName(bool forceFullFormat=false, bool displayNames=false);
84     virtual QString getSlotsSummary();
85     virtual QString getSlotsString();
86     virtual QList<JoyButtonSlot*> getActiveZoneList();
87     virtual QString getActiveZoneSummary();
88     virtual QString getCalculatedActiveZoneSummary();
89     virtual QString getName(bool forceFullFormat=false, bool displayNames=false);
90     virtual QString getXmlName();
91 
92     int getMouseSpeedX();
93     int getMouseSpeedY();
94 
95     int getWheelSpeedX();
96     int getWheelSpeedY();
97 
98     void setChangeSetSelection(int index, bool updateActiveString=true);
99     int getSetSelection();
100 
101     virtual void setChangeSetCondition(SetChangeCondition condition,
102                                        bool passive=false, bool updateActiveString=true);
103     SetChangeCondition getChangeSetCondition();
104 
105     bool getButtonState();
106     int getOriginSet();
107 
108     bool containsSequence();
109     bool containsDistanceSlots();
110     bool containsReleaseSlots();
111 
112     virtual double getDistanceFromDeadZone();
113     virtual double getMouseDistanceFromDeadZone();
114     virtual double getLastMouseDistanceFromDeadZone();
115 
116     // Don't use direct assignment but copying from a current button.
117     virtual void copyLastMouseDistanceFromDeadZone(JoyButton *srcButton);
118     virtual void copyLastAccelerationDistance(JoyButton *srcButton);
119 
120     void copyExtraAccelerationState(JoyButton *srcButton);
121     void setUpdateInitAccel(bool state);
122 
123     virtual void setVDPad(VDPad *vdpad);
124     void removeVDPad();
125     bool isPartVDPad();
126     VDPad* getVDPad();
127 
128     virtual bool isDefault();
129     void setIgnoreEventState(bool ignore);
130     bool getIgnoreEventState();
131 
132     void setMouseMode(JoyMouseMovementMode mousemode);
133     JoyMouseMovementMode getMouseMode();
134 
135     void setMouseCurve(JoyMouseCurve selectedCurve);
136     JoyMouseCurve getMouseCurve();
137 
138     int getSpringWidth();
139     int getSpringHeight();
140 
141     double getSensitivity();
142 
143     bool getWhileHeldStatus();
144     void setWhileHeldStatus(bool status);
145 
146     QString getActionName();
147     QString getButtonName();
148 
149     virtual void setDefaultButtonName(QString tempname);
150     virtual QString getDefaultButtonName();
151 
152     SetJoystick* getParentSet();
153 
154     void setCycleResetTime(unsigned int interval);
155     unsigned int getCycleResetTime();
156 
157     void setCycleResetStatus(bool enabled);
158     bool isCycleResetActive();
159 
160     bool isRelativeSpring();
161     void copyAssignments(JoyButton *destButton);
162 
163     virtual void setTurboMode(TurboMode mode);
164     TurboMode getTurboMode();
165     virtual bool isPartRealAxis();
166     virtual bool isModifierButton();
167 
168     bool hasActiveSlots();
169 
170     static int calculateFinalMouseSpeed(JoyMouseCurve curve, int value);
171     double getEasingDuration();
172 
173     static void moveMouseCursor(int &movedX, int &movedY, int &movedElapsed);
174     static void moveSpringMouse(int &movedX, int &movedY, bool &hasMoved);
175 
176     static JoyButtonMouseHelper* getMouseHelper();
177     static QList<JoyButton*>* getPendingMouseButtons();
178     static bool hasCursorEvents();
179     static bool hasSpringEvents();
180 
181     static double getWeightModifier();
182     static void setWeightModifier(double modifier);
183 
184     static int getMouseHistorySize();
185     static void setMouseHistorySize(int size);
186 
187     static int getMouseRefreshRate();
188     static void setMouseRefreshRate(int refresh);
189 
190     static int getSpringModeScreen();
191     static void setSpringModeScreen(int screen);
192 
193     static void resetActiveButtonMouseDistances();
194     void resetAccelerationDistances();
195 
196     void setExtraAccelerationStatus(bool status);
197     void setExtraAccelerationMultiplier(double value);
198 
199     bool isExtraAccelerationEnabled();
200     double getExtraAccelerationMultiplier();
201 
202     virtual void initializeDistanceValues();
203 
204     void setMinAccelThreshold(double value);
205     double getMinAccelThreshold();
206 
207     void setMaxAccelThreshold(double value);
208     double getMaxAccelThreshold();
209 
210     void setStartAccelMultiplier(double value);
211     double getStartAccelMultiplier();
212 
213     void setAccelExtraDuration(double value);
214     double getAccelExtraDuration();
215 
216     void setExtraAccelerationCurve(JoyExtraAccelerationCurve curve);
217     JoyExtraAccelerationCurve getExtraAccelerationCurve();
218 
219     virtual double getAccelerationDistance();
220     virtual double getLastAccelerationDistance();
221 
222     void setSpringDeadCircleMultiplier(int value);
223     int getSpringDeadCircleMultiplier();
224 
225     static int getGamepadRefreshRate();
226     static void setGamepadRefreshRate(int refresh);
227 
228     static void restartLastMouseTime();
229 
230     static void setStaticMouseThread(QThread *thread);
231     static void indirectStaticMouseThread(QThread *thread);
232 
233     static bool shouldInvokeMouseEvents();
234     static void invokeMouseEvents();
235 
236     static const QString xmlName;
237 
238     // Define default values for many properties.
239     static const int ENABLEDTURBODEFAULT;
240     static const double DEFAULTMOUSESPEEDMOD;
241     static const unsigned int DEFAULTKEYREPEATDELAY;
242     static const unsigned int DEFAULTKEYREPEATRATE;
243     static const JoyMouseCurve DEFAULTMOUSECURVE;
244     static const bool DEFAULTTOGGLE;
245     static const int DEFAULTTURBOINTERVAL;
246     static const bool DEFAULTUSETURBO;
247     static const int DEFAULTMOUSESPEEDX;
248     static const int DEFAULTMOUSESPEEDY;
249     static const int DEFAULTSETSELECTION;
250     static const SetChangeCondition DEFAULTSETCONDITION;
251     static const JoyMouseMovementMode DEFAULTMOUSEMODE;
252     static const int DEFAULTSPRINGWIDTH;
253     static const int DEFAULTSPRINGHEIGHT;
254     static const double DEFAULTSENSITIVITY;
255     static const int DEFAULTWHEELX;
256     static const int DEFAULTWHEELY;
257     static const bool DEFAULTCYCLERESETACTIVE;
258     static const int DEFAULTCYCLERESET;
259     static const bool DEFAULTRELATIVESPRING;
260     static const TurboMode DEFAULTTURBOMODE;
261     static const double DEFAULTEASINGDURATION;
262     static const double MINIMUMEASINGDURATION;
263     static const double MAXIMUMEASINGDURATION;
264 
265     static const int DEFAULTMOUSEHISTORYSIZE;
266     static const double DEFAULTWEIGHTMODIFIER;
267 
268     static const int MAXIMUMMOUSEHISTORYSIZE;
269     static const double MAXIMUMWEIGHTMODIFIER;
270 
271     static const int MAXIMUMMOUSEREFRESHRATE;
272     static const int DEFAULTIDLEMOUSEREFRESHRATE;
273     static int IDLEMOUSEREFRESHRATE;
274 
275     static const unsigned int MINCYCLERESETTIME;
276     static const unsigned int MAXCYCLERESETTIME;
277 
278     static const double DEFAULTEXTRACCELVALUE;
279     static const double DEFAULTMINACCELTHRESHOLD;
280     static const double DEFAULTMAXACCELTHRESHOLD;
281     static const double DEFAULTSTARTACCELMULTIPLIER;
282     static const double DEFAULTACCELEASINGDURATION;
283     static const JoyExtraAccelerationCurve DEFAULTEXTRAACCELCURVE;
284 
285     static const int DEFAULTSPRINGRELEASERADIUS;
286 
287     static QList<double> mouseHistoryX;
288     static QList<double> mouseHistoryY;
289 
290     static double cursorRemainderX;
291     static double cursorRemainderY;
292 
293 protected:
294     double getTotalSlotDistance(JoyButtonSlot *slot);
295     bool distanceEvent();
296     void clearAssignedSlots(bool signalEmit=true);
297     void releaseSlotEvent();
298     void findReleaseEventEnd();
299     void findReleaseEventIterEnd(QListIterator<JoyButtonSlot*> *tempiter);
300     void findHoldEventEnd();
301     bool checkForDelaySequence();
302     void checkForPressedSetChange();
303     bool insertAssignedSlot(JoyButtonSlot *newSlot, bool updateActiveString=true);
304     unsigned int getPreferredKeyPressTime();
305     void checkTurboCondition(JoyButtonSlot *slot);
306     static bool hasFutureSpringEvents();
307     virtual double getCurrentSpringDeadCircle();
308     void vdpadPassEvent(bool pressed, bool ignoresets=false);
309 
310     QString buildActiveZoneSummary(QList<JoyButtonSlot*> &tempList);
311     void localBuildActiveZoneSummaryString();
312 
313     virtual bool readButtonConfig(QXmlStreamReader *xml);
314 
315     typedef struct _mouseCursorInfo
316     {
317         JoyButtonSlot *slot;
318         double code;
319     } mouseCursorInfo;
320 
321     // Used to denote whether the actual joypad button is pressed
322     bool isButtonPressed;
323     // Used to denote whether the virtual key is pressed
324     bool isKeyPressed;
325     bool toggle;
326     bool quitEvent;
327     // Used to denote the SDL index of the actual joypad button
328     int index;
329     int turboInterval;
330 
331     QTimer turboTimer;
332     QTimer pauseTimer;
333     QTimer holdTimer;
334     QTimer pauseWaitTimer;
335     QTimer createDeskTimer;
336     QTimer releaseDeskTimer;
337     QTimer mouseWheelVerticalEventTimer;
338     QTimer mouseWheelHorizontalEventTimer;
339     QTimer setChangeTimer;
340     QTimer keyPressTimer;
341     QTimer delayTimer;
342     QTimer slotSetChangeTimer;
343     static QTimer staticMouseEventTimer;
344 
345     bool isDown;
346     bool toggleActiveState;
347     bool useTurbo;
348     QList<JoyButtonSlot*> assignments;
349     QList<JoyButtonSlot*> activeSlots;
350     QString customName;
351 
352     int mouseSpeedX;
353     int mouseSpeedY;
354     int wheelSpeedX;
355     int wheelSpeedY;
356 
357     int setSelection;
358     SetChangeCondition setSelectionCondition;
359     int originset;
360 
361     QListIterator<JoyButtonSlot*> *slotiter;
362     JoyButtonSlot *currentPause;
363     JoyButtonSlot *currentHold;
364     JoyButtonSlot *currentCycle;
365     JoyButtonSlot *previousCycle;
366     JoyButtonSlot *currentDistance;
367     JoyButtonSlot *currentMouseEvent;
368     JoyButtonSlot *currentRelease;
369     JoyButtonSlot *currentWheelVerticalEvent;
370     JoyButtonSlot *currentWheelHorizontalEvent;
371     JoyButtonSlot *currentKeyPress;
372     JoyButtonSlot *currentDelay;
373     JoyButtonSlot *currentSetChangeSlot;
374 
375     bool ignoresets;
376     QTime buttonHold;
377     QTime pauseHold;
378     QTime inpauseHold;
379     QTime buttonHeldRelease;
380     QTime keyPressHold;
381     QTime buttonDelay;
382     QTime turboHold;
383     QTime wheelVerticalTime;
384     QTime wheelHorizontalTime;
385     //static QElapsedTimer lastMouseTime;
386     static QTime testOldMouseTime;
387 
388     QQueue<bool> ignoreSetQueue;
389     QQueue<bool> isButtonPressedQueue;
390 
391     QQueue<JoyButtonSlot*> mouseEventQueue;
392     QQueue<JoyButtonSlot*> mouseWheelVerticalEventQueue;
393     QQueue<JoyButtonSlot*> mouseWheelHorizontalEventQueue;
394 
395     int currentRawValue;
396     VDPad *vdpad;
397     bool ignoreEvents;
398     JoyMouseMovementMode mouseMode;
399     JoyMouseCurve mouseCurve;
400 
401     int springWidth;
402     int springHeight;
403     double sensitivity;
404     bool smoothing;
405     bool whileHeldStatus;
406     double lastDistance;
407     double lastWheelVerticalDistance;
408     double lastWheelHorizontalDistance;
409     int tempTurboInterval;
410 
411     // Keep track of the previous mouse distance from the previous gamepad
412     // poll.
413     double lastMouseDistance;
414 
415     // Keep track of the previous full distance from the previous gamepad
416     // poll.
417     double lastAccelerationDistance;
418 
419     // Multiplier and time used for acceleration easing.
420     double currentAccelMulti;
421     QTime accelExtraDurationTime;
422     double accelDuration;
423     double oldAccelMulti;
424     double accelTravel; // Track travel when accel started
425 
426     // Should lastMouseDistance be updated. Set after mouse event.
427     bool updateLastMouseDistance;
428 
429     // Should startingMouseDistance be updated. Set after acceleration
430     // has finally been applied.
431     bool updateStartingMouseDistance;
432 
433     double updateOldAccelMulti;
434 
435     bool updateInitAccelValues;
436 
437     // Keep track of the current mouse distance after a poll. Used
438     // to update lastMouseDistance later.
439     double currentMouseDistance;
440 
441     // Keep track of the current mouse distance after a poll. Used
442     // to update lastMouseDistance later.
443     double currentAccelerationDistance;
444 
445     // Take into account when mouse acceleration started
446     double startingAccelerationDistance;
447 
448     double minMouseDistanceAccelThreshold;
449     double maxMouseDistanceAccelThreshold;
450     double startAccelMultiplier;
451 
452     JoyExtraAccelerationCurve extraAccelCurve;
453 
454     QString actionName;
455     QString buttonName; // User specified button name
456     QString defaultButtonName; // Name used by the system
457 
458     SetJoystick *parentSet; // Pointer to set that button is assigned to.
459 
460     bool cycleResetActive;
461     unsigned int cycleResetInterval;
462     QTime cycleResetHold;
463 
464     bool relativeSpring;
465     TurboMode currentTurboMode;
466 
467     double easingDuration;
468 
469     bool extraAccelerationEnabled;
470     double extraAccelerationMultiplier;
471 
472     int springDeadCircleMultiplier;
473 
474     bool pendingPress;
475     bool pendingEvent;
476     bool pendingIgnoreSets;
477 
478     QReadWriteLock activeZoneLock;
479     QReadWriteLock assignmentsLock;
480     QReadWriteLock activeZoneStringLock;
481 
482     QString activeZoneString;
483     QTimer activeZoneTimer;
484 
485     static double mouseSpeedModifier;
486     static QList<JoyButtonSlot*> mouseSpeedModList;
487 
488     static QList<mouseCursorInfo> cursorXSpeeds;
489     static QList<mouseCursorInfo> cursorYSpeeds;
490 
491     static QList<PadderCommon::springModeInfo> springXSpeeds;
492     static QList<PadderCommon::springModeInfo> springYSpeeds;
493 
494     static QList<JoyButton*> pendingMouseButtons;
495 
496     static QHash<unsigned int, int> activeKeys;
497     static QHash<unsigned int, int> activeMouseButtons;
498 #ifdef Q_OS_WIN
499     static JoyKeyRepeatHelper repeatHelper;
500 #endif
501 
502     static JoyButtonSlot *lastActiveKey;
503     static JoyButtonMouseHelper mouseHelper;
504     static double weightModifier;
505     static int mouseHistorySize;
506     static int mouseRefreshRate;
507     static int springModeScreen;
508     static int gamepadRefreshRate;
509 
510 signals:
511     void clicked (int index);
512     void released (int index);
513     void keyChanged(int keycode);
514     void mouseChanged(int mousecode);
515     void setChangeActivated(int index);
516     void setAssignmentChanged(int current_button, int associated_set, int mode);
517     void finishedPause();
518     void turboChanged(bool state);
519     void toggleChanged(bool state);
520     void turboIntervalChanged(int interval);
521     void slotsChanged();
522     void actionNameChanged();
523     void buttonNameChanged();
524     void propertyUpdated();
525     void activeZoneChanged();
526 
527 public slots:
528     void setTurboInterval (int interval);
529     void setToggle (bool toggle);
530     void setUseTurbo(bool useTurbo);
531     void setMouseSpeedX(int speed);
532     void setMouseSpeedY(int speed);
533 
534     void setWheelSpeedX(int speed);
535     void setWheelSpeedY(int speed);
536 
537     void setSpringWidth(int value);
538     void setSpringHeight(int value);
539 
540     void setSensitivity(double value);
541     void setSpringRelativeStatus(bool value);
542 
543     void setActionName(QString tempName);
544     void setButtonName(QString tempName);
545 
546     void setEasingDuration(double value);
547 
548     virtual void reset();
549     virtual void reset(int index);
550     virtual void resetProperties();
551 
552     virtual void clearSlotsEventReset(bool clearSignalEmit=true);
553     virtual void eventReset();
554 
555     bool setAssignedSlot(int code, unsigned int alias, int index,
556                          JoyButtonSlot::JoySlotInputAction mode=JoyButtonSlot::JoyKeyboard);
557 
558     bool setAssignedSlot(int code,
559                          JoyButtonSlot::JoySlotInputAction mode=JoyButtonSlot::JoyKeyboard);
560 
561     bool setAssignedSlot(int code, unsigned int alias,
562                          JoyButtonSlot::JoySlotInputAction mode=JoyButtonSlot::JoyKeyboard);
563 
564     bool setAssignedSlot(JoyButtonSlot *otherSlot, int index);
565 
566     bool insertAssignedSlot(int code, unsigned int alias, int index,
567                             JoyButtonSlot::JoySlotInputAction mode=JoyButtonSlot::JoyKeyboard);
568 
569     void removeAssignedSlot(int index);
570 
571     static void establishMouseTimerConnections();
572     void establishPropertyUpdatedConnections();
573     void disconnectPropertyUpdatedConnections();
574 
575     virtual void mouseEvent();
576 
577 protected slots:
578     virtual void turboEvent();
579     virtual void wheelEventVertical();
580     virtual void wheelEventHorizontal();
581     void createDeskEvent();
582     void releaseDeskEvent(bool skipsetchange=false);
583     void buildActiveZoneSummaryString();
584 
585 private slots:
586     void releaseActiveSlots();
587     void activateSlots();
588     void waitForDeskEvent();
589     void waitForReleaseDeskEvent();
590     void holdEvent();
591     void delayEvent();
592 
593     void pauseWaitEvent();
594     void checkForSetChange();
595     void keyPressEvent();
596     void slotSetChange();
597 };
598 
599 
600 #endif // JOYBUTTON_H
601