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