TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
joystickconfig.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : joystickconfig.cpp
4 created : Wed Mar 21 21:46:11 CET 2001
5 copyright : (C) 2001-2026 by Eric Espié, Bernhard Wymann
6 email : berniw@bluewin.ch
7
8 ***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <tgfclient.h>
23#include <track.h>
24#include <robot.h>
25#include "driverconfig.h"
26#include <playerpref.h>
27#include <portability.h>
28#include <plib/js.h>
29
30#include "controlconfig.h"
31#include "joystickconfig.h"
32
33static void *scrHandle2 = NULL;
34
35static tCmdInfo *Cmd;
36static int maxCmd;
37static void *parmHandle;
38static const char* driverSection;
39
40static jsJoystick *js[NUM_JOY] = {NULL};
41
42static float ax[_JS_MAX_AXES * NUM_JOY] = {0};
43static int rawb[NUM_JOY] = {0};
44
45// Variable to give a small delay for axis registration which might be overlapped by a button.
46// This is e.g. the case for my ps4 gamepad, L2 and R2 are a button and an axis.
47static double axisPressedTime = 0.0;
48
49#define NB_STEPS 6
50
51// TODO: refactor, this is horrible, depends on the order in controlconfig.cpp, static tCmdInfo Cmd[]
52#define OFFSET_CMD 6
53
54static const char *Instructions[] = {
55 "Center the joystick then press a button for more than 0.2s",
56 "Steer left then press a button for more than 0.2s",
57 "Steer right then press a button for more than 0.2s",
58 "Apply full throttle then press a button for more than 0.2s",
59 "Apply full brake then press a button for more than 0.2s",
60 "Apply full clutch then press a button for more than 0.2s",
61 "Calibration successfully done",
62 "Calibration failed"
63};
64
65static int CalState;
66static int InstId;
67
68static const char *LabName[] = { "Steer", "Throttle", "Brake", "Clutch" };
69static int LabAxisId[4];
70static int LabMinId[4];
71static int LabMaxId[4];
72
73
74static float axCenter[_JS_MAX_AXES * NUM_JOY];
75
76static void advanceStep (void)
77{
78 do {
79 CalState++;
80 } while ((Cmd[CalState + OFFSET_CMD].ref.type != GFCTRL_TYPE_JOY_AXIS) && (CalState < NB_STEPS));
81}
82
83
84static void JoyCalAutomaton(void)
85{
86 static int axis;
87 const int BUFSIZE = 1024;
88 char buf[BUFSIZE];
89
90 axisPressedTime = 0.0;
91
92 switch (CalState) {
93 case 0:
94 memcpy(axCenter, ax, sizeof(axCenter));
96 break;
97 case 1:
98 axis = Cmd[CalState + OFFSET_CMD].ref.index;
99 Cmd[CalState + OFFSET_CMD].min = ax[axis];
100 Cmd[CalState + OFFSET_CMD].max = axCenter[axis];
101 Cmd[CalState + OFFSET_CMD].pow = 1.0;
102 snprintf(buf, BUFSIZE, "%.2g", ax[axis]);
104 advanceStep();
105 break;
106 case 2:
107 axis = Cmd[CalState + OFFSET_CMD].ref.index;
108 Cmd[CalState + OFFSET_CMD].min = axCenter[axis];
109 Cmd[CalState + OFFSET_CMD].max = ax[axis];
110 Cmd[CalState + OFFSET_CMD].pow = 1.0;
111 snprintf(buf, BUFSIZE, "%.2g", ax[axis]);
113 advanceStep();
114 break;
115 case 3:
116 case 4:
117 case 5:
118 axis = Cmd[CalState + OFFSET_CMD].ref.index;
119 Cmd[CalState + OFFSET_CMD].min = axCenter[axis];
120 Cmd[CalState + OFFSET_CMD].max = ax[axis];
121 Cmd[CalState + OFFSET_CMD].pow = 1.0;
122 snprintf(buf, BUFSIZE, "%.2g", axCenter[axis]);
124 snprintf(buf, BUFSIZE, "%.2g", ax[axis]);
126 advanceStep();
127 break;
128 }
130}
131
132
133static void Idle2(void)
134{
135 int mask;
136 int b, i;
137 int index;
138 double currentTime = GfTimeClock();
139 const double delay = 0.2;
140
141 for (index = 0; index < NUM_JOY; index++) {
142 if (js[index]) {
143 js[index]->read(&b, &ax[index * _JS_MAX_AXES]);
144
145 if (currentTime - axisPressedTime > delay) {
146 /* Joystick buttons */
147 for (i = 0, mask = 1; i < 32; i++, mask *= 2) {
148 if (((b & mask) != 0) && ((rawb[index] & mask) == 0)) {
149 if (axisPressedTime == 0.0) {
150 axisPressedTime = currentTime;
151 } else {
152 const char *str = GfctrlGetNameByRef(GFCTRL_TYPE_JOY_BUT, i + 32 * index);
154 /* Button fired */
156 if (CalState >= NB_STEPS) {
157 glutIdleFunc(GfuiIdle);
158 }
159 glutPostRedisplay();
160 rawb[index] = b;
161 return;
162 }
163 }
164 }
165 }
166
167 if (currentTime - axisPressedTime > delay) {
168 rawb[index] = b;
169 }
170 }
171 }
172 }
173}
174
175
176static void onActivate(void)
177{
178 int i;
179 int index;
180 int step;
181
182 CalState = 0;
184 glutIdleFunc(Idle2);
185 glutPostRedisplay();
186 for (index = 0; index < NUM_JOY; index++) {
187 if (js[index]) {
188 js[index]->read(&rawb[index], &ax[index * _JS_MAX_AXES]); /* initial value */
189 }
190 }
191
192 axisPressedTime = 0.0;
193
194 for (i = 0; i < 4; i++) {
195 if (i > 0) {
196 step = i + 2;
197 } else {
198 step = i + 1;
199 }
200 if (Cmd[step + OFFSET_CMD].ref.type == GFCTRL_TYPE_JOY_AXIS) {
202 } else {
204 }
207 }
208}
209
210
211void *JoyCalMenuInit(void *prevMenu, tCmdInfo *cmd, int maxcmd, void *parmhandle, const char* driversection)
212{
213 int x, y, dy, i, index;
214
215 Cmd = cmd;
216 maxCmd = maxcmd;
217 parmHandle = parmhandle;
218 driverSection = driversection;
219
220 if (scrHandle2) {
221 return scrHandle2;
222 }
223
225 GfuiTitleCreate(scrHandle2, "Joystick Calibration", 0);
227
228 GfuiScreenAddBgImg(scrHandle2, "data/img/splash-joycal.png");
229
230 x = 128;
231 y = 300;
232 dy = 50;
233
234 for (i = 0; i < 4; i++) {
239 y -= dy;
240 }
241
242 for (index = 0; index < NUM_JOY; index++) {
243 if (js[index] == NULL) {
244 js[index] = new jsJoystick(index);
245 }
246
247 if (js[index]->notWorking()) {
248 /* don't configure the joystick */
249 js[index] = NULL;
250 }
251 }
252
254
256 [prevMenu] { GfuiScreenActivate(prevMenu); }, tGfuiAction(), tGfuiAction());
257
260
261 return scrHandle2;
262}
static Vector y[4]
Definition Convex.cpp:56
static int rawb[NUM_JOY]
static jsJoystick * js[NUM_JOY]
static float axCenter[_JS_MAX_AXES *NUM_JOY]
static float ax[_JS_MAX_AXES *NUM_JOY]
static void onActivate(void)
static double axisPressedTime
static tCmdInfo Cmd[]
static int maxCmd
const char * GfctrlGetNameByRef(GfCtrlType type, int index)
Get a control name by its reference.
Definition control.cpp:191
bool GfctrlIsEventBlacklisted(void *parmHandle, const char *driversSection, const char *event)
Check if given event is blacklisted (used for buttons or axis which fire a button AND move event).
Definition control.cpp:498
void * GfuiScreenCreateExAction(float *bgColor, const tGfuiAction &onActivate, const tGfuiAction &onDeactivate, int mouseAllowed)
Create a screen.
Definition gui.cpp:619
void GfuiMenuDefaultKeysAdd(void *scr)
Add the default menu keyboard callback to a screen.
Definition guimenu.cpp:56
void GfuiLabelSetText(void *scr, int id, const char *text)
Change the text of a label.
Definition guilabel.cpp:193
int GfuiTitleCreate(void *scr, const char *text, int maxlen)
Add a Title to the screen.
Definition guilabel.cpp:150
void GfuiScreenAddBgImg(void *scr, const char *filename)
Add an image background to a screen.
Definition gui.cpp:1058
void GfuiIdle(void)
Process held-mouse-button repeat actions on the active screen.
Definition gui.cpp:152
int GfuiLabelCreate(void *scr, const char *text, int font, int x, int y, int align, int maxlen)
Add a label to a screen.
Definition guilabel.cpp:121
void GfuiScreenActivate(void *screen)
Activate a screen and make it current.
Definition gui.cpp:508
int GfuiButtonCreateAction(void *scr, const char *text, int font, int x, int y, int width, int align, int mouse, const tGfuiAction &onPush, const tGfuiAction &onFocus, const tGfuiAction &onFocusLost)
Add a button to a screen.
static const char * Instructions[]
static int LabAxisId[4]
static void * scrHandle2
static const char * LabName[]
static void advanceStep(void)
static const char * driverSection
static void onActivate(void)
static void JoyCalAutomaton(void)
void * JoyCalMenuInit(void *prevMenu, tCmdInfo *cmd, int maxcmd, void *parmhandle, const char *driversection)
#define OFFSET_CMD
static void Idle2(void)
#define NB_STEPS
static int InstId
static int LabMinId[4]
static int CalState
static int LabMaxId[4]
double GfTimeClock(void)
Get the time in seconds.
Definition os.cpp:50
Parameter set handle structure, multiple handles can reference the same parameter set.
Definition params.cpp:125
#define GFUI_FONT_LARGE
Definition tgfclient.h:248
#define GFUI_FONT_MEDIUM
Definition tgfclient.h:249
@ GFCTRL_TYPE_JOY_AXIS
Definition tgfclient.h:463
@ GFCTRL_TYPE_JOY_BUT
Definition tgfclient.h:464
#define GFUI_ALIGN_HC_VC
Definition tgfclient.h:75
#define GFUI_MOUSE_UP
Definition tgfclient.h:82
std::function< void()> tGfuiAction
Definition tgfclient.h:107
#define GFUI_ALIGN_HC_VB
Definition tgfclient.h:74
#define NUM_JOY
Definition tgfclient.h:36