1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: in_sdl.cpp 3483 2008-04-10 18:03:34Z dj_jl $
11 //**
12 //** Copyright (C) 1999-2002 J306nis Legzdi267375
13 //**
14 //** This program is free software; you can redistribute it and/or
15 //** modify it under the terms of the GNU General Public License
16 //** as published by the Free Software Foundation; either version 2
17 //** of the License, or (at your option) any later version.
18 //**
19 //** This program is distributed in the hope that it will be useful,
20 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 //** GNU General Public License for more details.
23 //**
24 //**************************************************************************
25
26 // HEADER FILES ------------------------------------------------------------
27
28 #include <SDL.h>
29 #include "gamedefs.h"
30
31 // MACROS ------------------------------------------------------------------
32
33 #ifndef MAX_JOYSTICK_BUTTONS
34 #define MAX_JOYSTICK_BUTTONS 100
35 #endif
36
37 // TYPES -------------------------------------------------------------------
38
39 class VSdlInputDevice : public VInputDevice
40 {
41 public:
42 VSdlInputDevice();
43 ~VSdlInputDevice();
44
45 void ReadInput();
46
47 private:
48 int mouse;
49
50 int mouse_oldx;
51 int mouse_oldy;
52
53 SDL_Joystick* joystick;
54 bool joystick_started;
55 int joy_num_buttons;
56 int joy_x;
57 int joy_y;
58 int joy_newb[MAX_JOYSTICK_BUTTONS];
59 int joy_oldx;
60 int joy_oldy;
61 int joy_oldb[MAX_JOYSTICK_BUTTONS];
62
63 static const vuint8 sym2key[SDLK_LAST];
64
65 void StartupJoystick();
66 void PostJoystick();
67 };
68
69 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
70
71 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
72
73 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
74
75 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
76
77 // PUBLIC DATA DEFINITIONS -------------------------------------------------
78
79 static VCvarI m_filter("m_filter", "1", CVAR_Archive);
80
81 // PRIVATE DATA DEFINITIONS ------------------------------------------------
82
83 // tested with SDL 1.2.2
84 const vuint8 VSdlInputDevice::sym2key[SDLK_LAST] =
85 {
86 //0,
87 0,
88 //1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
89 0, 0, 0, 0, 0, 0, 0, K_BACKSPACE, K_TAB, 0, 0, 0, K_ENTER, 0, 0, 0,
90 //17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
91 0, 0, K_PAUSE, 0, 0, 0, 0, 0, 0, 0, K_ESCAPE, 0, 0, 0, 0, ' ',
92 //33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
93 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, ',', '-', '.', '/', '0',
94 //49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
95 '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, ';', 0, '=', 0, 0, 0,
96 //65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 //81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '\\', ']', 0, 0, '`',
100 //97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
101 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
102 //113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
103 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, K_DELETE, 0,
104 //129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,
105 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
106 //145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,
107 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
108 //161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
109 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
110 //177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
111 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
112 //193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,
113 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
114 //209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
115 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
116 //225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
117 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
118 //241,242,243,244,245,246,247,248,
119 0,0,0,0,0,0,0,0,
120 //249,250,251,252,253,254,255, 256,
121 0,0,0,0,0,0,0, K_PAD0,
122 //257, 258, 259, 260, 261, 262, 263, 264,
123 K_PAD1, K_PAD2, K_PAD3, K_PAD4, K_PAD5, K_PAD6, K_PAD7, K_PAD8,
124 //265, 266, 267, 268, 269, 270, 271, 272,
125 K_PAD9, K_PADDOT, K_PADDIVIDE, K_PADMULTIPLE, K_PADMINUS, K_PADPLUS, K_PADENTER, '=',
126 //273, 274, 275, 276, 277, 278, 279, 280,
127 K_UPARROW, K_DOWNARROW, K_RIGHTARROW, K_LEFTARROW, K_INSERT, K_HOME, K_END, K_PAGEUP,
128 //281, 282, 283, 284, 285, 286, 287, 288,
129 K_PAGEDOWN, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6, K_F7,
130 //289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
131 K_F8, K_F9, K_F10, K_F11, K_F12, 0, 0, 0, 0, 0, 0, K_NUMLOCK, K_CAPSLOCK, K_SCROLLLOCK, K_RSHIFT, K_LSHIFT,
132 //305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
133 K_RCTRL, K_LCTRL, K_RALT, K_LALT, 0, 0, K_LWIN, K_RWIN, 0, 0, 0, K_PRINTSCRN, 0, K_PAUSE, K_MENU, 0,
134 //321
135 0
136 };
137
138 // CODE --------------------------------------------------------------------
139
140 //==========================================================================
141 //
142 // VSdlInputDevice::VSdlInputDevice
143 //
144 //==========================================================================
145
VSdlInputDevice()146 VSdlInputDevice::VSdlInputDevice()
147 : mouse(0)
148 , mouse_oldx(0)
149 , mouse_oldy(0)
150 , joystick(NULL)
151 , joystick_started(false)
152 , joy_num_buttons(0)
153 , joy_x(0)
154 , joy_y(0)
155 , joy_oldx(0)
156 , joy_oldy(0)
157 {
158 guard(VSdlInputDevice::VSdlInputDevice);
159 // always off
160 SDL_ShowCursor(0);
161 // mouse and keyboard are setup using SDL's video interface
162 mouse = 1;
163 if (GArgs.CheckParm("-nomouse"))
164 {
165 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
166 SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
167 SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE);
168 mouse = 0;
169 }
170 else
171 {
172 // ignore mouse motion events in any case...
173 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
174 mouse_oldx = ScreenWidth / 2;
175 mouse_oldy = ScreenHeight / 2;
176 SDL_WarpMouse(mouse_oldx, mouse_oldy);
177 }
178
179 // Initialise joystick
180 StartupJoystick();
181 unguard;
182 }
183
184 //==========================================================================
185 //
186 // VSdlInputDevice::~VSdlInputDevice
187 //
188 //==========================================================================
189
~VSdlInputDevice()190 VSdlInputDevice::~VSdlInputDevice()
191 {
192 guard(VSdlInputDevice::~VSdlInputDevice);
193 // on
194 SDL_ShowCursor(1);
195 if (joystick_started)
196 {
197 SDL_JoystickClose(joystick);
198 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
199 }
200 unguard;
201 }
202
203 //==========================================================================
204 //
205 // VSdlInputDevice::ReadInput
206 //
207 // Reads input from the input devices.
208 //
209 //==========================================================================
210
ReadInput()211 void VSdlInputDevice::ReadInput()
212 {
213 guard(VSdlInputDevice::ReadInput);
214 SDL_Event ev;
215 event_t vev;
216 //int rel_x;
217 //int rel_y;
218 int mouse_x;
219 int mouse_y;
220 int normal_value;
221
222 SDL_PumpEvents();
223 while (SDL_PollEvent(&ev))
224 {
225 switch (ev.type)
226 {
227 case SDL_KEYDOWN:
228 case SDL_KEYUP:
229 if (sym2key[ev.key.keysym.sym])
230 {
231 GInput->KeyEvent(sym2key[ev.key.keysym.sym],
232 (ev.key.state == SDL_PRESSED) ? 1 : 0);
233 }
234 break;
235 #if 0
236 case SDL_MOUSEMOTION:
237 vev.type = ev_mouse;
238 vev.data1 = 0;
239 vev.data2 = ev.motion.xrel;
240 vev.data3 = ev.motion.yrel;
241 GInput->PostEvent(&vev);
242 break;
243 #endif /* 0 */
244 case SDL_MOUSEBUTTONDOWN:
245 case SDL_MOUSEBUTTONUP:
246 vev.type = (ev.button.state == SDL_PRESSED) ? ev_keydown : ev_keyup;
247 if (ev.button.button == SDL_BUTTON_LEFT)
248 vev.data1 = K_MOUSE1;
249 else if (ev.button.button == SDL_BUTTON_RIGHT)
250 vev.data1 = K_MOUSE2;
251 else if (ev.button.button == SDL_BUTTON_MIDDLE)
252 vev.data1 = K_MOUSE3;
253 else if (ev.button.button == SDL_BUTTON_WHEELUP)
254 vev.data1 = K_MWHEELUP;
255 else if (ev.button.button == SDL_BUTTON_WHEELDOWN)
256 vev.data1 = K_MWHEELDOWN;
257 else
258 break;
259 vev.data2 = 0;
260 vev.data3 = 0;
261 GInput->PostEvent(&vev);
262 break;
263 case SDL_JOYAXISMOTION:
264 normal_value = ev.jaxis.value * 127 / 32767;
265 if (ev.jaxis.axis == 0)
266 joy_x = normal_value;
267 else if (ev.jaxis.axis == 1)
268 joy_y = normal_value;
269 break;
270 case SDL_JOYBALLMOTION:
271 break;
272 case SDL_JOYHATMOTION:
273 break;
274 case SDL_JOYBUTTONDOWN:
275 joy_newb[ev.jbutton.button] = 1;
276 break;
277 case SDL_JOYBUTTONUP:
278 joy_newb[ev.jbutton.button] = 0;
279 break;
280 default:
281 break;
282 }
283 }
284
285 // Read mouse separately
286 if (mouse)
287 {
288 SDL_GetMouseState(&mouse_x, &mouse_y);
289 vev.type = ev_mouse;
290 vev.data1 = 0;
291 vev.data2 = mouse_x - ScreenWidth / 2;
292 vev.data3 = ScreenHeight / 2 - mouse_y;
293 GInput->PostEvent(&vev);
294 SDL_WarpMouse(ScreenWidth / 2, ScreenHeight / 2);
295 #if 0
296 SDL_GetRelativeMouseState(&rel_x, &rel_y);
297 vev.type = ev_mouse;
298 vev.data1 = 0;
299 vev.data2 = rel_x;
300 vev.data3 = rel_y;
301 GInput->PostEvent(&vev);
302 #endif
303 }
304
305 PostJoystick();
306
307 unguard;
308 }
309
310 //**************************************************************************
311 //**
312 //** JOYSTICK
313 //**
314 //**************************************************************************
315
316 //==========================================================================
317 //
318 // VSdlInputDevice::StartupJoystick
319 //
320 // Initialises joystick
321 //
322 //==========================================================================
323
StartupJoystick()324 void VSdlInputDevice::StartupJoystick()
325 {
326 guard(VSdlInputDevice::StartupJoystick);
327 if (GArgs.CheckParm("-nojoy"))
328 return;
329
330 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
331 {
332 GCon->Log(NAME_Init, "sdl init joystick failed.");
333 return;
334 }
335 // else
336 // {
337 // SDL_JoystickEventState(SDL_IGNORE);
338 // // we are on our own now...
339 // }
340 joystick = SDL_JoystickOpen(0);
341 if (!joystick)
342 return;
343
344 joy_num_buttons = SDL_JoystickNumButtons(joystick);
345 joystick_started = true;
346 memset(joy_oldb, 0, sizeof(joy_oldb));
347 memset(joy_newb, 0, sizeof(joy_newb));
348 unguard;
349 }
350
351 //==========================================================================
352 //
353 // VSdlInputDevice::PostJoystick
354 //
355 //==========================================================================
356
PostJoystick()357 void VSdlInputDevice::PostJoystick()
358 {
359 guard(VSdlInputDevice::PostJoystick);
360 int i;
361 event_t event;
362
363 if (!joystick_started)
364 return;
365
366 if ((joy_oldx != joy_x) || (joy_oldy != joy_y))
367 {
368 event.type = ev_joystick;
369 event.data1 = 0;
370 event.data2 = joy_x;
371 event.data3 = joy_y;
372 GInput->PostEvent(&event);
373
374 joy_oldx = joy_x;
375 joy_oldy = joy_y;
376 }
377
378 for (i = 0; i < joy_num_buttons; i++)
379 {
380 if (joy_newb[i] != joy_oldb[i])
381 {
382 GInput->KeyEvent(K_JOY1 + i, joy_newb[i]);
383 joy_oldb[i] = joy_newb[i];
384 }
385 }
386 unguard;
387 }
388
389 //**************************************************************************
390 //**
391 //** INPUT
392 //**
393 //**************************************************************************
394
395 //==========================================================================
396 //
397 // VInputDevice::CreateDevice
398 //
399 //==========================================================================
400
CreateDevice()401 VInputDevice* VInputDevice::CreateDevice()
402 {
403 return new VSdlInputDevice();
404 }
405