DEADSOFTWARE

moved to SDL2
[d2df-sdl.git] / src / engine / e_input.pas
1 unit e_input;
3 interface
5 uses
6 SysUtils,
7 e_log,
8 SDL2;
10 const
11 e_MaxKbdKeys = SDL_NUM_SCANCODES;
12 e_MaxJoys = 4;
13 e_MaxJoyBtns = 32;
14 e_MaxJoyAxes = 4;
15 e_MaxJoyHats = 4;
17 e_MaxJoyKeys = e_MaxJoyBtns + e_MaxJoyAxes*2 + e_MaxJoyHats*4;
19 e_MaxInputKeys = e_MaxKbdKeys + e_MaxJoys*e_MaxJoyKeys - 1;
20 // $$$..$$$ - 321 Keyboard buttons/keys
21 // $$$..$$$ - 4*32 Joystick buttons
22 // $$$..$$$ - 4*4 Joystick axes (- and +)
23 // $$$..$$$ - 4*4 Joystick hats (L U R D)
25 // these are apparently used in g_gui and g_game and elsewhere
26 IK_INVALID = 65535;
27 IK_ESCAPE = SDL_SCANCODE_ESCAPE;
28 IK_RETURN = SDL_SCANCODE_RETURN;
29 IK_ENTER = SDL_SCANCODE_RETURN;
30 IK_UP = SDL_SCANCODE_UP;
31 IK_DOWN = SDL_SCANCODE_DOWN;
32 IK_LEFT = SDL_SCANCODE_LEFT;
33 IK_RIGHT = SDL_SCANCODE_RIGHT;
34 IK_DELETE = SDL_SCANCODE_DELETE;
35 IK_HOME = SDL_SCANCODE_HOME;
36 IK_INSERT = SDL_SCANCODE_INSERT;
37 IK_SPACE = SDL_SCANCODE_SPACE;
38 IK_CONTROL = SDL_SCANCODE_LCTRL;
39 IK_SHIFT = SDL_SCANCODE_LSHIFT;
40 IK_TAB = SDL_SCANCODE_TAB;
41 IK_PAGEUP = SDL_SCANCODE_PAGEUP;
42 IK_PAGEDN = SDL_SCANCODE_PAGEDOWN;
43 IK_F2 = SDL_SCANCODE_F2;
44 IK_F3 = SDL_SCANCODE_F3;
45 IK_F4 = SDL_SCANCODE_F4;
46 IK_F5 = SDL_SCANCODE_F5;
47 IK_F6 = SDL_SCANCODE_F6;
48 IK_F7 = SDL_SCANCODE_F7;
49 IK_F8 = SDL_SCANCODE_F8;
50 IK_F9 = SDL_SCANCODE_F9;
51 IK_F10 = SDL_SCANCODE_F10;
52 IK_END = SDL_SCANCODE_END;
53 IK_BACKSPACE = SDL_SCANCODE_BACKSPACE;
54 IK_BACKQUOTE = SDL_SCANCODE_GRAVE;
55 IK_GRAVE = SDL_SCANCODE_GRAVE;
56 IK_PAUSE = SDL_SCANCODE_PAUSE;
57 // TODO: think of something better than this shit
58 IK_LASTKEY = SDL_NUM_SCANCODES-1;
60 AX_MINUS = 0;
61 AX_PLUS = 1;
62 HAT_LEFT = 0;
63 HAT_UP = 1;
64 HAT_RIGHT = 2;
65 HAT_DOWN = 3;
67 function e_InitInput(): Boolean;
68 procedure e_ReleaseInput();
69 procedure e_ClearInputBuffer();
70 function e_PollInput(): Boolean;
71 function e_KeyPressed(Key: Word): Boolean;
72 function e_AnyKeyPressed(): Boolean;
73 function e_GetFirstKeyPressed(): Word;
74 function e_JoystickStateToString(mode: Integer): String;
75 function e_JoyByHandle(handle: Word): Integer;
76 function e_JoyButtonToKey(id: Word; btn: Byte): Word;
77 function e_JoyAxisToKey(id: Word; ax: Byte; dir: Byte): Word;
78 function e_JoyHatToKey(id: Word; hat: Byte; dir: Byte): Word;
79 procedure e_SetKeyState(key: Word; state: Integer);
81 var
82 {e_MouseInfo: TMouseInfo;}
83 e_EnableInput: Boolean = False;
84 e_JoysticksAvailable: Byte = 0;
85 e_JoystickDeadzones: array [0..e_MaxJoys-1] of Integer = (8192, 8192, 8192, 8192);
86 e_KeyNames: array [0..e_MaxInputKeys] of String;
88 implementation
90 uses Math;
92 const
93 KBRD_END = e_MaxKbdKeys;
94 JOYK_BEG = KBRD_END;
95 JOYK_END = JOYK_BEG + e_MaxJoyBtns*e_MaxJoys;
96 JOYA_BEG = JOYK_END;
97 JOYA_END = JOYA_BEG + e_MaxJoyAxes*2*e_MaxJoys;
98 JOYH_BEG = JOYA_END;
99 JOYH_END = JOYH_BEG + e_MaxJoyHats*4*e_MaxJoys;
101 type
102 TJoystick = record
103 ID: Byte;
104 Handle: PSDL_Joystick;
105 Axes: Byte;
106 Buttons: Byte;
107 Hats: Byte;
108 ButtBuf: array [0..e_MaxJoyBtns] of Boolean;
109 AxisBuf: array [0..e_MaxJoyAxes] of Integer;
110 HatBuf: array [0..e_MaxJoyHats] of array [HAT_LEFT..HAT_DOWN] of Boolean;
111 end;
113 var
114 KeyBuffer: array [0..e_MaxKbdKeys] of Boolean;
115 Joysticks: array of TJoystick = nil;
117 function OpenJoysticks(): Byte;
118 var
119 i, k, c: Integer;
120 joy: PSDL_Joystick;
121 begin
122 Result := 0;
123 k := Min(e_MaxJoys, SDL_NumJoysticks());
124 if k = 0 then Exit;
125 c := 0;
126 for i := 0 to k do
127 begin
128 joy := SDL_JoystickOpen(i);
129 if joy <> nil then
130 begin
131 Inc(c);
132 e_WriteLog('Input: Opened SDL joystick ' + IntToStr(i) + ' as joystick ' + IntToStr(c) + ':', MSG_NOTIFY);
133 SetLength(Joysticks, c);
134 with Joysticks[c-1] do
135 begin
136 ID := i;
137 Handle := joy;
138 Axes := Min(e_MaxJoyAxes, SDL_JoystickNumAxes(joy));
139 Buttons := Min(e_MaxJoyBtns, SDL_JoystickNumButtons(joy));
140 Hats := Min(e_MaxJoyHats, SDL_JoystickNumHats(joy));
141 e_WriteLog(' ' + IntToStr(Axes) + ' axes, ' + IntToStr(Buttons) + ' buttons, ' +
142 IntToStr(Hats) + ' hats.', MSG_NOTIFY);
143 end;
144 end;
145 end;
146 Result := c;
147 end;
149 procedure ReleaseJoysticks();
150 var
151 i: Integer;
152 begin
153 if (Joysticks = nil) or (e_JoysticksAvailable = 0) then Exit;
154 for i := Low(Joysticks) to High(Joysticks) do
155 with Joysticks[i] do
156 SDL_JoystickClose(Handle);
157 SetLength(Joysticks, 0);
158 end;
160 function PollKeyboard(): Boolean;
161 var
162 Keys: PByte;
163 NKeys: Integer;
164 i: Cardinal;
165 begin
166 Result := False;
167 Keys := SDL_GetKeyboardState(@NKeys);
168 if (Keys = nil) or (NKeys < 1) then
169 Exit;
170 for i := 0 to NKeys do
171 KeyBuffer[i] := ((PByte(Cardinal(Keys) + i)^) <> 0);
172 for i := NKeys to High(KeyBuffer) do
173 KeyBuffer[i] := False;
174 end;
176 function PollJoysticks(): Boolean;
177 var
178 i, j: Word;
179 hat: Byte;
180 begin
181 Result := False;
182 if (Joysticks = nil) or (e_JoysticksAvailable = 0) then Exit;
183 SDL_JoystickUpdate();
184 for j := Low(Joysticks) to High(Joysticks) do
185 with Joysticks[j] do
186 begin
187 for i := 0 to Buttons do
188 ButtBuf[i] := SDL_JoystickGetButton(Handle, i) <> 0;
189 for i := 0 to Axes do
190 AxisBuf[i] := SDL_JoystickGetAxis(Handle, i);
191 for i := 0 to Hats do
192 begin
193 hat := SDL_JoystickGetHat(Handle, i);
194 HatBuf[i, HAT_UP] := LongBool(hat and SDL_HAT_UP);
195 HatBuf[i, HAT_DOWN] := LongBool(hat and SDL_HAT_DOWN);
196 HatBuf[i, HAT_LEFT] := LongBool(hat and SDL_HAT_LEFT);
197 HatBuf[i, HAT_RIGHT] := LongBool(hat and SDL_HAT_RIGHT);
198 end;
199 end;
200 end;
202 procedure GenerateKeyNames();
203 var
204 i, j, k: LongWord;
205 begin
206 // keyboard key names
207 for i := 0 to IK_LASTKEY do
208 e_KeyNames[i] := SDL_GetScancodeName(i);
210 // joysticks
211 for j := 0 to e_MaxJoys-1 do
212 begin
213 k := JOYK_BEG + j * e_MaxJoyBtns;
214 // buttons
215 for i := 0 to e_MaxJoyBtns-1 do
216 e_KeyNames[k + i] := Format('JOY%d B%d', [j, i]);
217 k := JOYA_BEG + j * e_MaxJoyAxes * 2;
218 // axes
219 for i := 0 to e_MaxJoyAxes-1 do
220 begin
221 e_KeyNames[k + i*2 ] := Format('JOY%d A%d+', [j, i]);
222 e_KeyNames[k + i*2 + 1] := Format('JOY%d A%d-', [j, i]);
223 end;
224 k := JOYH_BEG + j * e_MaxJoyHats * 4;
225 // hats
226 for i := 0 to e_MaxJoyHats-1 do
227 begin
228 e_KeyNames[k + i*4 ] := Format('JOY%d D%dL', [j, i]);
229 e_KeyNames[k + i*4 + 1] := Format('JOY%d D%dU', [j, i]);
230 e_KeyNames[k + i*4 + 2] := Format('JOY%d D%dR', [j, i]);
231 e_KeyNames[k + i*4 + 3] := Format('JOY%d D%dD', [j, i]);
232 end;
233 end;
234 end;
236 function e_InitInput(): Boolean;
237 begin
238 Result := False;
240 e_JoysticksAvailable := OpenJoysticks();
241 e_EnableInput := True;
242 GenerateKeyNames();
244 Result := True;
245 end;
247 procedure e_ReleaseInput();
248 begin
249 ReleaseJoysticks();
250 e_JoysticksAvailable := 0;
251 end;
253 procedure e_ClearInputBuffer();
254 var
255 i, j, d: Integer;
256 begin
257 for i := Low(KeyBuffer) to High(KeyBuffer) do
258 KeyBuffer[i] := False;
259 if (Joysticks = nil) or (e_JoysticksAvailable = 0) then
260 for i := Low(Joysticks) to High(Joysticks) do
261 begin
262 for j := Low(Joysticks[i].ButtBuf) to High(Joysticks[i].ButtBuf) do
263 Joysticks[i].ButtBuf[j] := False;
264 for j := Low(Joysticks[i].AxisBuf) to High(Joysticks[i].AxisBuf) do
265 Joysticks[i].AxisBuf[j] := 0;
266 for j := Low(Joysticks[i].HatBuf) to High(Joysticks[i].HatBuf) do
267 for d := Low(Joysticks[i].HatBuf[j]) to High(Joysticks[i].HatBuf[j]) do
268 Joysticks[i].HatBuf[j, d] := False;
269 end;
270 end;
272 function e_PollInput(): Boolean;
273 var
274 kb, js: Boolean;
275 begin
276 kb := PollKeyboard();
277 js := PollJoysticks();
279 Result := kb or js;
280 end;
282 function e_KeyPressed(Key: Word): Boolean;
283 var
284 joyi, dir: Integer;
285 begin
286 Result := False;
287 if (Key = IK_INVALID) or (Key = 0) then Exit;
289 if (Key < KBRD_END) then
290 begin // Keyboard buttons/keys
291 Result := KeyBuffer[Key];
292 end
294 else if (Key >= JOYK_BEG) and (Key < JOYK_END) then
295 begin // Joystick buttons
296 JoyI := (Key - JOYK_BEG) div e_MaxJoyBtns;
297 if JoyI >= e_JoysticksAvailable then
298 Result := False
299 else
300 begin
301 Key := (Key - JOYK_BEG) mod e_MaxJoyBtns;
302 Result := Joysticks[JoyI].ButtBuf[Key];
303 end;
304 end
306 else if (Key >= JOYA_BEG) and (Key < JOYA_END) then
307 begin // Joystick axes
308 JoyI := (Key - JOYA_BEG) div (e_MaxJoyAxes*2);
309 if JoyI >= e_JoysticksAvailable then
310 Result := False
311 else
312 begin
313 Key := (Key - JOYA_BEG) mod (e_MaxJoyAxes*2);
314 dir := Key mod 2;
315 if dir = AX_MINUS then
316 Result := Joysticks[JoyI].AxisBuf[Key div 2] < -e_JoystickDeadzones[JoyI]
317 else
318 Result := Joysticks[JoyI].AxisBuf[Key div 2] > e_JoystickDeadzones[JoyI]
319 end;
320 end
322 else if (Key >= JOYH_BEG) and (Key < JOYH_END) then
323 begin // Joystick hats
324 JoyI := (Key - JOYH_BEG) div (e_MaxJoyHats*4);
325 if JoyI >= e_JoysticksAvailable then
326 Result := False
327 else
328 begin
329 Key := (Key - JOYH_BEG) mod (e_MaxJoyHats*4);
330 dir := Key mod 4;
331 Result := Joysticks[JoyI].HatBuf[Key div 4, dir];
332 end;
333 end;
334 end;
336 procedure e_SetKeyState(key: Word; state: Integer);
337 var
338 JoyI, dir: Integer;
339 begin
340 if (Key = IK_INVALID) or (Key = 0) then Exit;
342 if (Key < KBRD_END) then
343 begin // Keyboard buttons/keys
344 keyBuffer[key] := (state <> 0);
345 end
347 else if (Key >= JOYK_BEG) and (Key < JOYK_END) then
348 begin // Joystick buttons
349 JoyI := (Key - JOYK_BEG) div e_MaxJoyBtns;
350 if JoyI >= e_JoysticksAvailable then
351 Exit
352 else
353 begin
354 Key := (Key - JOYK_BEG) mod e_MaxJoyBtns;
355 Joysticks[JoyI].ButtBuf[Key] := (state <> 0);
356 end;
357 end
359 else if (Key >= JOYA_BEG) and (Key < JOYA_END) then
360 begin // Joystick axes
361 JoyI := (Key - JOYA_BEG) div (e_MaxJoyAxes*2);
362 if JoyI >= e_JoysticksAvailable then
363 Exit
364 else
365 begin
366 Key := (Key - JOYA_BEG) mod (e_MaxJoyAxes*2);
367 Joysticks[JoyI].AxisBuf[Key div 2] := state;
368 end;
369 end
371 else if (Key >= JOYH_BEG) and (Key < JOYH_END) then
372 begin // Joystick hats
373 JoyI := (Key - JOYH_BEG) div (e_MaxJoyHats*4);
374 if JoyI >= e_JoysticksAvailable then
375 Exit
376 else
377 begin
378 Key := (Key - JOYH_BEG) mod (e_MaxJoyHats*4);
379 dir := Key mod 4;
380 Joysticks[JoyI].HatBuf[Key div 4, dir] := (state <> 0);
381 end;
382 end;
383 end;
385 function e_AnyKeyPressed(): Boolean;
386 var
387 k: Word;
388 begin
389 Result := False;
391 for k := 1 to e_MaxInputKeys do
392 if e_KeyPressed(k) then
393 begin
394 Result := True;
395 Break;
396 end;
397 end;
399 function e_GetFirstKeyPressed(): Word;
400 var
401 k: Word;
402 begin
403 Result := IK_INVALID;
405 for k := 1 to e_MaxInputKeys do
406 if e_KeyPressed(k) then
407 begin
408 Result := k;
409 Break;
410 end;
411 end;
413 ////////////////////////////////////////////////////////////////////////////////
415 function e_JoystickStateToString(mode: Integer): String;
416 begin
417 Result := '';
418 end;
420 function e_JoyByHandle(handle: Word): Integer;
421 var
422 i: Integer;
423 begin
424 Result := -1;
425 if Joysticks = nil then Exit;
426 for i := Low(Joysticks) to High(Joysticks) do
427 if Joysticks[i].ID = handle then
428 begin
429 Result := i;
430 Exit;
431 end;
432 end;
434 function e_JoyButtonToKey(id: Word; btn: Byte): Word;
435 begin
436 Result := 0;
437 if id >= Length(Joysticks) then Exit;
438 Result := JOYK_BEG + id*e_MaxJoyBtns + btn;
439 end;
441 function e_JoyAxisToKey(id: Word; ax: Byte; dir: Byte): Word;
442 begin
443 Result := 0;
444 if id >= Length(Joysticks) then Exit;
445 Result := JOYA_BEG + id*e_MaxJoyAxes*2 + ax*2 + dir;
446 end;
448 function e_JoyHatToKey(id: Word; hat: Byte; dir: Byte): Word;
449 begin
450 Result := 0;
451 if id >= Length(Joysticks) then Exit;
452 Result := JOYH_BEG + id*e_MaxJoyHats*4 + hat*4 + dir;
453 end;
455 end.