5102f188bf913578599d838018e2ac71c05d7ff3
[oweals/minetest.git] / src / gui / touchscreengui.h
1 /*
2 Copyright (C) 2014 sapier
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #pragma once
20
21 #include <IEventReceiver.h>
22 #include <IGUIButton.h>
23 #include <IGUIEnvironment.h>
24 #include <IrrlichtDevice.h>
25
26 #include <map>
27 #include <vector>
28
29 #include "client/tile.h"
30 #include "game.h"
31
32 using namespace irr;
33 using namespace irr::core;
34 using namespace irr::gui;
35
36 typedef enum {
37         jump_id = 0,
38         crunch_id,
39         zoom_id,
40         special1_id,
41         after_last_element_id,
42         settings_starter_id,
43         rare_controls_starter_id,
44         fly_id,
45         noclip_id,
46         fast_id,
47         debug_id,
48         camera_id,
49         range_id,
50         minimap_id,
51         toggle_chat_id,
52         chat_id,
53         inventory_id,
54         drop_id,
55         forward_id,
56         backward_id,
57         left_id,
58         right_id,
59         joystick_off_id,
60         joystick_bg_id,
61         joystick_center_id
62 } touch_gui_button_id;
63
64 typedef enum {
65         j_forward = 0,
66         j_backward,
67         j_left,
68         j_right,
69         j_special1
70 } touch_gui_joystick_move_id;
71
72 typedef enum {
73         AHBB_Dir_Top_Bottom,
74         AHBB_Dir_Bottom_Top,
75         AHBB_Dir_Left_Right,
76         AHBB_Dir_Right_Left
77 } autohide_button_bar_dir;
78
79 #define MIN_DIG_TIME_MS 500
80 #define MAX_TOUCH_COUNT 64
81 #define BUTTON_REPEAT_DELAY 0.2f
82
83 #define SETTINGS_BAR_Y_OFFSET 5
84 #define RARE_CONTROLS_BAR_Y_OFFSET 4
85
86 extern const char **touchgui_button_imagenames;
87 extern const char **touchgui_joystick_imagenames;
88
89 struct button_info
90 {
91         float repeatcounter;
92         float repeatdelay;
93         irr::EKEY_CODE keycode;
94         std::vector<int> ids;
95         IGUIButton *guibutton = nullptr;
96         bool immediate_release;
97
98         // 0: false, 1: (true) first texture, 2: (true) second texture
99         int togglable = 0;
100         std::vector<const char *> textures;
101 };
102
103 class AutoHideButtonBar
104 {
105 public:
106         AutoHideButtonBar(IrrlichtDevice *device, IEventReceiver *receiver);
107
108         void init(ISimpleTextureSource *tsrc, const char *starter_img, int button_id,
109                         v2s32 UpperLeft, v2s32 LowerRight, autohide_button_bar_dir dir,
110                         float timeout);
111
112         ~AutoHideButtonBar();
113
114         // add button to be shown
115         void addButton(touch_gui_button_id id, const wchar_t *caption,
116                         const char *btn_image);
117
118         // add toggle button to be shown
119         void addToggleButton(touch_gui_button_id id, const wchar_t *caption,
120                         const char *btn_image_1, const char *btn_image_2);
121
122         // detect settings bar button events
123         bool isButton(const SEvent &event);
124
125         // handle released hud buttons
126         bool isReleaseButton(int eventID);
127
128         // step handler
129         void step(float dtime);
130
131         // deactivate button bar
132         void deactivate();
133
134         // hide the whole buttonbar
135         void hide();
136
137         // unhide the buttonbar
138         void show();
139
140 private:
141         ISimpleTextureSource *m_texturesource = nullptr;
142         irr::video::IVideoDriver *m_driver;
143         IGUIEnvironment *m_guienv;
144         IEventReceiver *m_receiver;
145         button_info m_starter;
146         std::vector<button_info *> m_buttons;
147
148         v2s32 m_upper_left;
149         v2s32 m_lower_right;
150
151         // show settings bar
152         bool m_active = false;
153
154         bool m_visible = true;
155
156         // settings bar timeout
157         float m_timeout = 0.0f;
158         float m_timeout_value = 3.0f;
159         bool m_initialized = false;
160         autohide_button_bar_dir m_dir = AHBB_Dir_Right_Left;
161 };
162
163 class TouchScreenGUI
164 {
165 public:
166         TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver);
167         ~TouchScreenGUI();
168
169         void translateEvent(const SEvent &event);
170
171         void init(ISimpleTextureSource *tsrc);
172
173         double getYawChange()
174         {
175                 double res = m_camera_yaw_change;
176                 m_camera_yaw_change = 0;
177                 return res;
178         }
179
180         double getPitch() { return m_camera_pitch; }
181
182         /*!
183          * Returns a line which describes what the player is pointing at.
184          * The starting point and looking direction are significant,
185          * the line should be scaled to match its length to the actual distance
186          * the player can reach.
187          * The line starts at the camera and ends on the camera's far plane.
188          * The coordinates do not contain the camera offset.
189          */
190         line3d<f32> getShootline() { return m_shootline; }
191
192         void step(float dtime);
193         void resetHud();
194         void registerHudItem(int index, const rect<s32> &rect);
195         void Toggle(bool visible);
196
197         void hide();
198         void show();
199
200 private:
201         IrrlichtDevice *m_device;
202         IGUIEnvironment *m_guienv;
203         IEventReceiver *m_receiver;
204         ISimpleTextureSource *m_texturesource;
205         v2u32 m_screensize;
206         double m_touchscreen_threshold;
207         std::map<int, rect<s32>> m_hud_rects;
208         std::map<int, irr::EKEY_CODE> m_hud_ids;
209         bool m_visible; // is the gui visible
210
211         // value in degree
212         double m_camera_yaw_change = 0.0;
213         double m_camera_pitch = 0.0;
214
215         // forward, backward, left, right
216         touch_gui_button_id m_joystick_names[5] = {
217                         forward_id, backward_id, left_id, right_id, special1_id};
218         bool m_joystick_status[5] = {false, false, false, false, false};
219
220         /*!
221          * A line starting at the camera and pointing towards the
222          * selected object.
223          * The line ends on the camera's far plane.
224          * The coordinates do not contain the camera offset.
225          */
226         line3d<f32> m_shootline;
227
228         int m_move_id = -1;
229         bool m_move_has_really_moved = false;
230         s64 m_move_downtime = 0;
231         bool m_move_sent_as_mouse_event = false;
232         v2s32 m_move_downlocation = v2s32(-10000, -10000);
233
234         int m_joystick_id = -1;
235         bool m_joystick_has_really_moved = false;
236         bool m_fixed_joystick = false;
237         bool m_joystick_triggers_special1 = false;
238         button_info *m_joystick_btn_off = nullptr;
239         button_info *m_joystick_btn_bg = nullptr;
240         button_info *m_joystick_btn_center = nullptr;
241
242         button_info m_buttons[after_last_element_id];
243
244         // gui button detection
245         touch_gui_button_id getButtonID(s32 x, s32 y);
246
247         // gui button by eventID
248         touch_gui_button_id getButtonID(int eventID);
249
250         // check if a button has changed
251         void handleChangedButton(const SEvent &event);
252
253         // initialize a button
254         void initButton(touch_gui_button_id id, rect<s32> button_rect,
255                         std::wstring caption, bool immediate_release,
256                         float repeat_delay = BUTTON_REPEAT_DELAY);
257
258         // initialize a joystick button
259         button_info *initJoystickButton(touch_gui_button_id id, rect<s32> button_rect,
260                         int texture_id, bool visible = true);
261
262         struct id_status
263         {
264                 int id;
265                 int X;
266                 int Y;
267         };
268
269         // vector to store known ids and their initial touch positions
270         std::vector<id_status> m_known_ids;
271
272         // handle a button event
273         void handleButtonEvent(touch_gui_button_id bID, int eventID, bool action);
274
275         // handle pressed hud buttons
276         bool isHUDButton(const SEvent &event);
277
278         // handle released hud buttons
279         bool isReleaseHUDButton(int eventID);
280
281         // handle double taps
282         bool doubleTapDetection();
283
284         // handle release event
285         void handleReleaseEvent(int evt_id);
286
287         // apply joystick status
288         void applyJoystickStatus();
289
290         // get size of regular gui control button
291         int getGuiButtonSize();
292
293         // doubleclick detection variables
294         struct key_event
295         {
296                 unsigned int down_time;
297                 s32 x;
298                 s32 y;
299         };
300
301         // array for saving last known position of a pointer
302         v2s32 m_pointerpos[MAX_TOUCH_COUNT];
303
304         // array for doubletap detection
305         key_event m_key_events[2];
306
307         // settings bar
308         AutoHideButtonBar m_settingsbar;
309
310         // rare controls bar
311         AutoHideButtonBar m_rarecontrolsbar;
312 };
313 extern TouchScreenGUI *g_touchscreengui;