1 /* Tower Toppler - Nebulus
2  * Copyright (C) 2000-2012  Andreas R�ver
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (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, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 
19 #include "keyb.h"
20 #include "decl.h"
21 
22 #include <SDL.h>
23 
24 static ttkey keydown, keytyped;
25 static char chartyped;
26 static SDLKey sdlkeytyped;
27 static Uint16 mouse_x, mouse_y;
28 static bool mouse_moved;
29 static Uint16 mouse_button;
30 static int joy_inited = 0;
31 SDL_Joystick *joy;
32 
33 class quit_action_class {};
34 
35 #define JOYSTICK_DEADZONE 6000
36 
37 bool tt_has_focus;
38 
39 struct _ttkeyconv {
40    ttkey outval;
41    SDLKey key;
42 } static ttkeyconv[] = {
43    {up_key, SDLK_UP},
44    {down_key, SDLK_DOWN},
45    {left_key, SDLK_LEFT},
46    {right_key, SDLK_RIGHT},
47    {fire_key, SDLK_SPACE},
48    {fire_key, SDLK_RETURN},
49    {break_key, SDLK_ESCAPE},
50    {pause_key, SDLK_p},
51    {up_key, SDLK_UP},
52    {down_key, SDLK_DOWN},
53    {left_key, SDLK_LEFT},
54    {right_key, SDLK_RIGHT},
55    {fire_key, SDLK_SPACE},
56    {break_key, SDLK_ESCAPE},
57    {pause_key, SDLK_p},
58 };
59 
key_redefine(ttkey code,SDLKey key)60 void key_redefine(ttkey code, SDLKey key) {
61   int i;
62 
63   for (i = SIZE(ttkeyconv) - 1; i >= 0; i--)
64     if (ttkeyconv[i].outval == code) {
65       ttkeyconv[i].key = key;
66       break;
67     }
68 }
69 
key_init(void)70 void key_init(void) {
71   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
72   SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
73   SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
74 
75   SDL_EnableUNICODE(1);
76 
77   if (joy_inited == 0) {
78     if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
79       joy_inited = 2;
80     } else {
81       joy = SDL_JoystickOpen(0);
82       if (!joy) {
83         joy_inited = 2;
84       } else {
85         SDL_JoystickEventState(SDL_ENABLE);
86         printf("Joystick enabled\n");
87         joy_inited = 1;
88       }
89     }
90   }
91 
92   chartyped = 0;
93   keytyped = keydown = no_key;
94   sdlkeytyped = SDLK_UNKNOWN;
95   mouse_button = mouse_x = mouse_y = 0;
96   mouse_moved = false;
97 }
98 
handleEvents(void)99 static void handleEvents(void) {
100   SDL_Event e;
101 
102   while (SDL_PollEvent(&e)) {
103 
104     switch (e.type) {
105     case SDL_ACTIVEEVENT:
106       if ((e.active.state & SDL_APPINPUTFOCUS) || (e.active.state & SDL_APPACTIVE))
107         tt_has_focus = (e.active.gain == 1);
108       break;
109     case SDL_MOUSEMOTION:
110       mouse_x = e.motion.x;
111       mouse_y = e.motion.y;
112       mouse_moved = true;
113       break;
114     case SDL_JOYAXISMOTION:
115       if (e.jaxis.axis == 0) {
116         if (e.jaxis.value < -JOYSTICK_DEADZONE) {
117           keydown = (ttkey) (keydown | left_key);
118         } else
119         if (e.jaxis.value > JOYSTICK_DEADZONE) {
120           keydown = (ttkey) (keydown | right_key);
121         } else
122           keydown = (ttkey) (keydown & ~(right_key|left_key));
123       }
124       if (e.jaxis.axis == 1) {
125         if (e.jaxis.value < -JOYSTICK_DEADZONE) {
126           keydown = (ttkey) (keydown | up_key);
127         } else
128         if (e.jaxis.value > JOYSTICK_DEADZONE) {
129           keydown = (ttkey) (keydown | down_key);
130         } else
131           keydown = (ttkey) (keydown & ~(up_key|down_key));
132       }
133       keytyped = keydown;
134       break;
135     case SDL_JOYBUTTONDOWN:
136       keydown = (ttkey)(keydown | fire_key);
137       keytyped = keydown;
138       break;
139     case SDL_JOYBUTTONUP:
140       keydown = (ttkey)(keydown & ~fire_key);
141       keytyped = keydown;
142       break;
143     case SDL_MOUSEBUTTONDOWN:
144     case SDL_MOUSEBUTTONUP:
145       mouse_x = e.button.x;
146       mouse_y = e.button.y;
147       mouse_button = e.button.button;
148       break;
149     case SDL_QUIT:
150       fprintf(stderr, _("Wheee!!\n"));
151       exit(0);
152       break;
153     case SDL_KEYDOWN:
154     case SDL_KEYUP:
155 
156       ttkey key = no_key;
157       for (int tmpk = 0; tmpk < SIZE(ttkeyconv); tmpk++)
158         if (ttkeyconv[tmpk].key == e.key.keysym.sym) {
159           key = ttkeyconv[tmpk].outval;
160           break;
161         }
162 
163       if (e.key.state == SDL_PRESSED) {
164 
165         if ((e.key.keysym.unicode & 0xff80) == 0) {
166           chartyped = e.key.keysym.unicode & 0x7f;
167         } else
168           chartyped = 0;
169 
170         sdlkeytyped = e.key.keysym.sym;
171 
172         keydown = (ttkey)(keydown | key);
173         keytyped = (ttkey)(keytyped | key);
174 
175       } else {
176         keydown = (ttkey)(keydown & ~key);
177       }
178       break;
179     }
180   }
181 }
182 
key_done(void)183 void key_done(void) {
184   SDL_JoystickClose(joy);
185 }
186 
key_keystat(void)187 Uint16 key_keystat(void) {
188   handleEvents();
189   return keydown;
190 }
191 
key_keypressed(ttkey key)192 bool key_keypressed(ttkey key) {
193   handleEvents();
194   return (keytyped & key) != 0;
195 }
196 
key_sdlkey(void)197 SDLKey key_sdlkey(void) {
198   handleEvents();
199   SDLKey tmp = sdlkeytyped;
200   sdlkeytyped = SDLK_UNKNOWN;
201   keytyped = no_key;
202   chartyped = 0;
203   return tmp;
204 }
205 
key_keydatas(SDLKey & sdlkey,ttkey & tkey,char & ch)206 void key_keydatas(SDLKey &sdlkey, ttkey &tkey, char &ch) {
207   handleEvents();
208   sdlkey = sdlkeytyped;
209   tkey = keytyped;
210   ch = chartyped;
211   sdlkeytyped = SDLK_UNKNOWN;
212   keytyped = no_key;
213   chartyped = 0;
214 }
215 
216 
key_conv2sdlkey(ttkey k,bool game)217 SDLKey key_conv2sdlkey(ttkey k, bool game) {
218   register int i;
219 
220   if (game) {
221     for (i = SIZE(ttkeyconv) - 1; i >= 0; i--)
222       if (ttkeyconv[i].outval == k)
223         return ttkeyconv[i].key;
224   } else {
225     for (i = 0; i < SIZE(ttkeyconv); i++)
226       if (ttkeyconv[i].outval == k)
227         return ttkeyconv[i].key;
228   }
229 
230   return SDLK_UNKNOWN;
231 }
232 
key_sdlkey2conv(SDLKey k,bool game)233 ttkey key_sdlkey2conv(SDLKey k, bool game) {
234   register int i;
235 
236   if (k != SDLK_UNKNOWN) {
237     if (game) {
238       for (i = SIZE(ttkeyconv) - 1; i >= 0; i--)
239         if (ttkeyconv[i].key == k)
240           return ttkeyconv[i].outval;
241     } else {
242       for (i = 0; i < SIZE(ttkeyconv); i++)
243         if (ttkeyconv[i].key == k)
244           return ttkeyconv[i].outval;
245     }
246   }
247 
248   return no_key;
249 }
250 
key_readkey(void)251 ttkey key_readkey(void) {
252   handleEvents();
253 
254   ttkey i = keytyped;
255 
256   keytyped = no_key;
257   chartyped = 0;
258   sdlkeytyped = SDLK_UNKNOWN;
259 
260   return i;
261 }
262 
wait_for_focus(void)263 void wait_for_focus(void) {
264 
265   while (!tt_has_focus) {
266     SDL_Delay(200);
267     handleEvents();
268   }
269 
270   keytyped = no_key;
271   chartyped = 0;
272   sdlkeytyped = SDLK_UNKNOWN;
273 }
274 
key_chartyped(void)275 char key_chartyped(void) {
276   handleEvents();
277   int erg = chartyped;
278   chartyped = 0;
279   return erg;
280 }
281 
key_wait_for_none(keyb_wait_proc bg)282 void key_wait_for_none(keyb_wait_proc bg) {
283 
284   do {
285     handleEvents();
286     if (bg) (*bg)();
287   } while (keydown);
288 
289   keytyped = no_key;
290   chartyped = 0;
291   sdlkeytyped = SDLK_UNKNOWN;
292 }
293 
key_mouse(Uint16 * x,Uint16 * y,ttkey * bttn)294 bool key_mouse(Uint16 *x, Uint16 *y, ttkey *bttn) {
295   bool tmp = mouse_moved;
296   handleEvents();
297   switch (mouse_button) {
298   default: *bttn = no_key; break;
299   }
300   mouse_moved = false;
301   mouse_button = 0;
302   if (tmp) {
303     *x = mouse_x;
304     *y = mouse_y;
305   } else {
306     *x = *y = 0;
307   }
308   return tmp;
309 }
310