28
28
#include " video/drawing_context.hpp"
29
29
#include " video/surface.hpp"
30
30
31
- // Util to automatically put rectangles in their corners
32
- static Rectf apply_corner (const Rectf& rect, int screen_width, int screen_height)
33
- {
34
- Rectf r = rect;
35
-
36
- if (r.p1 ().x < 0 )
37
- r.move (Vector (static_cast <float >(screen_width), 0 ));
38
-
39
- if (r.p1 ().y < 0 )
40
- r.move (Vector (0 , static_cast <float >(screen_height)));
41
-
42
- return r;
43
- }
44
-
45
31
MobileController::MobileController () :
46
32
m_up(false ),
47
33
m_down(false ),
@@ -61,12 +47,19 @@ MobileController::MobileController() :
61
47
m_old_cheats(false ),
62
48
m_old_debug(false ),
63
49
m_old_escape(false ),
50
+ m_fingers(),
64
51
m_rect_directions(16 .f, -144 .f, 144 .f, -16 .f),
65
52
m_rect_jump(-160 .f, -80 .f, -96 .f, -16 .f),
66
53
m_rect_action(-80 .f, -80 .f, -16 .f, -16 .f),
67
54
m_rect_cheats(-160 .f, 16 .f, -96 .f, 80 .f),
68
55
m_rect_debug(-80 .f, 16 .f, -16 .f, 80 .f),
69
56
m_rect_escape(16 .f, 16 .f, 64 .f, 64 .f),
57
+ m_draw_directions(16 .f, -144 .f, 144 .f, -16 .f),
58
+ m_draw_jump(-160 .f, -80 .f, -96 .f, -16 .f),
59
+ m_draw_action(-80 .f, -80 .f, -16 .f, -16 .f),
60
+ m_draw_cheats(-160 .f, 16 .f, -96 .f, 80 .f),
61
+ m_draw_debug(-80 .f, 16 .f, -16 .f, 80 .f),
62
+ m_draw_escape(16 .f, 16 .f, 64 .f, 64 .f),
70
63
m_tex_dirs(Surface::from_file(" /images/engine/mobile/direction.png" )),
71
64
m_tex_btn(Surface::from_file(" /images/engine/mobile/button.png" )),
72
65
m_tex_btn_press(Surface::from_file(" /images/engine/mobile/button_press.png" )),
@@ -90,36 +83,75 @@ MobileController::draw(DrawingContext& context)
90
83
if (!g_config->mobile_controls )
91
84
return ;
92
85
93
- m_screen_width = context.get_width ();
94
- m_screen_height = context.get_height ();
86
+ if (m_screen_width != context.get_width () || m_screen_height != context.get_height ())
87
+ {
88
+ m_screen_width = context.get_width ();
89
+ m_screen_height = context.get_height ();
90
+ float width = static_cast <float >(m_screen_width);
91
+ float height = static_cast <float >(m_screen_height);
92
+ // Buttons on Android are bigger, and direction buttons are extra wide
93
+ // Use screen height to calculate button size, because 20:9 screen ratios are common
94
+ #ifdef __ANDROID__
95
+ constexpr float BUTTON_SCALE = 0 .4f ;
96
+ #else
97
+ constexpr float BUTTON_SCALE = 0 .2f ;
98
+ #endif
99
+ m_rect_directions.set_size (height * BUTTON_SCALE * 4 / 3 , height * BUTTON_SCALE);
100
+ m_rect_directions.set_pos (Vector (0 , height - height * BUTTON_SCALE));
101
+ m_draw_directions = Rectf::from_center (m_rect_directions.get_middle (),
102
+ Sizef (m_rect_directions.get_height () / 2 , m_rect_directions.get_height () / 2 ));
103
+
104
+ m_rect_jump.set_size (height * BUTTON_SCALE, height * BUTTON_SCALE);
105
+ m_rect_jump.set_pos (Vector (width - height * BUTTON_SCALE, height - height * BUTTON_SCALE));
106
+ m_draw_jump = m_rect_jump.grown (-m_rect_jump.get_height () * 3 / 8 );
107
+
108
+ m_rect_action.set_size (height * BUTTON_SCALE, height * BUTTON_SCALE);
109
+ m_rect_action.set_pos (Vector (width - 2 * height * BUTTON_SCALE, height - height * BUTTON_SCALE));
110
+ m_draw_action = m_rect_action.grown (-m_rect_action.get_height () * 3 / 8 );
111
+
112
+ m_rect_escape.set_size (height * BUTTON_SCALE / 2 , height * BUTTON_SCALE / 2 );
113
+ m_rect_escape.set_pos (Vector (0 , 0 ));
114
+ m_draw_escape = m_rect_escape.grown (-m_rect_escape.get_height () / 4 );
115
+
116
+ m_rect_cheats.set_size (height * BUTTON_SCALE / 2 , height * BUTTON_SCALE / 2 );
117
+ m_rect_cheats.set_pos (Vector (width - 2 * height * BUTTON_SCALE / 2 , 0 ));
118
+ m_draw_cheats = m_rect_cheats.grown (-m_rect_cheats.get_height () / 4 );
119
+
120
+ m_rect_debug.set_size (height * BUTTON_SCALE / 2 , height * BUTTON_SCALE / 2 );
121
+ m_rect_debug.set_pos (Vector (width - height * BUTTON_SCALE / 2 , 0 ));
122
+ m_draw_debug = m_rect_debug.grown (-m_rect_debug.get_height () / 4 );
123
+ }
124
+
125
+ PaintStyle translucent;
126
+ translucent.set_alpha (0 .5f );
95
127
96
- context.color ().draw_surface_scaled (m_tex_dirs, apply_corner (m_rect_directions, m_screen_width, m_screen_height), LAYER_GUI + 99 );
128
+ context.color ().draw_surface_scaled (m_tex_dirs, m_draw_directions, LAYER_GUI + 99 , translucent );
97
129
98
130
if (m_up)
99
- context.color ().draw_surface_scaled (m_tex_up, apply_corner (m_rect_directions, m_screen_width, m_screen_height), LAYER_GUI + 99 );
131
+ context.color ().draw_surface_scaled (m_tex_up, m_draw_directions, LAYER_GUI + 99 , translucent );
100
132
if (m_down)
101
- context.color ().draw_surface_scaled (m_tex_dwn, apply_corner (m_rect_directions, m_screen_width, m_screen_height), LAYER_GUI + 99 );
133
+ context.color ().draw_surface_scaled (m_tex_dwn, m_draw_directions, LAYER_GUI + 99 , translucent );
102
134
if (m_left)
103
- context.color ().draw_surface_scaled (m_tex_lft, apply_corner (m_rect_directions, m_screen_width, m_screen_height), LAYER_GUI + 99 );
135
+ context.color ().draw_surface_scaled (m_tex_lft, m_draw_directions, LAYER_GUI + 99 , translucent );
104
136
if (m_right)
105
- context.color ().draw_surface_scaled (m_tex_rgt, apply_corner (m_rect_directions, m_screen_width, m_screen_height), LAYER_GUI + 99 );
137
+ context.color ().draw_surface_scaled (m_tex_rgt, m_draw_directions, LAYER_GUI + 99 , translucent );
106
138
107
- context.color ().draw_surface_scaled (m_action ? m_tex_btn_press : m_tex_btn, apply_corner (m_rect_action, m_screen_width, m_screen_height), LAYER_GUI + 99 );
108
- context.color ().draw_surface_scaled (m_tex_action, apply_corner (m_rect_action, m_screen_width, m_screen_height), LAYER_GUI + 99 );
139
+ context.color ().draw_surface_scaled (m_action ? m_tex_btn_press : m_tex_btn, m_draw_action, LAYER_GUI + 99 , translucent );
140
+ context.color ().draw_surface_scaled (m_tex_action, m_draw_action, LAYER_GUI + 99 , translucent );
109
141
110
- context.color ().draw_surface_scaled (m_jump ? m_tex_btn_press : m_tex_btn, apply_corner (m_rect_jump, m_screen_width, m_screen_height), LAYER_GUI + 99 );
111
- context.color ().draw_surface_scaled (m_tex_jump, apply_corner (m_rect_jump, m_screen_width, m_screen_height), LAYER_GUI + 99 );
142
+ context.color ().draw_surface_scaled (m_jump ? m_tex_btn_press : m_tex_btn, m_draw_jump, LAYER_GUI + 99 , translucent );
143
+ context.color ().draw_surface_scaled (m_tex_jump, m_draw_jump, LAYER_GUI + 99 , translucent );
112
144
113
- context.color ().draw_surface_scaled (m_escape ? m_tex_btn_press : m_tex_btn, apply_corner (m_rect_escape, m_screen_width, m_screen_height), LAYER_GUI + 99 );
114
- context.color ().draw_surface_scaled (m_tex_pause, apply_corner (m_rect_escape, m_screen_width, m_screen_height) .grown (-8 . f ) , LAYER_GUI + 99 );
145
+ context.color ().draw_surface_scaled (m_escape ? m_tex_btn_press : m_tex_btn, m_draw_escape, LAYER_GUI + 99 , translucent );
146
+ context.color ().draw_surface_scaled (m_tex_pause, m_draw_escape .grown (-m_draw_escape. get_height () / 8 ) , LAYER_GUI + 99 , translucent );
115
147
116
148
if (g_config->developer_mode )
117
149
{
118
- context.color ().draw_surface_scaled (m_cheats ? m_tex_btn_press : m_tex_btn, apply_corner (m_rect_cheats, m_screen_width, m_screen_height), LAYER_GUI + 99 );
119
- context.color ().draw_surface_scaled (m_tex_cheats, apply_corner (m_rect_cheats, m_screen_width, m_screen_height), LAYER_GUI + 99 );
150
+ context.color ().draw_surface_scaled (m_cheats ? m_tex_btn_press : m_tex_btn, m_draw_cheats, LAYER_GUI + 99 , translucent );
151
+ context.color ().draw_surface_scaled (m_tex_cheats, m_draw_cheats, LAYER_GUI + 99 , translucent );
120
152
121
- context.color ().draw_surface_scaled (m_debug ? m_tex_btn_press : m_tex_btn, apply_corner (m_rect_debug, m_screen_width, m_screen_height), LAYER_GUI + 99 );
122
- context.color ().draw_surface_scaled (m_tex_debug, apply_corner (m_rect_debug, m_screen_width, m_screen_height), LAYER_GUI + 99 );
153
+ context.color ().draw_surface_scaled (m_debug ? m_tex_btn_press : m_tex_btn, m_draw_debug, LAYER_GUI + 99 , translucent );
154
+ context.color ().draw_surface_scaled (m_tex_debug, m_draw_debug, LAYER_GUI + 99 , translucent );
123
155
}
124
156
}
125
157
@@ -149,26 +181,9 @@ MobileController::update()
149
181
activate_widget_at_pos (static_cast <float >(x), static_cast <float >(y));
150
182
}
151
183
152
- // FIXME: This assumes that 1) there is only one touchscreen and 2) SuperTux
153
- // fills the whole screen
154
- if (SDL_GetNumTouchDevices () < 1 )
155
- return ;
156
-
157
- SDL_TouchID device = SDL_GetTouchDevice (0 );
158
-
159
- if (device == 0 )
160
- throw new std::runtime_error (" Error getting touchscreen info: " + std::string (SDL_GetError ()));
161
-
162
- int num_touches = SDL_GetNumTouchFingers (device);
163
-
164
- for (int i = 0 ; i < num_touches; i++)
184
+ for (auto & i : m_fingers)
165
185
{
166
- SDL_Finger* finger = SDL_GetTouchFinger (device, i);
167
-
168
- if (!finger)
169
- continue ;
170
-
171
- activate_widget_at_pos (finger->x * float (m_screen_width), finger->y * float (m_screen_height));
186
+ activate_widget_at_pos (i.second .x , i.second .y );
172
187
}
173
188
}
174
189
@@ -196,6 +211,50 @@ MobileController::apply(Controller& controller) const
196
211
controller.set_control (Control::DEBUG_MENU, m_debug);
197
212
if (m_escape != m_old_escape)
198
213
controller.set_control (Control::ESCAPE, m_escape);
214
+
215
+ if (m_up || m_down || m_left || m_right || m_jump || m_action || m_cheats || m_debug || m_escape)
216
+ {
217
+ controller.set_touchscreen (true );
218
+ }
219
+ }
220
+
221
+ bool
222
+ MobileController::process_finger_down_event (const SDL_TouchFingerEvent& event)
223
+ {
224
+ Vector pos (event.x * float (m_screen_width), event.y * float (m_screen_height));
225
+ m_fingers[event.fingerId ] = pos;
226
+ return m_rect_jump.contains (pos) ||
227
+ m_rect_action.contains (pos) ||
228
+ m_rect_escape.contains (pos) ||
229
+ m_rect_directions.contains (pos) ||
230
+ (g_config->developer_mode && m_rect_cheats.contains (pos)) ||
231
+ (g_config->developer_mode && m_rect_debug.contains (pos));
232
+ }
233
+
234
+ bool
235
+ MobileController::process_finger_up_event (const SDL_TouchFingerEvent& event)
236
+ {
237
+ Vector pos (event.x * float (m_screen_width), event.y * float (m_screen_height));
238
+ m_fingers.erase (event.fingerId );
239
+ return m_rect_jump.contains (pos) ||
240
+ m_rect_action.contains (pos) ||
241
+ m_rect_escape.contains (pos) ||
242
+ m_rect_directions.contains (pos) ||
243
+ (g_config->developer_mode && m_rect_cheats.contains (pos)) ||
244
+ (g_config->developer_mode && m_rect_debug.contains (pos));
245
+ }
246
+
247
+ bool
248
+ MobileController::process_finger_motion_event (const SDL_TouchFingerEvent& event)
249
+ {
250
+ Vector pos (event.x * float (m_screen_width), event.y * float (m_screen_height));
251
+ m_fingers[event.fingerId ] = pos;
252
+ return m_rect_jump.contains (pos) ||
253
+ m_rect_action.contains (pos) ||
254
+ m_rect_escape.contains (pos) ||
255
+ m_rect_directions.contains (pos) ||
256
+ (g_config->developer_mode && m_rect_cheats.contains (pos)) ||
257
+ (g_config->developer_mode && m_rect_debug.contains (pos));
199
258
}
200
259
201
260
void
@@ -206,42 +265,41 @@ MobileController::activate_widget_at_pos(float x, float y)
206
265
207
266
Vector pos (x, y);
208
267
209
- if (apply_corner ( m_rect_jump, m_screen_width, m_screen_height) .contains (pos))
268
+ if (m_rect_jump.contains (pos))
210
269
m_jump = true ;
211
270
212
- if (apply_corner ( m_rect_action, m_screen_width, m_screen_height) .contains (pos))
271
+ if (m_rect_action.contains (pos))
213
272
m_action = true ;
214
273
215
274
if (g_config->developer_mode )
216
275
{
217
- if (apply_corner ( m_rect_cheats, m_screen_width, m_screen_height) .contains (pos))
276
+ if (m_rect_cheats.contains (pos))
218
277
m_cheats = true ;
219
278
220
- if (apply_corner ( m_rect_debug, m_screen_width, m_screen_height) .contains (pos))
279
+ if (m_rect_debug.contains (pos))
221
280
m_debug = true ;
222
281
}
223
282
224
- if (apply_corner ( m_rect_escape, m_screen_width, m_screen_height) .contains (pos))
283
+ if (m_rect_escape.contains (pos))
225
284
m_escape = true ;
226
285
227
- Rectf applied = apply_corner (m_rect_directions, m_screen_width, m_screen_height);
228
- Rectf up = applied;
286
+ Rectf up = m_rect_directions;
229
287
up.set_bottom (up.get_bottom () - up.get_height () * 2 .f / 3 .f );
230
288
if (up.contains (pos))
231
289
m_up = true ;
232
290
233
- Rectf down = applied ;
291
+ Rectf down = m_rect_directions ;
234
292
down.set_top (down.get_top () + down.get_height () * 2 .f / 3 .f );
235
293
if (down.contains (pos))
236
294
m_down = true ;
237
295
238
- Rectf left = applied ;
239
- left.set_right (left.get_right () - left.get_width () * 2 .f / 3 .f );
296
+ Rectf left = m_rect_directions ;
297
+ left.set_right (left.get_right () - left.get_width () * 7 .f / 12 .f );
240
298
if (left.contains (pos))
241
299
m_left = true ;
242
300
243
- Rectf right = applied ;
244
- right.set_left (right.get_left () + right.get_width () * 2 .f / 3 .f );
301
+ Rectf right = m_rect_directions ;
302
+ right.set_left (right.get_left () + right.get_width () * 7 .f / 12 .f );
245
303
if (right.contains (pos))
246
304
m_right = true ;
247
305
}
0 commit comments