1 /***************************************************************************
2 gamewinsystem.cpp - Window managing with game key settings
3 -------------------
4 begin : do sep 16 2004
5 copyright : (C) 2004 by CJP
6 email : cornware-cjp@users.sourceforge.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include <cstdio>
19
20 #include "SDL.h"
21
22 #include "lconfig.h"
23
24 #include "gamewinsystem.h"
25
26 /*
27 Key codes used in SDL implementation:
28
29 0 .. SDLK_LAST-1: SDL keyboard
30 SDLK_LAST .. SDLK_LAST+255: First joystick
31 ... other joysticks
32 (max. 8 joysticks)
33
34 So, with the defines below:
35 joystick x button y = JOYSTICK + JOY_NUMCODES*x + JOY_BTN + y
36 joystick x lefy = JOYSTICK + JOY_NUMCODES*x + JOY_LEFT
37 */
38
39 #define JOYSTICK (SDLK_LAST)
40 #define JOY_LEFT (0)
41 #define JOY_RIGHT (1)
42 #define JOY_UP (2)
43 #define JOY_DOWN (3)
44 #define JOY_BTN (4)
45
46 #define JOY_NUMCODES (256)
47 #define MAX_NUM_JOYBUTTONS (JOY_NUMCODES - JOY_BTN)
48
49 #define MAX_NUM_JOYSTICKS (8)
50
51 vector<CGameWinSystem::SKeyName> CGameWinSystem::m_KeyNames;
52
CGameWinSystem(const CString & caption)53 CGameWinSystem::CGameWinSystem(const CString &caption) : CWinSystem(caption)
54 {
55 //allocate the keycode arrays
56 for(unsigned int p=0; p < 4; p++)
57 {
58 tCodeArray keys(10), controls(4);
59 m_PlayerKeyCode.push_back(keys);
60 m_PlayerControlCode.push_back(controls);
61 }
62 m_GlobalKeyCode = tCodeArray(10);
63
64 reloadConfiguration();
65 }
66
reloadConfiguration()67 bool CGameWinSystem::reloadConfiguration()
68 {
69 if(!CWinSystem::reloadConfiguration()) return false;
70
71 CLConfig &conf = *theMainConfig;
72
73 //set default values
74 m_GlobalKeyCode[eNextSong] = name2key(conf.getValue("input_global", "nextsong"));
75 m_GlobalKeyCode[ePause] = name2key(conf.getValue("input_global", "pause"));
76
77 setupKeys("input_player0", 0);
78 setupKeys("input_player1", 1);
79 setupKeys("input_player2", 2);
80 setupKeys("input_player3", 3);
81
82 return true;
83 }
84
~CGameWinSystem()85 CGameWinSystem::~CGameWinSystem()
86 {
87 }
88
setupKeys(const CString & section,unsigned int player)89 void CGameWinSystem::setupKeys(const CString §ion, unsigned int player)
90 {
91 CLConfig &conf = *theMainConfig;
92 m_PlayerKeyCode[player][eShiftUp] = name2key(conf.getValue(section, "shiftup"));
93 m_PlayerKeyCode[player][eShiftDown] = name2key(conf.getValue(section, "shiftdown"));
94 m_PlayerKeyCode[player][eHorn] = name2key(conf.getValue(section, "horn"));
95 m_PlayerKeyCode[player][eCameraChange] = name2key(conf.getValue(section, "camerachange"));
96 m_PlayerKeyCode[player][eCameraToggle] = name2key(conf.getValue(section, "cameratoggle"));
97 m_PlayerControlCode[player][eUp] = name2key(conf.getValue(section, "up"));
98 m_PlayerControlCode[player][eDown] = name2key(conf.getValue(section, "down"));
99 m_PlayerControlCode[player][eLeft] = name2key(conf.getValue(section, "left"));
100 m_PlayerControlCode[player][eRight] = name2key(conf.getValue(section, "right"));
101 }
102
103
104 // Public interface:
105
getPlayerControlState(ePlayerControl ctl,unsigned int player)106 float CGameWinSystem::getPlayerControlState(ePlayerControl ctl, unsigned int player)
107 {
108 return getControlCodeState(getPlayerControlCode(ctl, player));
109 }
110
getPlayerKeyState(ePlayerKey key,unsigned int player)111 bool CGameWinSystem::getPlayerKeyState(ePlayerKey key, unsigned int player)
112 {
113 return getKeyCodeState(getPlayerKeyCode(key, player));
114 }
115
playerKeyWasPressed(ePlayerKey key,unsigned int player)116 bool CGameWinSystem::playerKeyWasPressed(ePlayerKey key, unsigned int player)
117 {
118 return keyCodeWasPressed(getPlayerKeyCode(key, player));
119 }
120
getGlobalKeyState(eGlobalKey key)121 bool CGameWinSystem::getGlobalKeyState(eGlobalKey key)
122 {
123 return getKeyCodeState(getGlobalKeyCode(key));
124 }
125
globalKeyWasPressed(eGlobalKey key)126 bool CGameWinSystem::globalKeyWasPressed(eGlobalKey key)
127 {
128 return keyCodeWasPressed(getGlobalKeyCode(key));
129 }
130
getKeyFromGlobalKey(eGlobalKey key)131 unsigned int CGameWinSystem::getKeyFromGlobalKey(eGlobalKey key)
132 {
133 return getGlobalKeyCode(key);
134 }
135
initKeyNameTranslationTable()136 void CGameWinSystem::initKeyNameTranslationTable()
137 {
138 m_KeyNames.clear();
139
140 //single character key names:
141 CString c = " ";
142 for(char i = 'a'; i <= 'z'; i++)
143 {
144 c[0] = i;
145 m_KeyNames.push_back(SKeyName(i , c));
146 }
147 for(char i = '0'; i <= '9'; i++)
148 {
149 c[0] = i;
150 m_KeyNames.push_back(SKeyName(i , c));
151 }
152 c = "`~!@#$%^&*()-=_+[]{}\\|;\':\",./<>?";
153 for(unsigned int i=0; i < c.length(); i++)
154 {
155 m_KeyNames.push_back(SKeyName(c[i] , c.mid(i, 1)));
156 }
157
158 //misc keys
159 m_KeyNames.push_back(SKeyName(SDLK_RETURN , "return"));
160 m_KeyNames.push_back(SKeyName(' ' , "space"));
161 m_KeyNames.push_back(SKeyName(SDLK_TAB , "tab"));
162 m_KeyNames.push_back(SKeyName(SDLK_ESCAPE , "escape"));
163 m_KeyNames.push_back(SKeyName(SDLK_BACKSPACE, "backspace"));
164
165 //modifier keys
166 m_KeyNames.push_back(SKeyName(SDLK_LCTRL , "lctrl"));
167 m_KeyNames.push_back(SKeyName(SDLK_RCTRL , "rctrl"));
168 m_KeyNames.push_back(SKeyName(SDLK_LSHIFT, "lshift"));
169 m_KeyNames.push_back(SKeyName(SDLK_RSHIFT, "rshift"));
170 m_KeyNames.push_back(SKeyName(SDLK_LALT , "lalt"));
171 m_KeyNames.push_back(SKeyName(SDLK_RALT , "ralt"));
172 m_KeyNames.push_back(SKeyName(SDLK_LMETA , "lmeta"));
173 m_KeyNames.push_back(SKeyName(SDLK_RMETA , "rmeta"));
174
175 //keypad
176 m_KeyNames.push_back(SKeyName(SDLK_KP0, "kp0"));
177 m_KeyNames.push_back(SKeyName(SDLK_KP1, "kp1"));
178 m_KeyNames.push_back(SKeyName(SDLK_KP2, "kp2"));
179 m_KeyNames.push_back(SKeyName(SDLK_KP3, "kp3"));
180 m_KeyNames.push_back(SKeyName(SDLK_KP4, "kp4"));
181 m_KeyNames.push_back(SKeyName(SDLK_KP5, "kp5"));
182 m_KeyNames.push_back(SKeyName(SDLK_KP6, "kp6"));
183 m_KeyNames.push_back(SKeyName(SDLK_KP7, "kp7"));
184 m_KeyNames.push_back(SKeyName(SDLK_KP8, "kp8"));
185 m_KeyNames.push_back(SKeyName(SDLK_KP9, "kp9"));
186 m_KeyNames.push_back(SKeyName(SDLK_KP_ENTER , "kpenter"));
187 m_KeyNames.push_back(SKeyName(SDLK_KP_DIVIDE , "kp/"));
188 m_KeyNames.push_back(SKeyName(SDLK_KP_MULTIPLY, "kp*"));
189 m_KeyNames.push_back(SKeyName(SDLK_KP_PLUS , "kp+"));
190 m_KeyNames.push_back(SKeyName(SDLK_KP_MINUS , "kp-"));
191 m_KeyNames.push_back(SKeyName(SDLK_KP_PERIOD , "kp."));
192 m_KeyNames.push_back(SKeyName(SDLK_KP_EQUALS , "kp="));
193
194 //navigation island
195 m_KeyNames.push_back(SKeyName(SDLK_INSERT , "insert"));
196 m_KeyNames.push_back(SKeyName(SDLK_DELETE , "delete"));
197 m_KeyNames.push_back(SKeyName(SDLK_HOME , "home"));
198 m_KeyNames.push_back(SKeyName(SDLK_END , "end"));
199 m_KeyNames.push_back(SKeyName(SDLK_PAGEUP , "pageup"));
200 m_KeyNames.push_back(SKeyName(SDLK_PAGEDOWN, "pagedown"));
201
202 m_KeyNames.push_back(SKeyName(SDLK_PAUSE , "pause"));
203
204 //function keys
205 m_KeyNames.push_back(SKeyName(SDLK_F1 , "f1"));
206 m_KeyNames.push_back(SKeyName(SDLK_F2 , "f2"));
207 m_KeyNames.push_back(SKeyName(SDLK_F3 , "f3"));
208 m_KeyNames.push_back(SKeyName(SDLK_F4 , "f4"));
209 m_KeyNames.push_back(SKeyName(SDLK_F5 , "f5"));
210 m_KeyNames.push_back(SKeyName(SDLK_F6 , "f6"));
211 m_KeyNames.push_back(SKeyName(SDLK_F7 , "f7"));
212 m_KeyNames.push_back(SKeyName(SDLK_F8 , "f8"));
213 m_KeyNames.push_back(SKeyName(SDLK_F9 , "f9"));
214 m_KeyNames.push_back(SKeyName(SDLK_F10, "f10"));
215 m_KeyNames.push_back(SKeyName(SDLK_F11, "f11"));
216 m_KeyNames.push_back(SKeyName(SDLK_F12, "f12"));
217
218 //cursor keys
219 m_KeyNames.push_back(SKeyName(SDLK_UP , "up"));
220 m_KeyNames.push_back(SKeyName(SDLK_DOWN , "down"));
221 m_KeyNames.push_back(SKeyName(SDLK_LEFT , "left"));
222 m_KeyNames.push_back(SKeyName(SDLK_RIGHT, "right"));
223
224 //joysticks
225 for(unsigned int i=0; i < MAX_NUM_JOYSTICKS; i++)
226 {
227 m_KeyNames.push_back(SKeyName(
228 JOYSTICK + JOY_NUMCODES*i + JOY_UP,
229 CString().format("joy%dup", 16, i)));
230 m_KeyNames.push_back(SKeyName(
231 JOYSTICK + JOY_NUMCODES*i + JOY_DOWN,
232 CString().format("joy%ddown", 16, i)));
233 m_KeyNames.push_back(SKeyName(
234 JOYSTICK + JOY_NUMCODES*i + JOY_LEFT,
235 CString().format("joy%dleft", 16, i)));
236 m_KeyNames.push_back(SKeyName(
237 JOYSTICK + JOY_NUMCODES*i + JOY_RIGHT,
238 CString().format("joy%dright", 16, i)));
239
240 for(unsigned int j=0; j < MAX_NUM_JOYBUTTONS; j++)
241 m_KeyNames.push_back(SKeyName(
242 JOYSTICK + JOY_NUMCODES*i + JOY_BTN+j ,
243 CString().format("joy%dbutton%d", 32, i, j)
244 ));
245 }
246 }
247
key2name(unsigned int key) const248 CString CGameWinSystem::key2name(unsigned int key) const
249 {
250 if(m_KeyNames.size() == 0) initKeyNameTranslationTable();
251
252 for(unsigned int i=0; i < m_KeyNames.size(); i++)
253 if(m_KeyNames[i].key == (int)key)
254 return m_KeyNames[i].name;
255
256 printf("Key %d is unknown\n", key);
257 return ""; //not found
258 }
259
name2key(const CString & name) const260 unsigned int CGameWinSystem::name2key(const CString &name) const
261 {
262 if(m_KeyNames.size() == 0) initKeyNameTranslationTable();
263
264 for(unsigned int i=0; i < m_KeyNames.size(); i++)
265 if(m_KeyNames[i].name == name)
266 return m_KeyNames[i].key;
267
268 return 0; //not found
269 }
270
271
272 //Enum to keycode conversion
273
getGlobalKeyCode(eGlobalKey key)274 unsigned int CGameWinSystem::getGlobalKeyCode(eGlobalKey key)
275 {
276 return m_GlobalKeyCode[key];
277 }
278
getPlayerKeyCode(ePlayerKey key,unsigned int player)279 unsigned int CGameWinSystem::getPlayerKeyCode(ePlayerKey key, unsigned int player)
280 {
281 return m_PlayerKeyCode[player][key];
282 }
283
getPlayerControlCode(ePlayerControl ctl,unsigned int player)284 unsigned int CGameWinSystem::getPlayerControlCode(ePlayerControl ctl, unsigned int player)
285 {
286 return m_PlayerControlCode[player][ctl];
287 }
288
289
290
291 //Get state from keycode
292
getKeyCodeState(unsigned int code)293 bool CGameWinSystem::getKeyCodeState(unsigned int code)
294 {
295 //SDL keys
296 if(code < SDLK_LAST)
297 {
298 return getKeyState(code);
299 }
300
301 //Joysticks
302 int joyID = (code - JOYSTICK) / JOY_NUMCODES;
303 if(
304 joyID >= 0 &&
305 joyID < MAX_NUM_JOYSTICKS &&
306 (unsigned int)joyID < m_Joysticks.size() &&
307 m_Joysticks[joyID].joystick != NULL
308 )
309 {
310 int button = code - JOYSTICK - JOY_NUMCODES*joyID - JOY_BTN;
311 if(button < 0)
312 return false;
313
314 return SDL_JoystickGetButton(m_Joysticks[joyID].joystick, button);
315 }
316
317 return false;
318 }
319
keyCodeWasPressed(unsigned int code)320 bool CGameWinSystem::keyCodeWasPressed(unsigned int code)
321 {
322 //SDL keys
323 if(code < SDLK_LAST)
324 return wasPressed(code);
325
326 //Joysticks
327 int joyID = (code - JOYSTICK) / JOY_NUMCODES;
328 if(joyID >= 0 && joyID < MAX_NUM_JOYSTICKS)
329 {
330 int button = code - JOYSTICK - JOY_NUMCODES*joyID - JOY_BTN;
331 if(button < 0)
332 return false;
333
334 return joyBtnWasPressed(joyID, button);
335 }
336
337 return false;
338 }
339
getControlCodeState(unsigned int code)340 float CGameWinSystem::getControlCodeState(unsigned int code)
341 {
342 //SDL keys
343 if(code < SDLK_LAST)
344 {
345 return (float)(getKeyState(code));
346 }
347
348 //Joysticks
349 int joyID = (code - JOYSTICK) / JOY_NUMCODES;
350 if(
351 joyID >= 0 &&
352 joyID < MAX_NUM_JOYSTICKS &&
353 (unsigned int)joyID < m_Joysticks.size() &&
354 m_Joysticks[joyID].joystick != NULL
355 )
356 {
357 SDL_Joystick *js = m_Joysticks[joyID].joystick;
358 int direction = code - JOYSTICK - JOY_NUMCODES*joyID;
359 if(direction == JOY_LEFT)
360 {
361 float val = (float)-SDL_JoystickGetAxis(js, 0) / 32767;
362 if(val < 0.0) val = 0.0;
363 return val;
364 }
365 else if(direction == JOY_RIGHT)
366 {
367 float val = (float)SDL_JoystickGetAxis(js, 0) / 32767;
368 if(val < 0.0) val = 0.0;
369 return val;
370 }
371 else if(direction == JOY_UP)
372 {
373 float val = (float)-SDL_JoystickGetAxis(js, 1) / 32767;
374 if(val < 0.0) val = 0.0;
375 return val;
376 }
377 else if(direction == JOY_DOWN)
378 {
379 float val = (float)SDL_JoystickGetAxis(js, 1) / 32767;
380 if(val < 0.0) val = 0.0;
381 return val;
382 }
383 //TODO: support joystick buttons for controls
384 }
385
386 return 0.0;
387 }
388
getJoystickKeyCode(unsigned int joystick,unsigned int button)389 unsigned int CGameWinSystem::getJoystickKeyCode(unsigned int joystick, unsigned int button)
390 {
391 return JOYSTICK + JOY_NUMCODES*joystick + JOY_BTN + button;
392 }
393
getJoystickAxisCode(unsigned int joystick,unsigned int axis,bool positive)394 unsigned int CGameWinSystem::getJoystickAxisCode(unsigned int joystick, unsigned int axis, bool positive)
395 {
396 unsigned int offset = JOYSTICK + JOY_NUMCODES*joystick;
397
398 if(axis == 0 && positive) return offset + JOY_RIGHT;
399 if(axis == 0 && !positive) return offset + JOY_LEFT;
400 if(axis == 1 && !positive) return offset + JOY_UP;
401 if(axis == 1 && positive) return offset + JOY_DOWN;
402
403 return 0;
404 }
405
406