1 (* Copyright (C) Doom 2D: Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE ../shared/a_modes.inc}
27 e_MaxKbdKeys
= SDL_NUM_SCANCODES
;
34 e_MaxJoyKeys
= e_MaxJoyBtns
+ e_MaxJoyAxes
*2 + e_MaxJoyHats
*4;
36 e_MaxInputKeys
= e_MaxKbdKeys
+ e_MaxJoys
*e_MaxJoyKeys
+ e_MaxVirtKeys
- 1;
37 // $$$..$$$ - 321 Keyboard buttons/keys
38 // $$$..$$$ - 4*32 Joystick buttons
39 // $$$..$$$ - 8*2 Joystick axes (- and +)
40 // $$$..$$$ - 4*4 Joystick hats (L U R D)
41 // $$$..$$$ - 48 Virtual buttons/keys
43 // these are apparently used in g_gui and g_game and elsewhere
45 IK_ESCAPE
= SDL_SCANCODE_ESCAPE
;
46 IK_RETURN
= SDL_SCANCODE_RETURN
;
47 IK_KPRETURN
= SDL_SCANCODE_KP_ENTER
;
48 IK_ENTER
= SDL_SCANCODE_RETURN
;
49 IK_UP
= SDL_SCANCODE_UP
;
50 IK_KPUP
= SDL_SCANCODE_KP_8
;
51 IK_DOWN
= SDL_SCANCODE_DOWN
;
52 IK_KPDOWN
= SDL_SCANCODE_KP_2
;
53 IK_LEFT
= SDL_SCANCODE_LEFT
;
54 IK_KPLEFT
= SDL_SCANCODE_KP_4
;
55 IK_RIGHT
= SDL_SCANCODE_RIGHT
;
56 IK_KPRIGHT
= SDL_SCANCODE_KP_6
;
57 IK_DELETE
= SDL_SCANCODE_DELETE
;
58 IK_HOME
= SDL_SCANCODE_HOME
;
59 IK_KPHOME
= SDL_SCANCODE_KP_7
;
60 IK_INSERT
= SDL_SCANCODE_INSERT
;
61 IK_SPACE
= SDL_SCANCODE_SPACE
;
62 IK_CONTROL
= SDL_SCANCODE_LCTRL
;
63 IK_SHIFT
= SDL_SCANCODE_LSHIFT
;
64 IK_ALT
= SDL_SCANCODE_LALT
;
65 IK_TAB
= SDL_SCANCODE_TAB
;
66 IK_PAGEUP
= SDL_SCANCODE_PAGEUP
;
67 IK_KPPAGEUP
= SDL_SCANCODE_KP_9
;
68 IK_PAGEDN
= SDL_SCANCODE_PAGEDOWN
;
69 IK_KPPAGEDN
= SDL_SCANCODE_KP_3
;
70 IK_0
= SDL_SCANCODE_0
;
71 IK_1
= SDL_SCANCODE_1
;
72 IK_2
= SDL_SCANCODE_2
;
73 IK_3
= SDL_SCANCODE_3
;
74 IK_4
= SDL_SCANCODE_4
;
75 IK_5
= SDL_SCANCODE_5
;
76 IK_6
= SDL_SCANCODE_6
;
77 IK_7
= SDL_SCANCODE_7
;
78 IK_8
= SDL_SCANCODE_8
;
79 IK_9
= SDL_SCANCODE_9
;
80 IK_F1
= SDL_SCANCODE_F1
;
81 IK_F2
= SDL_SCANCODE_F2
;
82 IK_F3
= SDL_SCANCODE_F3
;
83 IK_F4
= SDL_SCANCODE_F4
;
84 IK_F5
= SDL_SCANCODE_F5
;
85 IK_F6
= SDL_SCANCODE_F6
;
86 IK_F7
= SDL_SCANCODE_F7
;
87 IK_F8
= SDL_SCANCODE_F8
;
88 IK_F9
= SDL_SCANCODE_F9
;
89 IK_F10
= SDL_SCANCODE_F10
;
90 IK_F11
= SDL_SCANCODE_F11
;
91 IK_F12
= SDL_SCANCODE_F12
;
92 IK_END
= SDL_SCANCODE_END
;
93 IK_KPEND
= SDL_SCANCODE_KP_1
;
94 IK_BACKSPACE
= SDL_SCANCODE_BACKSPACE
;
95 IK_BACKQUOTE
= SDL_SCANCODE_GRAVE
;
96 IK_GRAVE
= SDL_SCANCODE_GRAVE
;
97 IK_PAUSE
= SDL_SCANCODE_PAUSE
;
98 IK_Y
= SDL_SCANCODE_Y
;
99 IK_N
= SDL_SCANCODE_N
;
100 IK_W
= SDL_SCANCODE_W
;
101 IK_A
= SDL_SCANCODE_A
;
102 IK_S
= SDL_SCANCODE_S
;
103 IK_D
= SDL_SCANCODE_D
;
104 IK_Q
= SDL_SCANCODE_Q
;
105 IK_E
= SDL_SCANCODE_E
;
106 IK_H
= SDL_SCANCODE_H
;
107 IK_J
= SDL_SCANCODE_J
;
108 IK_T
= SDL_SCANCODE_T
;
109 IK_MINUS
= SDL_SCANCODE_MINUS
;
110 // TODO: think of something better than this shit
111 IK_LASTKEY
= SDL_NUM_SCANCODES
-1;
113 VK_FIRSTKEY
= e_MaxKbdKeys
+ e_MaxJoys
*e_MaxJoyKeys
;
114 VK_LEFT
= VK_FIRSTKEY
+ 0;
115 VK_RIGHT
= VK_FIRSTKEY
+ 1;
116 VK_UP
= VK_FIRSTKEY
+ 2;
117 VK_DOWN
= VK_FIRSTKEY
+ 3;
118 VK_FIRE
= VK_FIRSTKEY
+ 4;
119 VK_OPEN
= VK_FIRSTKEY
+ 5;
120 VK_JUMP
= VK_FIRSTKEY
+ 6;
121 VK_CHAT
= VK_FIRSTKEY
+ 7;
122 VK_ESCAPE
= VK_FIRSTKEY
+ 8;
123 VK_0
= VK_FIRSTKEY
+ 9;
124 VK_1
= VK_FIRSTKEY
+ 10;
125 VK_2
= VK_FIRSTKEY
+ 11;
126 VK_3
= VK_FIRSTKEY
+ 12;
127 VK_4
= VK_FIRSTKEY
+ 13;
128 VK_5
= VK_FIRSTKEY
+ 14;
129 VK_6
= VK_FIRSTKEY
+ 15;
130 VK_7
= VK_FIRSTKEY
+ 16;
131 VK_8
= VK_FIRSTKEY
+ 17;
132 VK_9
= VK_FIRSTKEY
+ 18;
133 VK_A
= VK_FIRSTKEY
+ 19;
134 VK_B
= VK_FIRSTKEY
+ 20;
135 VK_C
= VK_FIRSTKEY
+ 21;
136 VK_D
= VK_FIRSTKEY
+ 22;
137 VK_E
= VK_FIRSTKEY
+ 23;
138 VK_F
= VK_FIRSTKEY
+ 24;
139 VK_CONSOLE
= VK_FIRSTKEY
+ 25;
140 VK_STATUS
= VK_FIRSTKEY
+ 26;
141 VK_TEAM
= VK_FIRSTKEY
+ 27;
142 VK_PREV
= VK_FIRSTKEY
+ 28;
143 VK_NEXT
= VK_FIRSTKEY
+ 29;
144 VK_STRAFE
= VK_FIRSTKEY
+ 30;
145 VK_LSTRAFE
= VK_FIRSTKEY
+ 31;
146 VK_RSTRAFE
= VK_FIRSTKEY
+ 32;
147 VK_PRINTSCR
= VK_FIRSTKEY
+ 33;
148 VK_LASTKEY
= e_MaxKbdKeys
+ e_MaxJoys
*e_MaxJoyKeys
+ e_MaxVirtKeys
- 1;
157 function e_InitInput(): Boolean;
158 procedure e_ReleaseInput();
159 procedure e_ClearInputBuffer();
160 //function e_PollInput(): Boolean;
161 procedure e_PollJoysticks(); // call this from message loop to update joysticks
162 function e_KeyPressed(Key
: Word): Boolean;
163 function e_AnyKeyPressed(): Boolean;
164 function e_GetFirstKeyPressed(): Word;
165 function e_JoystickStateToString(mode
: Integer): String;
166 function e_JoyByHandle(handle
: Word): Integer;
167 function e_JoyButtonToKey(id
: Word; btn
: Byte): Word;
168 function e_JoyAxisToKey(id
: Word; ax
: Byte; dir
: Byte): Word;
169 function e_JoyHatToKey(id
: Word; hat
: Byte; dir
: Byte): Word;
170 procedure e_SetKeyState(key
: Word; state
: Integer);
172 procedure e_UnpressAllKeys ();
173 procedure e_KeyUpDown (key
: Word; down
: Boolean);
176 {e_MouseInfo: TMouseInfo;}
177 e_EnableInput
: Boolean = False;
178 e_JoysticksAvailable
: Byte = 0;
179 e_JoystickDeadzones
: array [0..e_MaxJoys
-1] of Integer = (8192, 8192, 8192, 8192);
180 e_KeyNames
: array [0..e_MaxInputKeys
] of String;
187 KBRD_END
= e_MaxKbdKeys
;
189 JOYK_END
= JOYK_BEG
+ e_MaxJoyBtns
*e_MaxJoys
;
191 JOYA_END
= JOYA_BEG
+ e_MaxJoyAxes
*2*e_MaxJoys
;
193 JOYH_END
= JOYH_BEG
+ e_MaxJoyHats
*4*e_MaxJoys
;
195 VIRT_END
= VIRT_BEG
+ e_MaxVirtKeys
;
200 Handle
: PSDL_Joystick
;
204 ButtBuf
: array [0..e_MaxJoyBtns
] of Boolean;
205 AxisBuf
: array [0..e_MaxJoyAxes
] of Integer;
206 AxisZero
: array [0..e_MaxJoyAxes
] of Integer;
207 HatBuf
: array [0..e_MaxJoyHats
] of array [HAT_LEFT
..HAT_DOWN
] of Boolean;
211 KeyBuffer
: array [0..e_MaxKbdKeys
] of Boolean;
212 VirtBuffer
: array [0..e_MaxVirtKeys
] of Boolean;
213 Joysticks
: array of TJoystick
= nil;
215 function OpenJoysticks(): Byte;
221 k
:= Min(e_MaxJoys
, SDL_NumJoysticks());
226 joy
:= SDL_JoystickOpen(i
);
230 e_WriteLog('Input: Opened SDL joystick ' + IntToStr(i
) + ' (' + SDL_JoystickName(joy
) +
231 ') as joystick ' + IntToStr(c
) + ':', TMsgType
.Notify
);
232 SetLength(Joysticks
, c
);
233 with Joysticks
[c
-1] do
237 Axes
:= Min(e_MaxJoyAxes
, SDL_JoystickNumAxes(joy
));
238 Buttons
:= Min(e_MaxJoyBtns
, SDL_JoystickNumButtons(joy
));
239 Hats
:= Min(e_MaxJoyHats
, SDL_JoystickNumHats(joy
));
240 // TODO: find proper solution for this xbox trigger shit
241 for j
:= 0 to Axes
do AxisZero
[j
] := SDL_JoystickGetAxis(joy
, j
);
242 e_WriteLog(' ' + IntToStr(Axes
) + ' axes, ' + IntToStr(Buttons
) + ' buttons, ' +
243 IntToStr(Hats
) + ' hats.', TMsgType
.Notify
);
250 procedure ReleaseJoysticks();
254 if (Joysticks
= nil) or (e_JoysticksAvailable
= 0) then Exit
;
255 for i
:= Low(Joysticks
) to High(Joysticks
) do
257 SDL_JoystickClose(Handle
);
258 SetLength(Joysticks
, 0);
262 procedure e_UnpressAllKeys ();
266 for i
:= 0 to High(KeyBuffer
) do KeyBuffer
[i
] := False;
267 for i
:= 0 to High(VirtBuffer
) do VirtBuffer
[i
] := False;
271 procedure e_KeyUpDown (key
: Word; down
: Boolean);
273 if (key
> 0) and (key
< Length(KeyBuffer
)) then KeyBuffer
[key
] := down
274 else if (key
>= VIRT_BEG
) and (key
< VIRT_END
) then VirtBuffer
[key
- VIRT_BEG
] := down
278 function PollKeyboard(): Boolean;
288 Keys := SDL_GetKeyboardState(@NKeys);
289 if (Keys = nil) or (NKeys < 1) then Exit;
290 for i := 0 to NKeys do
292 if ((PByte(NativeUInt(Keys) + i)^) <> 0) then KeyBuffer[i] := false;
294 for i := NKeys to High(KeyBuffer) do KeyBuffer[i] := False;
298 procedure e_PollJoysticks();
304 if (Joysticks
= nil) or (e_JoysticksAvailable
= 0) then Exit
;
305 SDL_JoystickUpdate();
306 for j
:= Low(Joysticks
) to High(Joysticks
) do
310 for i
:= 0 to Buttons
do ButtBuf
[i
] := SDL_JoystickGetButton(Handle
, i
) <> 0;
311 for i
:= 0 to Axes
do AxisBuf
[i
] := SDL_JoystickGetAxis(Handle
, i
);
312 for i
:= 0 to Hats
do
314 hat
:= SDL_JoystickGetHat(Handle
, i
);
315 HatBuf
[i
, HAT_UP
] := LongBool(hat
and SDL_HAT_UP
);
316 HatBuf
[i
, HAT_DOWN
] := LongBool(hat
and SDL_HAT_DOWN
);
317 HatBuf
[i
, HAT_LEFT
] := LongBool(hat
and SDL_HAT_LEFT
);
318 HatBuf
[i
, HAT_RIGHT
] := LongBool(hat
and SDL_HAT_RIGHT
);
324 procedure GenerateKeyNames();
328 // keyboard key names
329 for i
:= 0 to IK_LASTKEY
do
330 e_KeyNames
[i
] := SDL_GetScancodeName(i
);
333 for j
:= 0 to e_MaxJoys
-1 do
335 k
:= JOYK_BEG
+ j
* e_MaxJoyBtns
;
337 for i
:= 0 to e_MaxJoyBtns
-1 do
338 e_KeyNames
[k
+ i
] := Format('JOY%d B%d', [j
, i
]);
339 k
:= JOYA_BEG
+ j
* e_MaxJoyAxes
* 2;
341 for i
:= 0 to e_MaxJoyAxes
-1 do
343 e_KeyNames
[k
+ i
*2 ] := Format('JOY%d A%d+', [j
, i
]);
344 e_KeyNames
[k
+ i
*2 + 1] := Format('JOY%d A%d-', [j
, i
]);
346 k
:= JOYH_BEG
+ j
* e_MaxJoyHats
* 4;
348 for i
:= 0 to e_MaxJoyHats
-1 do
350 e_KeyNames
[k
+ i
*4 ] := Format('JOY%d D%dL', [j
, i
]);
351 e_KeyNames
[k
+ i
*4 + 1] := Format('JOY%d D%dU', [j
, i
]);
352 e_KeyNames
[k
+ i
*4 + 2] := Format('JOY%d D%dR', [j
, i
]);
353 e_KeyNames
[k
+ i
*4 + 3] := Format('JOY%d D%dD', [j
, i
]);
358 for i
:= 0 to e_MaxVirtKeys
-1 do
359 e_KeyNames
[VIRT_BEG
+ i
] := 'VIRTUAL ' + IntToStr(i
);
362 function e_InitInput(): Boolean;
366 e_JoysticksAvailable
:= OpenJoysticks();
367 e_EnableInput
:= True;
373 procedure e_ReleaseInput();
376 e_JoysticksAvailable
:= 0;
379 procedure e_ClearInputBuffer();
383 for i
:= Low(KeyBuffer
) to High(KeyBuffer
) do
384 KeyBuffer
[i
] := False;
385 if (Joysticks
= nil) or (e_JoysticksAvailable
= 0) then
386 for i
:= Low(Joysticks
) to High(Joysticks
) do
388 for j
:= Low(Joysticks
[i
].ButtBuf
) to High(Joysticks
[i
].ButtBuf
) do
389 Joysticks
[i
].ButtBuf
[j
] := False;
390 for j
:= Low(Joysticks
[i
].AxisBuf
) to High(Joysticks
[i
].AxisBuf
) do
391 Joysticks
[i
].AxisBuf
[j
] := 0;
392 for j
:= Low(Joysticks
[i
].HatBuf
) to High(Joysticks
[i
].HatBuf
) do
393 for d
:= Low(Joysticks
[i
].HatBuf
[j
]) to High(Joysticks
[i
].HatBuf
[j
]) do
394 Joysticks
[i
].HatBuf
[j
, d
] := False;
396 for i
:= Low(VirtBuffer
) to High(VirtBuffer
) do
397 VirtBuffer
[i
] := False;
401 function e_PollInput(): Boolean;
405 kb := PollKeyboard();
406 js := e_PollJoysticks();
412 function e_KeyPressed(Key
: Word): Boolean;
417 if (Key
= IK_INVALID
) or (Key
= 0) then Exit
;
419 if (Key
< KBRD_END
) then
420 begin // Keyboard buttons/keys
421 Result
:= KeyBuffer
[Key
];
424 else if (Key
>= JOYK_BEG
) and (Key
< JOYK_END
) then
425 begin // Joystick buttons
426 JoyI
:= (Key
- JOYK_BEG
) div e_MaxJoyBtns
;
427 if JoyI
>= e_JoysticksAvailable
then
431 Key
:= (Key
- JOYK_BEG
) mod e_MaxJoyBtns
;
432 Result
:= Joysticks
[JoyI
].ButtBuf
[Key
];
436 else if (Key
>= JOYA_BEG
) and (Key
< JOYA_END
) then
437 begin // Joystick axes
438 JoyI
:= (Key
- JOYA_BEG
) div (e_MaxJoyAxes
*2);
439 if JoyI
>= e_JoysticksAvailable
then
443 Key
:= (Key
- JOYA_BEG
) mod (e_MaxJoyAxes
*2);
445 if dir
= AX_MINUS
then
446 Result
:= Joysticks
[JoyI
].AxisBuf
[Key
div 2] <
447 Joysticks
[JoyI
].AxisZero
[Key
div 2] - e_JoystickDeadzones
[JoyI
]
449 Result
:= Joysticks
[JoyI
].AxisBuf
[Key
div 2] >
450 Joysticks
[JoyI
].AxisZero
[Key
div 2] + e_JoystickDeadzones
[JoyI
]
454 else if (Key
>= JOYH_BEG
) and (Key
< JOYH_END
) then
455 begin // Joystick hats
456 JoyI
:= (Key
- JOYH_BEG
) div (e_MaxJoyHats
*4);
457 if JoyI
>= e_JoysticksAvailable
then
461 Key
:= (Key
- JOYH_BEG
) mod (e_MaxJoyHats
*4);
463 Result
:= Joysticks
[JoyI
].HatBuf
[Key
div 4, dir
];
467 else if (Key
>= VIRT_BEG
) and (Key
< VIRT_END
) then
468 Result
:= VirtBuffer
[Key
- VIRT_BEG
]
471 procedure e_SetKeyState(key
: Word; state
: Integer);
475 if (Key
= IK_INVALID
) or (Key
= 0) then Exit
;
477 if (Key
< KBRD_END
) then
478 begin // Keyboard buttons/keys
479 keyBuffer
[key
] := (state
<> 0);
482 else if (Key
>= JOYK_BEG
) and (Key
< JOYK_END
) then
483 begin // Joystick buttons
484 JoyI
:= (Key
- JOYK_BEG
) div e_MaxJoyBtns
;
485 if JoyI
>= e_JoysticksAvailable
then
489 Key
:= (Key
- JOYK_BEG
) mod e_MaxJoyBtns
;
490 Joysticks
[JoyI
].ButtBuf
[Key
] := (state
<> 0);
494 else if (Key
>= JOYA_BEG
) and (Key
< JOYA_END
) then
495 begin // Joystick axes
496 JoyI
:= (Key
- JOYA_BEG
) div (e_MaxJoyAxes
*2);
497 if JoyI
>= e_JoysticksAvailable
then
501 Key
:= (Key
- JOYA_BEG
) mod (e_MaxJoyAxes
*2);
502 Joysticks
[JoyI
].AxisBuf
[Key
div 2] := state
;
506 else if (Key
>= JOYH_BEG
) and (Key
< JOYH_END
) then
507 begin // Joystick hats
508 JoyI
:= (Key
- JOYH_BEG
) div (e_MaxJoyHats
*4);
509 if JoyI
>= e_JoysticksAvailable
then
513 Key
:= (Key
- JOYH_BEG
) mod (e_MaxJoyHats
*4);
515 Joysticks
[JoyI
].HatBuf
[Key
div 4, dir
] := (state
<> 0);
519 else if (Key
>= VIRT_BEG
) and (Key
< VIRT_END
) then
520 VirtBuffer
[Key
- VIRT_BEG
] := (state
<> 0)
523 function e_AnyKeyPressed(): Boolean;
529 for k
:= 1 to e_MaxInputKeys
do
530 if e_KeyPressed(k
) then
537 function e_GetFirstKeyPressed(): Word;
541 Result
:= IK_INVALID
;
543 for k
:= 1 to e_MaxInputKeys
do
544 if e_KeyPressed(k
) then
551 ////////////////////////////////////////////////////////////////////////////////
553 function e_JoystickStateToString(mode
: Integer): String;
558 function e_JoyByHandle(handle
: Word): Integer;
563 if Joysticks
= nil then Exit
;
564 for i
:= Low(Joysticks
) to High(Joysticks
) do
565 if Joysticks
[i
].ID
= handle
then
572 function e_JoyButtonToKey(id
: Word; btn
: Byte): Word;
575 if id
>= e_MaxJoys
then Exit
;
576 Result
:= JOYK_BEG
+ id
*e_MaxJoyBtns
+ btn
;
579 function e_JoyAxisToKey(id
: Word; ax
: Byte; dir
: Byte): Word;
582 if id
>= e_MaxJoys
then Exit
;
583 Result
:= JOYA_BEG
+ id
*e_MaxJoyAxes
*2 + ax
*2 + dir
;
586 function e_JoyHatToKey(id
: Word; hat
: Byte; dir
: Byte): Word;
589 if id
>= e_MaxJoys
then Exit
;
590 Result
:= JOYH_BEG
+ id
*e_MaxJoyHats
*4 + hat
*4 + dir
;