1 /*
2 *
3 * Copyright (c) 1994, 2002, 2003 Johannes Prix
4 * Copyright (c) 1994, 2002, 2003 Reinhard Prix
5 *
6 *
7 * This file is part of Freedroid
8 *
9 * Freedroid is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * Freedroid is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Freedroid; see the file COPYING. If not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 */
25
26 /*----------------------------------------------------------------------
27 *
28 * Desc: functions for keyboard and joystick handling
29 *
30 *----------------------------------------------------------------------*/
31
32 #define _input_c
33
34 #include "system.h"
35
36 #include "defs.h"
37 #include "struct.h"
38 #include "global.h"
39 #include "proto.h"
40
41 #ifndef SDL_BUTTON_WHEELUP
42 #define SDL_BUTTON_WHEELUP 4
43 #endif
44 #ifndef SDL_BUTTON_WHEELDOWN
45 #define SDL_BUTTON_WHEELDOWN 5
46 #endif
47
48 bool show_cursor; // show mouse-cursor or not?
49 #define CURSOR_KEEP_VISIBLE 3000 // ticks to keep mouse-cursor visible without mouse-input
50
51 int WheelUpEvents=0; // count number of not read-out wheel events
52 int WheelDownEvents=0;
53 Uint32 last_mouse_event = 0; // record when last mouse event took place (SDL ticks)
54 int CurrentlyMouseRightPressed=0;
55 int CurrentlyMouseLeftPressed = 0;
56
57 bool key_pressed[SDLK_LAST]; // array of states (pressed/released) of all keys
58 int joy_dirstate[4]; // array of 4 directions we map the joystick to
59
60 SDLMod current_modifiers;
61
62 SDL_Event event;
63
64 // direction for joystick->keyboard mappings
65 enum _joy_dirs {
66 JOY_UP = 0,
67 JOY_RIGHT,
68 JOY_DOWN,
69 JOY_LEFT
70 };
71 #define FLAG_NEW 0xf0
72
73
sgn(int x)74 int sgn (int x)
75 {
76 return (x ? ((x)/abs(x)) : 0);
77 }
78
Init_Joy(void)79 void Init_Joy (void)
80 {
81 int num_joy;
82
83 if (SDL_InitSubSystem (SDL_INIT_JOYSTICK) == -1)
84 {
85 fprintf(stderr, "Couldn't initialize SDL-Joystick: %s\n",SDL_GetError());
86 Terminate(ERR);
87 } else
88 DebugPrintf(1, "\nSDL Joystick initialisation successful.\n");
89
90
91 DebugPrintf (1, " %d Joysticks found!\n", num_joy = SDL_NumJoysticks ());
92
93 if (num_joy > 0)
94 joy = SDL_JoystickOpen (0);
95
96 if (joy)
97 {
98 DebugPrintf (1, "Identifier: %s\n", SDL_JoystickName (0));
99 DebugPrintf (1, "Number of Axes: %d\n", joy_num_axes = SDL_JoystickNumAxes(joy));
100 DebugPrintf (1, "Number of Buttons: %d\n", SDL_JoystickNumButtons(joy));
101
102 /* aktivate Joystick event handling */
103 SDL_JoystickEventState (SDL_ENABLE);
104
105 }
106 else
107 joy = NULL; /* signals that no yoystick is present */
108
109
110 return;
111 }
112
113
114 void
ReactToSpecialKeys(void)115 ReactToSpecialKeys(void)
116 {
117 //--------------------
118 // user asked for quit
119 //
120 if ( KeyIsPressedR('q') )
121 QuitGameMenu();
122
123 if ( KeyIsPressedR('c') && AltPressed() && CtrlPressed() && ShiftPressed() )
124 Cheatmenu ();
125 if ( EscapePressedR() )
126 EscapeMenu ();
127
128 if ( KeyIsPressedR ('p') )
129 Pause ();
130
131 if (KeyIsPressedR (SDLK_F12) )
132 TakeScreenshot();
133
134 } // void ReactToSpecialKeys(void)
135
136 int
keyboard_update(void)137 keyboard_update(void)
138 {
139 Uint8 axis;
140
141 // switch mouse-cursor visibility as a function of time of last activity
142 if (SDL_GetTicks () - last_mouse_event > CURSOR_KEEP_VISIBLE)
143 show_cursor = FALSE;
144 else
145 show_cursor = TRUE;
146
147 while( SDL_PollEvent( &event ) )
148 {
149 switch( event.type )
150 {
151 case SDL_QUIT:
152 printf("\n\nUser requestet Termination...\n\nTerminating...");
153 Terminate(0);
154 break;
155 /* Look for a keypress */
156
157 case SDL_KEYDOWN:
158 current_modifiers = event.key.keysym.mod;
159 key_pressed[event.key.keysym.sym] = TRUE;
160 break;
161 case SDL_KEYUP:
162 current_modifiers = event.key.keysym.mod;
163 key_pressed[event.key.keysym.sym] = FALSE;
164 break;
165
166 case SDL_JOYAXISMOTION:
167 axis = event.jaxis.axis;
168 if (axis == 0 || ((joy_num_axes >= 5) && (axis == 3)) ) /* x-axis */
169 {
170 input_axis.x = event.jaxis.value;
171
172 // this is a bit tricky, because we want to allow direction keys
173 // to be soft-released. When mapping the joystick->keyboard, we
174 // therefore have to make sure that this mapping only occurs when
175 // and actual _change_ of the joystick-direction ('digital') occurs
176 // so that it behaves like "set"/"release"
177 if (joy_sensitivity*event.jaxis.value > 10000) /* about half tilted */
178 {
179 // compare to previous joy-direction!
180 if (!joy_dirstate[JOY_RIGHT])
181 {
182 key_pressed[SDLK_RIGHT] = TRUE;
183 key_pressed[SDLK_LEFT] = FALSE;
184 }
185 joy_dirstate[JOY_RIGHT] = TRUE;
186 joy_dirstate[JOY_LEFT] = FALSE;
187 }
188 else if (joy_sensitivity*event.jaxis.value < -10000)
189 {
190 if (!joy_dirstate[JOY_LEFT])
191 {
192 key_pressed[SDLK_LEFT] = TRUE;
193 key_pressed[SDLK_RIGHT] = FALSE;
194 }
195 joy_dirstate[JOY_LEFT] = TRUE;
196 joy_dirstate[JOY_RIGHT] = FALSE;
197 }
198 else
199 {
200 joy_dirstate[JOY_LEFT] = FALSE;
201 joy_dirstate[JOY_RIGHT] = FALSE;
202 key_pressed[SDLK_LEFT] = FALSE;
203 key_pressed[SDLK_RIGHT] = FALSE;
204 }
205 }
206 else if ((axis == 1) || ((joy_num_axes >=5) && (axis == 4))) /* y-axis */
207 {
208 input_axis.y = event.jaxis.value;
209
210 if (joy_sensitivity*event.jaxis.value > 10000)
211 {
212 if (!joy_dirstate[JOY_DOWN])
213 {
214 key_pressed[SDLK_DOWN] = TRUE;
215 key_pressed[SDLK_UP] = FALSE;
216 }
217 joy_dirstate[JOY_DOWN] = TRUE;
218 joy_dirstate[JOY_UP] = FALSE;
219 }
220 else if (joy_sensitivity*event.jaxis.value < -10000)
221 {
222 if (!joy_dirstate[JOY_UP])
223 {
224 key_pressed[SDLK_UP] = TRUE;
225 key_pressed[SDLK_DOWN] = FALSE;
226 }
227 joy_dirstate[JOY_UP] = TRUE;
228 joy_dirstate[JOY_DOWN]= FALSE;
229 }
230 else
231 {
232 joy_dirstate[JOY_UP] = FALSE;
233 joy_dirstate[JOY_DOWN] = FALSE;
234 key_pressed[SDLK_UP] = FALSE;
235 key_pressed[SDLK_DOWN] = FALSE;
236 }
237 }
238
239 break;
240
241 case SDL_JOYBUTTONDOWN: // here we do some brute-force remappings...
242 // map first button onto fire,
243 if (event.jbutton.button == 0)
244 key_pressed[SDLK_SPACE] = TRUE;
245
246 // second button onto MouseRight (i.e Takeover)
247 else if (event.jbutton.button == 1)
248 CurrentlyMouseRightPressed = TRUE;
249
250 // and third button onto 'RSHIFT' , i.e Activate
251 else if (event.jbutton.button == 2)
252 key_pressed[SDLK_RSHIFT] = TRUE;
253
254 axis_is_active = TRUE;
255 break;
256
257 case SDL_JOYBUTTONUP:
258 // map first button onto fire,
259 if (event.jbutton.button == 0)
260 key_pressed[SDLK_SPACE] = FALSE;
261
262 // second button onto MouseRight (i.e Takeover)
263 else if (event.jbutton.button == 1)
264 CurrentlyMouseRightPressed = FALSE;
265
266 // and third button onto 'RSHIFT' , i.e Activate
267 else if (event.jbutton.button == 2)
268 key_pressed[SDLK_RSHIFT] = FALSE;
269
270 axis_is_active = FALSE;
271 break;
272
273 case SDL_MOUSEMOTION:
274 input_axis.x = event.button.x - UserCenter_x + 16;
275 input_axis.y = event.button.y - UserCenter_y + 16;
276
277 last_mouse_event = SDL_GetTicks ();
278
279 break;
280
281 /* Mouse control */
282 case SDL_MOUSEBUTTONDOWN:
283 if (event.button.button == SDL_BUTTON_LEFT)
284 {
285 CurrentlyMouseLeftPressed = TRUE;
286 axis_is_active = TRUE;
287 }
288
289 if (event.button.button == SDL_BUTTON_RIGHT)
290 CurrentlyMouseRightPressed = TRUE;
291
292 // we just map middle->Rshift (i.e. Activate)
293 if (event.button.button == SDL_BUTTON_MIDDLE)
294 key_pressed[SDLK_RSHIFT] = TRUE;
295
296 // wheel events are immediately released, so we rather
297 // count the number of not yet read-out events
298 if (event.button.button == SDL_BUTTON_WHEELUP)
299 WheelUpEvents ++;
300
301 if (event.button.button == SDL_BUTTON_WHEELDOWN)
302 WheelDownEvents ++;
303
304 last_mouse_event = SDL_GetTicks();
305 break;
306
307 case SDL_MOUSEBUTTONUP:
308 if (event.button.button == SDL_BUTTON_LEFT)
309 {
310 CurrentlyMouseLeftPressed = FALSE;
311 axis_is_active = FALSE;
312 }
313
314 if (event.button.button == SDL_BUTTON_RIGHT)
315 CurrentlyMouseRightPressed = FALSE;
316
317 if (event.button.button == SDL_BUTTON_MIDDLE) // we just map middle->Escape
318 key_pressed[SDLK_RSHIFT] = FALSE;
319
320 break;
321
322 default:
323 break;
324 }
325
326 }
327
328 return 0;
329 }
330
331 /*-----------------------------------------------------------------
332 * Desc: should do roughly what getchar() does, but in raw
333 * (SLD) keyboard mode.
334 *
335 * Return: the (SDLKey) of the next key-pressed event cast to (int)
336 *
337 *-----------------------------------------------------------------*/
338 int
getchar_raw(void)339 getchar_raw (void)
340 {
341 SDL_Event event;
342 int Returnkey;
343
344 // keyboard_update (); /* treat all pending keyboard-events */
345
346 while (1)
347 {
348 SDL_WaitEvent (&event); /* wait for next event */
349
350 if (event.type == SDL_KEYDOWN)
351 {
352 /*
353 * here we use the fact that, I cite from SDL_keyboard.h:
354 * "The keyboard syms have been cleverly chosen to map to ASCII"
355 * ... I hope that this design feature is portable, and durable ;)
356 */
357 Returnkey = (int) event.key.keysym.sym;
358 if ( event.key.keysym.mod & KMOD_SHIFT ) Returnkey = toupper( (int)event.key.keysym.sym );
359 return ( Returnkey );
360 }
361 else
362 {
363 SDL_PushEvent (&event); /* put this event back into the queue */
364 keyboard_update (); /* and treat it the usual way */
365 continue;
366 }
367
368 } /* while(1) */
369
370 } /* getchar_raw() */
371
372 // forget the wheel-counters
373 void
ResetMouseWheel(void)374 ResetMouseWheel (void)
375 {
376 WheelUpEvents = WheelDownEvents = 0;
377 return;
378 }
379
380 bool
WheelUpPressed(void)381 WheelUpPressed (void)
382 {
383 keyboard_update();
384 if (WheelUpEvents)
385 return (WheelUpEvents--);
386 else
387 return (FALSE);
388 }
389
390 bool
WheelDownPressed(void)391 WheelDownPressed (void)
392 {
393 keyboard_update();
394 if (WheelDownEvents)
395 return (WheelDownEvents--);
396 else
397 return (FALSE);
398 }
399
400 bool
KeyIsPressed(SDLKey key)401 KeyIsPressed (SDLKey key)
402 {
403 keyboard_update();
404 return (key_pressed[key]);
405 }
406
407
408 // does the same as KeyIsPressed, but automatically releases the key as well..
409 bool
KeyIsPressedR(SDLKey key)410 KeyIsPressedR (SDLKey key)
411 {
412 bool ret;
413 keyboard_update();
414 ret = key_pressed[key];
415 ReleaseKey (key);
416 return (ret);
417 }
418
419 void
ReleaseKey(SDLKey key)420 ReleaseKey (SDLKey key)
421 {
422 key_pressed[key] = FALSE;
423 return;
424 }
425
426 bool
ModIsPressed(SDLMod mod)427 ModIsPressed (SDLMod mod)
428 {
429 bool ret;
430 keyboard_update();
431 ret = ( (current_modifiers & mod) != 0) ;
432 return (ret);
433 }
434
435 bool
NoDirectionPressed(void)436 NoDirectionPressed (void)
437 {
438 if ( (axis_is_active && (input_axis.x || input_axis.y)) ||
439 DownPressed () || UpPressed() || LeftPressed() || RightPressed() )
440 return ( FALSE );
441 else
442 return ( TRUE );
443 } // int NoDirectionPressed(void)
444
445
446 bool
MouseRightPressed(void)447 MouseRightPressed(void)
448 {
449 keyboard_update();
450 return (CurrentlyMouseRightPressed);
451 }
452
453
454 bool
MouseRightPressedR(void)455 MouseRightPressedR (void)
456 {
457 bool ret;
458 keyboard_update();
459 ret = CurrentlyMouseRightPressed;
460 CurrentlyMouseRightPressed = FALSE;
461 return (ret);
462 }
463
464 bool
MouseLeftPressed(void)465 MouseLeftPressed(void)
466 {
467 keyboard_update();
468 return CurrentlyMouseLeftPressed;
469 }
470
471 bool
MouseLeftPressedR(void)472 MouseLeftPressedR (void)
473 {
474 bool ret;
475 keyboard_update();
476 ret = CurrentlyMouseLeftPressed;
477 CurrentlyMouseLeftPressed = FALSE;
478 return (ret);
479 }
480
481
482
483
484
485 #undef _intput_c
486