DEADSOFTWARE

Reserved key range for virtual keyboard + alternative virtkbd layout
[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 procedure g_Touch_ShowKeyboard(yes: Boolean);
25 procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent);
26 procedure g_Touch_Draw;
28 implementation
30 uses
31 SysUtils,
32 e_log, e_graphics, e_input, g_options, g_game, g_main, g_weapons, g_console;
34 var
35 jab: Boolean;
36 size: Single;
37 enabled: Boolean;
38 keyFinger: array [VK_FIRSTKEY..VK_LASTKEY] of Integer;
40 procedure GetKeyRect(key: Word; out x, y, w, h: Integer; out founded: Boolean);
41 var
42 sw, sh, sz: Integer;
43 dpi: Single;
44 begin
45 if SDL_GetDisplayDPI(0, @dpi, nil, nil) <> 0 then
46 dpi := 96;
48 founded := true;
49 sz := Trunc(size * dpi);
50 sw := gScreenWidth; sh := gScreenHeight;
51 if jab then
52 begin
53 w := sz div 2; h := sz div 3;
54 case key of
55 VK_CONSOLE: begin x := 0; y := 0 end;
56 VK_ESCAPE: begin x := sw - w - 1; y := 0 end;
57 VK_CHAT: begin x := sw div 2 - w - 4; y := 0 end;
58 VK_TEAM: begin x := sw div 2 + 0 + 4; y := 0 end;
59 else
60 w := sz; h := sz * 2;
61 case key of
62 VK_LEFT: begin x := 0; y := sh - h - 1 end;
63 VK_RIGHT: begin x := w; y := sh - h - 1 end;
64 else
65 w := sz; h := sz;
66 case key of
67 VK_OPEN: begin h := sz; x := sw - 1*w - 1; y := sh - 1*h - 1 end;
68 VK_JUMP: begin h := sz; x := sw - 1*w - 1; y := sh - 2*h - 1 end;
69 VK_UP: begin h := sz div 2; x := sw - 2*w - 1; y := sh - 2*sz - 1 end;
70 VK_FIRE: begin h := sz; x := sw - 2*w - 1; y := sh - sz div 2 - sz - 1 end;
71 VK_DOWN: begin h := sz div 2; x := sw - 2*w - 1; y := sh - sz div 2 - 1 end;
72 VK_PREV: begin h := sz div 2; x := 0; y := sh - 3*sz - 1 end;
73 VK_NEXT: begin h := sz div 2; x := sw - w - 1; y := sh - 3*sz - 1 end;
74 else
75 founded := false
76 end
77 end
78 end
79 end
80 else
81 begin
82 x := 0; y := 0; w := sz; h := sz;
83 case key of
84 VK_LEFT: begin x := 0; y := sh div 2 - h div 2; end;
85 VK_RIGHT: begin x := w; y := sh div 2 - h div 2; end;
86 VK_UP: begin x := sw - w - 1; y := sh div 2 - h div 2 - h; end;
87 VK_DOWN: begin x := sw - w - 1; y := sh div 2 - h div 2 + h; end;
88 VK_FIRE: begin x := sw - 1*w - 1; y := sh div 2 - h div 2; end;
89 VK_OPEN: begin x := sw - 3*w - 1; y := sh div 2 - h div 2; end;
90 VK_JUMP: begin x := sw - 2*w - 1; y := sh div 2 - h div 2; end;
91 else
92 w := sz div 2; h := sz div 2;
93 case key of
94 VK_0: begin x := sw div 2 - w div 2 - 5*w - 1; y := sh - 1*h - 1; end;
95 VK_1: begin x := sw div 2 - w div 2 - 4*w - 1; y := sh - 1*h - 1; end;
96 VK_2: begin x := sw div 2 - w div 2 - 3*w - 1; y := sh - 1*h - 1; end;
97 VK_3: begin x := sw div 2 - w div 2 - 2*w - 1; y := sh - 1*h - 1; end;
98 VK_4: begin x := sw div 2 - w div 2 - 1*w - 1; y := sh - 1*h - 1; end;
99 VK_5: begin x := sw div 2 - w div 2 + 0*w - 1; y := sh - 1*h - 1; end;
100 VK_6: begin x := sw div 2 - w div 2 + 1*w - 1; y := sh - 1*h - 1; end;
101 VK_7: begin x := sw div 2 - w div 2 + 2*w - 1; y := sh - 1*h - 1; end;
102 VK_8: begin x := sw div 2 - w div 2 + 3*w - 1; y := sh - 1*h - 1; end;
103 VK_9: begin x := sw div 2 - w div 2 + 4*w - 1; y := sh - 1*h - 1; end;
104 VK_A: begin x := sw div 2 - w div 2 + 5*w - 1; y := sh - 1*h - 1; end;
105 VK_CHAT: begin x := sw div 2 - w div 2 - 2*w - 1; y := sh - 2*h - 1; end;
106 VK_ESCAPE: begin x := sw div 2 - w div 2 - 1*w - 1; y := sh - 2*h - 1; end;
107 VK_CONSOLE: begin x := sw div 2 - w div 2 + 0*w - 1; y := sh - 2*h - 1; end;
108 VK_STATUS: begin x := sw div 2 - w div 2 + 1*w - 1; y := sh - 2*h - 1; end;
109 VK_TEAM: begin x := sw div 2 - w div 2 + 2*w - 1; y := sh - 2*h - 1; end;
110 else
111 founded := false
112 end
113 end
114 end
115 end;
117 function GetKeyName(key: Word): String;
118 begin
119 case key of
120 VK_LEFT: result := 'LEFT';
121 VK_RIGHT: result := 'RIGHT';
122 VK_UP: result := 'UP';
123 VK_DOWN: result := 'DOWN';
124 VK_FIRE: result := 'FIRE';
125 VK_OPEN: result := 'OPEN';
126 VK_JUMP: result := 'JUMP';
127 VK_CHAT: result := 'CHAT';
128 VK_ESCAPE: result := 'ESC';
129 VK_0: result := '0';
130 VK_1: result := '1';
131 VK_2: result := '2';
132 VK_3: result := '3';
133 VK_4: result := '4';
134 VK_5: result := '5';
135 VK_6: result := '6';
136 VK_7: result := '7';
137 VK_8: result := '8';
138 VK_9: result := '9';
139 VK_A: result := '10';
140 VK_B: result := '11';
141 VK_C: result := '12';
142 VK_D: result := '13';
143 VK_E: result := '14';
144 VK_F: result := '15';
145 VK_CONSOLE: result := 'CON';
146 VK_STATUS: result := 'STAT';
147 VK_TEAM: result := 'TEAM';
148 VK_PREV: result := '<PREV';
149 VK_NEXT: result := 'NEXT>';
150 else
151 if (key > 0) and (key < e_MaxInputKeys) then
152 result := e_KeyNames[key]
153 else
154 result := '<' + IntToStr(key) + '>'
155 end
156 end;
158 procedure DrawRect(x, y, w, h: Integer);
159 begin
160 e_DrawQuad(x, y, x + w, y + h, 0, 255, 0, 63);
161 end;
163 function IntersectControl(ctl, xx, yy: Integer): Boolean;
164 var
165 x, y, w, h: Integer;
166 founded: Boolean;
167 begin
168 GetKeyRect(ctl, x, y, w, h, founded);
169 result := founded and (xx >= x) and (yy >= y) and (xx <= x + w) and (yy <= y + h);
170 end;
172 procedure g_Touch_ShowKeyboard(yes: Boolean);
173 begin
174 {$IFNDEF HEADLESS}
175 if not enabled then
176 Exit;
178 if yes then
179 SDL_StartTextInput
180 else
181 SDL_StopTextInput
182 {$ENDIF}
183 end;
185 procedure g_Touch_HandleEvent(const ev: TSDL_TouchFingerEvent);
186 var
187 x, y, i, finger: Integer;
188 begin
189 if not enabled then
190 Exit;
191 if SDL_IsTextInputActive() = SDL_True then
192 Exit;
194 finger := ev.fingerId + 2;
195 x := Trunc(ev.x * gScreenWidth);
196 y := Trunc(ev.y * gScreenHeight);
198 for i := VK_FIRSTKEY to VK_LASTKEY do
199 begin
200 if IntersectControl(i, x, y) then
201 begin
202 if ev.type_ = SDL_FINGERUP then
203 keyFinger[i] := 0
204 else if ev.type_ = SDL_FINGERMOTION then
205 keyFinger[i] := finger
206 else if ev.type_ = SDL_FINGERDOWN then
207 begin
208 KeyPress(i); // Menu events
209 keyFinger[i] := finger;
210 end
211 end
212 else if keyFinger[i] = finger then
213 begin
214 if ev.type_ = SDL_FINGERUP then
215 keyFinger[i] := 0
216 else if ev.type_ = SDL_FINGERMOTION then
217 keyFinger[i] := 0
218 end;
220 e_KeyUpDown(i, keyFinger[i] <> 0);
221 end;
222 end;
224 procedure g_Touch_Draw;
225 var
226 i, x, y, w, h: Integer;
227 founded: Boolean;
228 begin
229 {$IFNDEF HEADLESS}
230 if not enabled then
231 Exit;
232 if SDL_IsTextInputActive() = SDL_True then
233 Exit;
235 for i := VK_FIRSTKEY to VK_LASTKEY do
236 begin
237 GetKeyRect(i, x, y, w, h, founded);
238 if founded then
239 begin
240 DrawRect(x, y, w, h);
241 e_TextureFontPrint(x, y, GetKeyName(i), gStdFont)
242 end;
243 end;
244 {$ENDIF}
245 end;
247 initialization
248 {$IFDEF ANDROID}
249 enabled := true;
250 {$ENDIF}
251 size := 1;
252 conRegVar('touch_enable', @enabled, 'enable/disable virtual buttons', 'draw buttons');
253 conRegVar('touch_size', @size, 0.1, 10, 'size of virtual buttons', 'button size');
254 conRegVar('touch_alt', @jab, 'althernative virtual buttons layout', 'althernative layout');
255 end.