DEADSOFTWARE

Android: added key for calling android keyboard
[d2df-sdl.git] / src / game / g_touch.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
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.
7 *
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.
12 *
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/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 unit g_touch;
19 interface
21 uses
22 SDL2;
24 var
25 g_touch_enabled: Boolean;
26 g_touch_size: Single;
27 g_touch_offset: Single;
28 g_touch_fire: Boolean;
29 g_touch_alt: Boolean;
31 procedure g_Touch_Init;
32 procedure g_Touch_ShowKeyboard(yes: Boolean);
33 procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent);
34 procedure g_Touch_Draw;
36 implementation
38 uses
39 SysUtils,
40 e_log, e_graphics, e_input, g_options, g_game, g_main, g_weapons, g_console;
42 const
43 VS_KEYBOARD = 60000;
45 var
46 angleFire: Boolean;
47 keyFinger: array [VK_FIRSTKEY..VK_LASTKEY] of Integer;
49 procedure GetKeyRect(key: Integer; out x, y, w, h: Integer; out founded: Boolean);
50 var
51 sw, sh, sz: Integer;
52 dpi: Single;
53 begin
54 if SDL_GetDisplayDPI(0, @dpi, nil, nil) <> 0 then
55 dpi := 96;
57 founded := true;
58 sz := Trunc(g_touch_size * dpi);
59 sw := gScreenWidth; sh := gScreenHeight;
60 if g_touch_alt then
61 begin
62 w := sz div 2; h := sz div 2;
63 case key of
64 VK_CONSOLE: begin x := 0; y := 0 end;
65 VK_ESCAPE: begin x := sw - 1*w - 1; y := 0 end;
66 VS_KEYBOARD:begin x := sw - 2*w - 1; y := 0 end;
67 VK_CHAT: begin x := sw div 2 - w div 2 - w; y := 0 end;
68 VK_STATUS: begin x := sw div 2 - w div 2 + 0; y := 0 end;
69 VK_TEAM: begin x := sw div 2 - w div 2 + w; y := 0 end;
70 VK_PREV: begin x := 0; y := sh - 4*sz - 1; w := sz end;
71 VK_NEXT: begin x := sw - sz - 1; y := sh - 4*sz - 1; w := sz end;
72 else
73 w := sz; h := sz * 3;
74 case key of
75 VK_LEFT: begin x := 0; y := sh - h - 1 end;
76 VK_RIGHT: begin x := w; y := sh - h - 1 end;
77 else
78 w := sz; h := sz;
79 case key of
80 VK_UP: begin x := sw - 2*w - 1; y := sh - 3*h - 1 end;
81 VK_FIRE: begin x := sw - 2*w - 1; y := sh - 2*h - 1 end;
82 VK_DOWN: begin x := sw - 2*w - 1; y := sh - 1*h - 1 end;
83 VK_OPEN: begin x := sw - 1*w - 1; y := sh - 1*h - h div 2 - 1 end;
84 VK_JUMP: begin x := sw - 1*w - 1; y := sh - 2*h - h div 2 - 1 end;
85 else
86 founded := false
87 end
88 end
89 end
90 end
91 else
92 begin
93 x := 0; y := Round(sh * g_touch_offset / 100); w := sz; h := sz;
94 case key of
95 VK_ESCAPE: begin x := 0; y := y - 3*h div 2; w := w; h := h div 2 end;
96 VK_LSTRAFE: begin x := 0; y := y - h div 2; w := w div 2 end;
97 VK_LEFT: begin x := w div 2; y := y - h div 2 end;
98 VK_RIGHT: begin x := w div 2 + 1*w; y := y - h div 2 end;
99 VK_RSTRAFE: begin x := w div 2 + 2*w; y := y - h div 2; w := w div 2 end;
100 VK_UP: begin x := sw - w - 1; y := y - h div 2 - h end;
101 VK_FIRE: begin x := sw - 1*w - 1; y := y - h div 2 end;
102 VK_DOWN: begin x := sw - w - 1; y := y - h div 2 + h end;
103 VK_NEXT: begin x := sw - 2*w - 1; y := y - h div 2 - h end;
104 VK_JUMP: begin x := sw - 2*w - 1; y := y - h div 2 end;
105 VK_PREV: begin x := sw - 3*w - 1; y := y - h div 2 - h end;
106 VK_OPEN: begin x := sw - 3*w - 1; y := y - h div 2 end;
107 else
108 x := 0; y := 0; w := sz div 2; h := sz div 2;
109 case key of
110 VK_0: begin x := sw div 2 - w div 2 - 5*w - 1; y := sh - 1*h - 1 end;
111 VK_1: begin x := sw div 2 - w div 2 - 4*w - 1; y := sh - 1*h - 1 end;
112 VK_2: begin x := sw div 2 - w div 2 - 3*w - 1; y := sh - 1*h - 1 end;
113 VK_3: begin x := sw div 2 - w div 2 - 2*w - 1; y := sh - 1*h - 1 end;
114 VK_4: begin x := sw div 2 - w div 2 - 1*w - 1; y := sh - 1*h - 1 end;
115 VK_5: begin x := sw div 2 - w div 2 + 0*w - 1; y := sh - 1*h - 1 end;
116 VK_6: begin x := sw div 2 - w div 2 + 1*w - 1; y := sh - 1*h - 1 end;
117 VK_7: begin x := sw div 2 - w div 2 + 2*w - 1; y := sh - 1*h - 1 end;
118 VK_8: begin x := sw div 2 - w div 2 + 3*w - 1; y := sh - 1*h - 1 end;
119 VK_9: begin x := sw div 2 - w div 2 + 4*w - 1; y := sh - 1*h - 1 end;
120 VK_A: begin x := sw div 2 - w div 2 + 5*w - 1; y := sh - 1*h - 1 end;
121 VK_CHAT: begin x := sw div 2 - w div 2 - 2*w - 1; y := sh - 2*h - 1 end;
122 VK_CONSOLE: begin x := sw div 2 - w div 2 - 1*w - 1; y := sh - 2*h - 1 end;
123 VK_STATUS: begin x := sw div 2 - w div 2 + 0*w - 1; y := sh - 2*h - 1 end;
124 VK_TEAM: begin x := sw div 2 - w div 2 + 1*w - 1; y := sh - 2*h - 1 end;
125 VS_KEYBOARD:begin x := sw div 2 - w div 2 + 2*w - 1; y := sh - 2*h - 1 end;
126 else
127 founded := false
128 end
129 end
130 end
131 end;
133 function GetKeyName(key: Integer): String;
134 begin
135 case key of
136 VS_KEYBOARD: result := 'KBD';
137 VK_LEFT: result := 'LEFT';
138 VK_RIGHT: result := 'RIGHT';
139 VK_UP: result := 'UP';
140 VK_DOWN: result := 'DOWN';
141 VK_FIRE: result := 'FIRE';
142 VK_OPEN: result := 'OPEN';
143 VK_JUMP: result := 'JUMP';
144 VK_CHAT: result := 'CHAT';
145 VK_ESCAPE: result := 'ESC';
146 VK_0: result := '0';
147 VK_1: result := '1';
148 VK_2: result := '2';
149 VK_3: result := '3';
150 VK_4: result := '4';
151 VK_5: result := '5';
152 VK_6: result := '6';
153 VK_7: result := '7';
154 VK_8: result := '8';
155 VK_9: result := '9';
156 VK_A: result := '10';
157 VK_B: result := '11';
158 VK_C: result := '12';
159 VK_D: result := '13';
160 VK_E: result := '14';
161 VK_F: result := '15';
162 VK_CONSOLE: result := 'CON';
163 VK_STATUS: result := 'STAT';
164 VK_TEAM: result := 'TEAM';
165 VK_PREV: result := '<PREW';
166 VK_NEXT: result := 'NEXT>';
167 VK_LSTRAFE: result := '<';
168 VK_RSTRAFE: result := '>';
169 else
170 if (key > 0) and (key < e_MaxInputKeys) then
171 result := e_KeyNames[key]
172 else
173 result := '<' + IntToStr(key) + '>'
174 end
175 end;
177 function IntersectControl(ctl, xx, yy: Integer): Boolean;
178 var
179 x, y, w, h: Integer;
180 founded: Boolean;
181 begin
182 GetKeyRect(ctl, x, y, w, h, founded);
183 result := founded and (xx >= x) and (yy >= y) and (xx <= x + w) and (yy <= y + h);
184 end;
186 procedure g_Touch_Init;
187 begin
188 {$IFNDEF HEADLESS}
189 g_touch_enabled := SDL_GetNumTouchDevices() > 0
190 {$ENDIF}
191 end;
193 procedure g_Touch_ShowKeyboard(yes: Boolean);
194 begin
195 {$IFNDEF HEADLESS}
196 if not g_touch_enabled then
197 Exit;
199 if yes then
200 SDL_StartTextInput
201 else
202 SDL_StopTextInput
203 {$ENDIF}
204 end;
206 procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent);
207 var
208 x, y, i, finger: Integer;
209 begin
210 if not g_touch_enabled then
211 Exit;
212 if SDL_IsTextInputActive() = SDL_True then
213 Exit;
215 finger := ev.fingerId + 2;
216 x := Trunc(ev.x * gScreenWidth);
217 y := Trunc(ev.y * gScreenHeight);
219 for i := VK_FIRSTKEY to VK_LASTKEY do
220 begin
221 if IntersectControl(i, x, y) then
222 begin
223 if ev.type_ = SDL_FINGERUP then
224 keyFinger[i] := 0
225 else if ev.type_ = SDL_FINGERMOTION then
226 keyFinger[i] := finger
227 else if ev.type_ = SDL_FINGERDOWN then
228 begin
229 KeyPress(i); // Menu events
230 keyFinger[i] := finger;
231 end
232 end
233 else if keyFinger[i] = finger then
234 begin
235 if ev.type_ = SDL_FINGERUP then
236 keyFinger[i] := 0
237 else if ev.type_ = SDL_FINGERMOTION then
238 keyFinger[i] := 0
239 end;
241 e_KeyUpDown(i, keyFinger[i] <> 0);
242 end;
244 if IntersectControl(VS_KEYBOARD, x, y) then
245 g_Touch_ShowKeyboard(true);
247 (* emulate up+fire / donw+fire *)
248 if g_touch_fire and (gGameSettings.GameType <> GT_NONE) then
249 begin
250 if keyFinger[VK_UP] <> 0 then
251 begin
252 angleFire := true;
253 keyFinger[VK_FIRE] := keyFinger[VK_UP];
254 e_KeyUpDown(VK_FIRE, true);
255 end
256 else if keyFinger[VK_DOWN] <> 0 then
257 begin
258 angleFire := true;
259 keyFinger[VK_FIRE] := keyFinger[VK_DOWN];
260 e_KeyUpDown(VK_FIRE, true);
261 end
262 else if angleFire then
263 begin
264 angleFire := false;
265 keyFinger[VK_FIRE] := 0;
266 e_KeyUpDown(VK_FIRE, false);
267 end
268 end;
270 (* left/right strafe *)
271 if gGameSettings.GameType <> GT_NONE then
272 begin
273 if keyFinger[VK_LSTRAFE] <> 0 then
274 begin
275 keyFinger[VK_LEFT] := finger;
276 keyFinger[VK_RIGHT] := 0;
277 keyFinger[VK_STRAFE] := finger;
278 e_KeyUpDown(VK_LEFT, true);
279 e_KeyUpDown(VK_RIGHT, false);
280 e_KeyUpDown(VK_STRAFE, true);
281 end
282 else if keyFinger[VK_RSTRAFE] <> 0 then
283 begin
284 keyFinger[VK_LEFT] := 0;
285 keyFinger[VK_RIGHT] := finger;
286 keyFinger[VK_STRAFE] := finger;
287 e_KeyUpDown(VK_LEFT, false);
288 e_KeyUpDown(VK_RIGHT, true);
289 e_KeyUpDown(VK_STRAFE, true);
290 end
291 else
292 begin
293 keyFinger[VK_STRAFE] := 0;
294 e_KeyUpDown(VK_STRAFE, false);
295 end
296 end;
297 end;
299 procedure g_Touch_Draw;
300 var i: Integer;
302 procedure Draw (i: Integer);
303 var x, y, w, h: Integer; founded: Boolean;
304 begin
305 GetKeyRect(i, x, y, w, h, founded);
306 if founded then
307 begin
308 e_DrawQuad(x, y, x + w, y + h, 0, 255, 0, 31);
309 e_TextureFontPrintEx(x, y, GetKeyName(i), gStdFont, 255, 255, 255, 1, True)
310 end;
311 end;
313 begin
314 {$IFNDEF HEADLESS}
315 if not g_touch_enabled then
316 Exit;
317 if SDL_IsTextInputActive() = SDL_True then
318 Exit;
320 for i := VK_FIRSTKEY to VK_LASTKEY do
321 Draw(i);
323 Draw(VS_KEYBOARD);
324 {$ENDIF}
325 end;
327 initialization
328 conRegVar('touch_enable', @g_touch_enabled, 'enable/disable virtual buttons', 'draw buttons');
329 conRegVar('touch_fire', @g_touch_fire, 'enable/disable fire when press virtual up/down', 'fire when press up/down');
330 conRegVar('touch_size', @g_touch_size, 0.1, 10, 'size of virtual buttons', 'button size');
331 conRegVar('touch_offset', @g_touch_offset, 0, 100, '', '');
332 conRegVar('touch_alt', @g_touch_alt, 'althernative virtual buttons layout', 'althernative layout');
333 end.