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
;
33 e_MaxJoyKeys
= e_MaxJoyBtns
+ e_MaxJoyAxes
*2 + e_MaxJoyHats
*4;
35 e_MaxInputKeys
= e_MaxKbdKeys
+ e_MaxJoys
*e_MaxJoyKeys
- 1;
36 // $$$..$$$ - 321 Keyboard buttons/keys
37 // $$$..$$$ - 4*32 Joystick buttons
38 // $$$..$$$ - 8*2 Joystick axes (- and +)
39 // $$$..$$$ - 4*4 Joystick hats (L U R D)
41 // these are apparently used in g_gui and g_game and elsewhere
43 IK_ESCAPE
= SDL_SCANCODE_ESCAPE
;
44 IK_RETURN
= SDL_SCANCODE_RETURN
;
45 IK_KPRETURN
= SDL_SCANCODE_KP_ENTER
;
46 IK_ENTER
= SDL_SCANCODE_RETURN
;
47 IK_UP
= SDL_SCANCODE_UP
;
48 IK_KPUP
= SDL_SCANCODE_KP_8
;
49 IK_DOWN
= SDL_SCANCODE_DOWN
;
50 IK_KPDOWN
= SDL_SCANCODE_KP_2
;
51 IK_LEFT
= SDL_SCANCODE_LEFT
;
52 IK_KPLEFT
= SDL_SCANCODE_KP_4
;
53 IK_RIGHT
= SDL_SCANCODE_RIGHT
;
54 IK_KPRIGHT
= SDL_SCANCODE_KP_6
;
55 IK_DELETE
= SDL_SCANCODE_DELETE
;
56 IK_HOME
= SDL_SCANCODE_HOME
;
57 IK_KPHOME
= SDL_SCANCODE_KP_7
;
58 IK_INSERT
= SDL_SCANCODE_INSERT
;
59 IK_SPACE
= SDL_SCANCODE_SPACE
;
60 IK_CONTROL
= SDL_SCANCODE_LCTRL
;
61 IK_SHIFT
= SDL_SCANCODE_LSHIFT
;
62 IK_TAB
= SDL_SCANCODE_TAB
;
63 IK_PAGEUP
= SDL_SCANCODE_PAGEUP
;
64 IK_KPPAGEUP
= SDL_SCANCODE_KP_9
;
65 IK_PAGEDN
= SDL_SCANCODE_PAGEDOWN
;
66 IK_KPPAGEDN
= SDL_SCANCODE_KP_3
;
67 IK_F2
= SDL_SCANCODE_F2
;
68 IK_F3
= SDL_SCANCODE_F3
;
69 IK_F4
= SDL_SCANCODE_F4
;
70 IK_F5
= SDL_SCANCODE_F5
;
71 IK_F6
= SDL_SCANCODE_F6
;
72 IK_F7
= SDL_SCANCODE_F7
;
73 IK_F8
= SDL_SCANCODE_F8
;
74 IK_F9
= SDL_SCANCODE_F9
;
75 IK_F10
= SDL_SCANCODE_F10
;
76 IK_END
= SDL_SCANCODE_END
;
77 IK_KPEND
= SDL_SCANCODE_KP_1
;
78 IK_BACKSPACE
= SDL_SCANCODE_BACKSPACE
;
79 IK_BACKQUOTE
= SDL_SCANCODE_GRAVE
;
80 IK_GRAVE
= SDL_SCANCODE_GRAVE
;
81 IK_PAUSE
= SDL_SCANCODE_PAUSE
;
82 IK_Y
= SDL_SCANCODE_Y
;
83 IK_N
= SDL_SCANCODE_N
;
84 // TODO: think of something better than this shit
85 IK_LASTKEY
= SDL_NUM_SCANCODES
-1;
94 function e_InitInput(): Boolean;
95 procedure e_ReleaseInput();
96 procedure e_ClearInputBuffer();
97 function e_PollInput(): Boolean;
98 function e_KeyPressed(Key
: Word): Boolean;
99 function e_AnyKeyPressed(): Boolean;
100 function e_GetFirstKeyPressed(): Word;
101 function e_JoystickStateToString(mode
: Integer): String;
102 function e_JoyByHandle(handle
: Word): Integer;
103 function e_JoyButtonToKey(id
: Word; btn
: Byte): Word;
104 function e_JoyAxisToKey(id
: Word; ax
: Byte; dir
: Byte): Word;
105 function e_JoyHatToKey(id
: Word; hat
: Byte; dir
: Byte): Word;
106 procedure e_SetKeyState(key
: Word; state
: Integer);
108 procedure e_UnpressAllKeys ();
109 procedure e_KeyUpDown (key
: Word; down
: Boolean);
112 {e_MouseInfo: TMouseInfo;}
113 e_EnableInput
: Boolean = False;
114 e_JoysticksAvailable
: Byte = 0;
115 e_JoystickDeadzones
: array [0..e_MaxJoys
-1] of Integer = (8192, 8192, 8192, 8192);
116 e_KeyNames
: array [0..e_MaxInputKeys
] of String;
123 KBRD_END
= e_MaxKbdKeys
;
125 JOYK_END
= JOYK_BEG
+ e_MaxJoyBtns
*e_MaxJoys
;
127 JOYA_END
= JOYA_BEG
+ e_MaxJoyAxes
*2*e_MaxJoys
;
129 JOYH_END
= JOYH_BEG
+ e_MaxJoyHats
*4*e_MaxJoys
;
134 Handle
: PSDL_Joystick
;
138 ButtBuf
: array [0..e_MaxJoyBtns
] of Boolean;
139 AxisBuf
: array [0..e_MaxJoyAxes
] of Integer;
140 AxisZero
: array [0..e_MaxJoyAxes
] of Integer;
141 HatBuf
: array [0..e_MaxJoyHats
] of array [HAT_LEFT
..HAT_DOWN
] of Boolean;
145 KeyBuffer
: array [0..e_MaxKbdKeys
] of Boolean;
146 Joysticks
: array of TJoystick
= nil;
148 function OpenJoysticks(): Byte;
154 k
:= Min(e_MaxJoys
, SDL_NumJoysticks());
159 joy
:= SDL_JoystickOpen(i
);
163 e_WriteLog('Input: Opened SDL joystick ' + IntToStr(i
) + ' (' + SDL_JoystickName(joy
) +
164 ') as joystick ' + IntToStr(c
) + ':', MSG_NOTIFY
);
165 SetLength(Joysticks
, c
);
166 with Joysticks
[c
-1] do
170 Axes
:= Min(e_MaxJoyAxes
, SDL_JoystickNumAxes(joy
));
171 Buttons
:= Min(e_MaxJoyBtns
, SDL_JoystickNumButtons(joy
));
172 Hats
:= Min(e_MaxJoyHats
, SDL_JoystickNumHats(joy
));
173 // TODO: find proper solution for this xbox trigger shit
174 for j
:= 0 to Axes
do AxisZero
[j
] := SDL_JoystickGetAxis(joy
, j
);
175 e_WriteLog(' ' + IntToStr(Axes
) + ' axes, ' + IntToStr(Buttons
) + ' buttons, ' +
176 IntToStr(Hats
) + ' hats.', MSG_NOTIFY
);
183 procedure ReleaseJoysticks();
187 if (Joysticks
= nil) or (e_JoysticksAvailable
= 0) then Exit
;
188 for i
:= Low(Joysticks
) to High(Joysticks
) do
190 SDL_JoystickClose(Handle
);
191 SetLength(Joysticks
, 0);
195 procedure e_UnpressAllKeys ();
199 for i
:= 0 to High(KeyBuffer
) do KeyBuffer
[i
] := False;
203 procedure e_KeyUpDown (key
: Word; down
: Boolean);
205 if (key
> 0) and (key
< Length(KeyBuffer
)) then KeyBuffer
[key
] := down
;
209 function PollKeyboard(): Boolean;
219 Keys := SDL_GetKeyboardState(@NKeys);
220 if (Keys = nil) or (NKeys < 1) then Exit;
221 for i := 0 to NKeys do
223 if ((PByte(NativeUInt(Keys) + i)^) <> 0) then KeyBuffer[i] := false;
225 for i := NKeys to High(KeyBuffer) do KeyBuffer[i] := False;
229 function PollJoysticks(): Boolean;
235 if (Joysticks
= nil) or (e_JoysticksAvailable
= 0) then Exit
;
236 SDL_JoystickUpdate();
237 for j
:= Low(Joysticks
) to High(Joysticks
) do
240 for i
:= 0 to Buttons
do
241 ButtBuf
[i
] := SDL_JoystickGetButton(Handle
, i
) <> 0;
242 for i
:= 0 to Axes
do
243 AxisBuf
[i
] := SDL_JoystickGetAxis(Handle
, i
);
244 for i
:= 0 to Hats
do
246 hat
:= SDL_JoystickGetHat(Handle
, i
);
247 HatBuf
[i
, HAT_UP
] := LongBool(hat
and SDL_HAT_UP
);
248 HatBuf
[i
, HAT_DOWN
] := LongBool(hat
and SDL_HAT_DOWN
);
249 HatBuf
[i
, HAT_LEFT
] := LongBool(hat
and SDL_HAT_LEFT
);
250 HatBuf
[i
, HAT_RIGHT
] := LongBool(hat
and SDL_HAT_RIGHT
);
255 procedure GenerateKeyNames();
259 // keyboard key names
260 for i
:= 0 to IK_LASTKEY
do
261 e_KeyNames
[i
] := SDL_GetScancodeName(i
);
264 for j
:= 0 to e_MaxJoys
-1 do
266 k
:= JOYK_BEG
+ j
* e_MaxJoyBtns
;
268 for i
:= 0 to e_MaxJoyBtns
-1 do
269 e_KeyNames
[k
+ i
] := Format('JOY%d B%d', [j
, i
]);
270 k
:= JOYA_BEG
+ j
* e_MaxJoyAxes
* 2;
272 for i
:= 0 to e_MaxJoyAxes
-1 do
274 e_KeyNames
[k
+ i
*2 ] := Format('JOY%d A%d+', [j
, i
]);
275 e_KeyNames
[k
+ i
*2 + 1] := Format('JOY%d A%d-', [j
, i
]);
277 k
:= JOYH_BEG
+ j
* e_MaxJoyHats
* 4;
279 for i
:= 0 to e_MaxJoyHats
-1 do
281 e_KeyNames
[k
+ i
*4 ] := Format('JOY%d D%dL', [j
, i
]);
282 e_KeyNames
[k
+ i
*4 + 1] := Format('JOY%d D%dU', [j
, i
]);
283 e_KeyNames
[k
+ i
*4 + 2] := Format('JOY%d D%dR', [j
, i
]);
284 e_KeyNames
[k
+ i
*4 + 3] := Format('JOY%d D%dD', [j
, i
]);
289 function e_InitInput(): Boolean;
293 e_JoysticksAvailable
:= OpenJoysticks();
294 e_EnableInput
:= True;
300 procedure e_ReleaseInput();
303 e_JoysticksAvailable
:= 0;
306 procedure e_ClearInputBuffer();
310 for i
:= Low(KeyBuffer
) to High(KeyBuffer
) do
311 KeyBuffer
[i
] := False;
312 if (Joysticks
= nil) or (e_JoysticksAvailable
= 0) then
313 for i
:= Low(Joysticks
) to High(Joysticks
) do
315 for j
:= Low(Joysticks
[i
].ButtBuf
) to High(Joysticks
[i
].ButtBuf
) do
316 Joysticks
[i
].ButtBuf
[j
] := False;
317 for j
:= Low(Joysticks
[i
].AxisBuf
) to High(Joysticks
[i
].AxisBuf
) do
318 Joysticks
[i
].AxisBuf
[j
] := 0;
319 for j
:= Low(Joysticks
[i
].HatBuf
) to High(Joysticks
[i
].HatBuf
) do
320 for d
:= Low(Joysticks
[i
].HatBuf
[j
]) to High(Joysticks
[i
].HatBuf
[j
]) do
321 Joysticks
[i
].HatBuf
[j
, d
] := False;
325 function e_PollInput(): Boolean;
329 kb
:= PollKeyboard();
330 js
:= PollJoysticks();
335 function e_KeyPressed(Key
: Word): Boolean;
340 if (Key
= IK_INVALID
) or (Key
= 0) then Exit
;
342 if (Key
< KBRD_END
) then
343 begin // Keyboard buttons/keys
344 Result
:= KeyBuffer
[Key
];
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
354 Key
:= (Key
- JOYK_BEG
) mod e_MaxJoyBtns
;
355 Result
:= Joysticks
[JoyI
].ButtBuf
[Key
];
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
366 Key
:= (Key
- JOYA_BEG
) mod (e_MaxJoyAxes
*2);
368 if dir
= AX_MINUS
then
369 Result
:= Joysticks
[JoyI
].AxisBuf
[Key
div 2] <
370 Joysticks
[JoyI
].AxisZero
[Key
div 2] - e_JoystickDeadzones
[JoyI
]
372 Result
:= Joysticks
[JoyI
].AxisBuf
[Key
div 2] >
373 Joysticks
[JoyI
].AxisZero
[Key
div 2] + e_JoystickDeadzones
[JoyI
]
377 else if (Key
>= JOYH_BEG
) and (Key
< JOYH_END
) then
378 begin // Joystick hats
379 JoyI
:= (Key
- JOYH_BEG
) div (e_MaxJoyHats
*4);
380 if JoyI
>= e_JoysticksAvailable
then
384 Key
:= (Key
- JOYH_BEG
) mod (e_MaxJoyHats
*4);
386 Result
:= Joysticks
[JoyI
].HatBuf
[Key
div 4, dir
];
391 procedure e_SetKeyState(key
: Word; state
: Integer);
395 if (Key
= IK_INVALID
) or (Key
= 0) then Exit
;
397 if (Key
< KBRD_END
) then
398 begin // Keyboard buttons/keys
399 keyBuffer
[key
] := (state
<> 0);
402 else if (Key
>= JOYK_BEG
) and (Key
< JOYK_END
) then
403 begin // Joystick buttons
404 JoyI
:= (Key
- JOYK_BEG
) div e_MaxJoyBtns
;
405 if JoyI
>= e_JoysticksAvailable
then
409 Key
:= (Key
- JOYK_BEG
) mod e_MaxJoyBtns
;
410 Joysticks
[JoyI
].ButtBuf
[Key
] := (state
<> 0);
414 else if (Key
>= JOYA_BEG
) and (Key
< JOYA_END
) then
415 begin // Joystick axes
416 JoyI
:= (Key
- JOYA_BEG
) div (e_MaxJoyAxes
*2);
417 if JoyI
>= e_JoysticksAvailable
then
421 Key
:= (Key
- JOYA_BEG
) mod (e_MaxJoyAxes
*2);
422 Joysticks
[JoyI
].AxisBuf
[Key
div 2] := state
;
426 else if (Key
>= JOYH_BEG
) and (Key
< JOYH_END
) then
427 begin // Joystick hats
428 JoyI
:= (Key
- JOYH_BEG
) div (e_MaxJoyHats
*4);
429 if JoyI
>= e_JoysticksAvailable
then
433 Key
:= (Key
- JOYH_BEG
) mod (e_MaxJoyHats
*4);
435 Joysticks
[JoyI
].HatBuf
[Key
div 4, dir
] := (state
<> 0);
440 function e_AnyKeyPressed(): Boolean;
446 for k
:= 1 to e_MaxInputKeys
do
447 if e_KeyPressed(k
) then
454 function e_GetFirstKeyPressed(): Word;
458 Result
:= IK_INVALID
;
460 for k
:= 1 to e_MaxInputKeys
do
461 if e_KeyPressed(k
) then
468 ////////////////////////////////////////////////////////////////////////////////
470 function e_JoystickStateToString(mode
: Integer): String;
475 function e_JoyByHandle(handle
: Word): Integer;
480 if Joysticks
= nil then Exit
;
481 for i
:= Low(Joysticks
) to High(Joysticks
) do
482 if Joysticks
[i
].ID
= handle
then
489 function e_JoyButtonToKey(id
: Word; btn
: Byte): Word;
492 if id
>= Length(Joysticks
) then Exit
;
493 Result
:= JOYK_BEG
+ id
*e_MaxJoyBtns
+ btn
;
496 function e_JoyAxisToKey(id
: Word; ax
: Byte; dir
: Byte): Word;
499 if id
>= Length(Joysticks
) then Exit
;
500 Result
:= JOYA_BEG
+ id
*e_MaxJoyAxes
*2 + ax
*2 + dir
;
503 function e_JoyHatToKey(id
: Word; hat
: Byte; dir
: Byte): Word;
506 if id
>= Length(Joysticks
) then Exit
;
507 Result
:= JOYH_BEG
+ id
*e_MaxJoyHats
*4 + hat
*4 + dir
;