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 &section, 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