From 5d9ca99ad711e022304c8af3ab0aaa17ec11199f Mon Sep 17 00:00:00 2001 From: MoNTE48 Date: Fri, 11 Sep 2020 23:25:18 +0200 Subject: [PATCH] Backport MultiCraft TouchScreenGUI improvements --- build/android/icons/camera_btn.svg | 108 --- build/android/icons/chat_btn.svg | 96 --- build/android/icons/down.svg | 542 --------------- build/android/icons/drop_btn.svg | 173 ----- build/android/icons/joystick_bg.svg | 876 ----------------------- build/android/icons/joystick_center.svg | 877 ----------------------- build/android/icons/joystick_off.svg | 882 ------------------------ build/android/icons/jump_btn.svg | 547 --------------- build/android/icons/minimap_btn.svg | 159 ----- build/android/icons/rangeview_btn.svg | 456 ------------ src/gui/touchscreengui.cpp | 370 ++++++---- src/gui/touchscreengui.h | 40 +- textures/base/pack/camera_btn.png | Bin 1859 -> 332 bytes textures/base/pack/chat_btn.png | Bin 873 -> 278 bytes textures/base/pack/down.png | Bin 1690 -> 0 bytes textures/base/pack/down_btn.png | Bin 0 -> 268 bytes textures/base/pack/drop_btn.png | Bin 1269 -> 543 bytes textures/base/pack/escape_btn.png | Bin 0 -> 245 bytes textures/base/pack/fly_btn.png | Bin 1559 -> 0 bytes textures/base/pack/inventory_btn.png | Bin 331 -> 259 bytes textures/base/pack/joystick_bg.png | Bin 12481 -> 718 bytes textures/base/pack/joystick_center.png | Bin 2574 -> 296 bytes textures/base/pack/joystick_off.png | Bin 14363 -> 1062 bytes textures/base/pack/jump_btn.png | Bin 1710 -> 291 bytes textures/base/pack/minimap_btn.png | Bin 1220 -> 351 bytes textures/base/pack/rangeview_btn.png | Bin 2423 -> 377 bytes 26 files changed, 248 insertions(+), 4878 deletions(-) delete mode 100644 build/android/icons/camera_btn.svg delete mode 100644 build/android/icons/chat_btn.svg delete mode 100644 build/android/icons/down.svg delete mode 100644 build/android/icons/drop_btn.svg delete mode 100644 build/android/icons/joystick_bg.svg delete mode 100644 build/android/icons/joystick_center.svg delete mode 100644 build/android/icons/joystick_off.svg delete mode 100644 build/android/icons/jump_btn.svg delete mode 100644 build/android/icons/minimap_btn.svg delete mode 100644 build/android/icons/rangeview_btn.svg delete mode 100644 textures/base/pack/down.png create mode 100644 textures/base/pack/down_btn.png create mode 100644 textures/base/pack/escape_btn.png delete mode 100644 textures/base/pack/fly_btn.png diff --git a/build/android/icons/camera_btn.svg b/build/android/icons/camera_btn.svg deleted file mode 100644 index a91a7fcf8..000000000 --- a/build/android/icons/camera_btn.svg +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/chat_btn.svg b/build/android/icons/chat_btn.svg deleted file mode 100644 index 41dc6f8c7..000000000 --- a/build/android/icons/chat_btn.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/down.svg b/build/android/icons/down.svg deleted file mode 100644 index 190e7e875..000000000 --- a/build/android/icons/down.svg +++ /dev/null @@ -1,542 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/drop_btn.svg b/build/android/icons/drop_btn.svg deleted file mode 100644 index 7cb0e8532..000000000 --- a/build/android/icons/drop_btn.svg +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/joystick_bg.svg b/build/android/icons/joystick_bg.svg deleted file mode 100644 index d8836b358..000000000 --- a/build/android/icons/joystick_bg.svg +++ /dev/null @@ -1,876 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/joystick_center.svg b/build/android/icons/joystick_center.svg deleted file mode 100644 index 17202290a..000000000 --- a/build/android/icons/joystick_center.svg +++ /dev/null @@ -1,877 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/joystick_off.svg b/build/android/icons/joystick_off.svg deleted file mode 100644 index 58e1acf22..000000000 --- a/build/android/icons/joystick_off.svg +++ /dev/null @@ -1,882 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/jump_btn.svg b/build/android/icons/jump_btn.svg deleted file mode 100644 index 882c49ed7..000000000 --- a/build/android/icons/jump_btn.svg +++ /dev/null @@ -1,547 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/minimap_btn.svg b/build/android/icons/minimap_btn.svg deleted file mode 100644 index deda32717..000000000 --- a/build/android/icons/minimap_btn.svg +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - diff --git a/build/android/icons/rangeview_btn.svg b/build/android/icons/rangeview_btn.svg deleted file mode 100644 index f9319e0b5..000000000 --- a/build/android/icons/rangeview_btn.svg +++ /dev/null @@ -1,456 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index 6e59e2b40..e326d5b91 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -2,6 +2,7 @@ Copyright (C) 2014 sapier Copyright (C) 2018 srifqi, Muhammad Rifqi Priyo Susanto +Copyright (C) 2014-2020 Maksim Gamarnik [MoNTE48] MoNTE48@mail.ua This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -38,9 +39,16 @@ using namespace irr::core; const char **button_imagenames = (const char *[]) { "jump_btn.png", - "down.png", - "zoom.png", - "aux_btn.png" + "drop_btn.png", + "down_btn.png", + //"zoom.png", + //"aux_btn.png", + "inventory_btn.png", + "escape_btn.png", + "minimap_btn.png", + "rangeview_btn.png", + "camera_btn.png", + "chat_btn.png" }; const char **joystick_imagenames = (const char *[]) { @@ -77,12 +85,12 @@ static irr::EKEY_CODE id2keycode(touch_gui_button_id id) case crunch_id: key = "sneak"; break; - case zoom_id: + /*case zoom_id: key = "zoom"; break; case special1_id: key = "special1"; - break; + break;*/ case fly_id: key = "freemove"; break; @@ -110,6 +118,8 @@ static irr::EKEY_CODE id2keycode(touch_gui_button_id id) case range_id: key = "rangeselect"; break; + case escape_id: + return irr::KEY_ESCAPE; default: break; } @@ -475,46 +485,62 @@ void TouchScreenGUI::init(ISimpleTextureSource *tsrc) */ if (m_fixed_joystick) { m_joystick_btn_off = initJoystickButton(joystick_off_id, - rect(button_size, - m_screensize.Y - button_size * 4, - button_size * 4, - m_screensize.Y - button_size), 0); + rect(button_size / 2, + m_screensize.Y - button_size * 4.5, + button_size * 4.5, + m_screensize.Y - button_size / 2), 0); } else { m_joystick_btn_off = initJoystickButton(joystick_off_id, - rect(button_size, - m_screensize.Y - button_size * 3, - button_size * 3, - m_screensize.Y - button_size), 0); + rect(button_size / 2, + m_screensize.Y - button_size * 3.5, + button_size * 3.5, + m_screensize.Y - button_size / 2), 0); } m_joystick_btn_bg = initJoystickButton(joystick_bg_id, - rect(button_size, - m_screensize.Y - button_size * 4, - button_size * 4, - m_screensize.Y - button_size), + rect(button_size / 2, + m_screensize.Y - button_size * 4.5, + button_size * 4.5, + m_screensize.Y - button_size / 2), 1, false); m_joystick_btn_center = initJoystickButton(joystick_center_id, - rect(0, 0, button_size, button_size), 2, false); + rect(0, 0, button_size * 1.5, button_size * 1.5), 2, false); // init jump button initButton(jump_id, - rect(m_screensize.X - (1.75 * button_size), - m_screensize.Y - button_size, - m_screensize.X - (0.25 * button_size), - m_screensize.Y), + rect(m_screensize.X - button_size * 3, + m_screensize.Y - button_size * 3, + m_screensize.X - button_size * 1.5, + m_screensize.Y - button_size * 1.5), L"x", false); + // init drop button + initButton(drop_id, + rect(m_screensize.X - button_size, + m_screensize.Y / 2 - button_size * 1.5, + m_screensize.X, + m_screensize.Y / 2 - button_size / 2), + L"drop", false); + // init crunch button initButton(crunch_id, - rect(m_screensize.X - (3.25 * button_size), - m_screensize.Y - button_size, - m_screensize.X - (1.75 * button_size), - m_screensize.Y), + rect(m_screensize.X - button_size * 3, + m_screensize.Y - button_size / 1.5, + m_screensize.X - button_size * 1.5, + m_screensize.Y), L"H", false); + // init inventory button + initButton(inventory_id, + rect(m_screensize.X - button_size * 1.5, + m_screensize.Y - button_size * 1.5, + m_screensize.X, + m_screensize.Y), + L"inv", false); + // init zoom button - initButton(zoom_id, +/* initButton(zoom_id, rect(m_screensize.X - (1.25 * button_size), m_screensize.Y - (4 * button_size), m_screensize.X - (0.25 * button_size), @@ -543,9 +569,6 @@ void TouchScreenGUI::init(ISimpleTextureSource *tsrc) m_settingsbar.addButton(noclip_id, L"noclip", "noclip_btn.png"); m_settingsbar.addButton(fast_id, L"fast", "fast_btn.png"); m_settingsbar.addButton(debug_id, L"debug", "debug_btn.png"); - m_settingsbar.addButton(camera_id, L"camera", "camera_btn.png"); - m_settingsbar.addButton(range_id, L"rangeview", "rangeview_btn.png"); - m_settingsbar.addButton(minimap_id, L"minimap", "minimap_btn.png"); // Chat is shown by default, so chat_hide_btn.png is shown first. m_settingsbar.addToggleButton(toggle_chat_id, L"togglechat", @@ -563,7 +586,60 @@ void TouchScreenGUI::init(ISimpleTextureSource *tsrc) m_rarecontrolsbar.addButton(chat_id, L"Chat", "chat_btn.png"); m_rarecontrolsbar.addButton(inventory_id, L"inv", "inventory_btn.png"); - m_rarecontrolsbar.addButton(drop_id, L"drop", "drop_btn.png"); + m_rarecontrolsbar.addButton(drop_id, L"drop", "drop_btn.png");*/ + + const bool minimap = g_settings->getBool("enable_minimap"); + + double button_075 = 1; + s32 button_05 = 1; + double button_05b = 0; + if (!minimap) { + button_075 = 0.75; + button_05 = 2; + button_05b = button_size * 0.5; + } + + // init pause button [1] + initButton(escape_id, + rect(m_screensize.X / 2 - button_size * 2 * button_075, + 0, + m_screensize.X / 2 - button_size / button_05, + button_size), + L"Exit", false); + + // init minimap button [2] + if (minimap) { + initButton(minimap_id, + rect(m_screensize.X / 2 - button_size, + 0, + m_screensize.X / 2, + button_size), + L"minimap", false); + } + + // init rangeselect button [3] + initButton(range_id, + rect(m_screensize.X / 2 - button_05b, + 0, + m_screensize.X / 2 + button_size / button_05, + button_size), + L"rangeview", false); + + // init camera button [4] + initButton(camera_id, + rect(m_screensize.X / 2 + button_size / button_05, + 0, + m_screensize.X / 2 + button_size * 2 * button_075, + button_size), + L"camera", false); + + // init chat button + initButton(chat_id, + rect(m_screensize.X - button_size * 1.25, + 0, + m_screensize.X, + button_size), + L"Chat", false); } touch_gui_button_id TouchScreenGUI::getButtonID(s32 x, s32 y) @@ -666,7 +742,6 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id) { touch_gui_button_id button = getButtonID(evt_id); - if (button != after_last_element_id) { // handle button events handleButtonEvent(button, evt_id, false); @@ -687,9 +762,24 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id) translated->MouseInput.Event = EMIE_LMOUSE_LEFT_UP; m_receiver->OnEvent(*translated); delete translated; - } else { - // do double tap detection - doubleTapDetection(); + } else if (!m_move_has_really_moved) { + auto *translated = new SEvent; + memset(translated, 0, sizeof(SEvent)); + translated->EventType = EET_MOUSE_INPUT_EVENT; + translated->MouseInput.X = m_move_downlocation.X; + translated->MouseInput.Y = m_move_downlocation.Y; + translated->MouseInput.Shift = false; + translated->MouseInput.Control = false; + translated->MouseInput.ButtonStates = 0; + translated->MouseInput.Event = EMIE_LMOUSE_LEFT_UP; + m_receiver->OnEvent(*translated); + delete translated; + quickTapDetection(); + m_shootline = m_device + ->getSceneManager() + ->getSceneCollisionManager() + ->getRayFromScreenCoordinates( + v2s32(m_move_downlocation.X, m_move_downlocation.Y)); } } @@ -720,6 +810,66 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id) } } +void TouchScreenGUI::moveJoystick(const SEvent &event, float dx, float dy) { + m_joystick_has_really_moved = true; + double distance = sqrt(dx * dx + dy * dy); + + // angle in degrees + double angle = acos(dx / distance) * 180 / M_PI; + if (dy < 0) + angle *= -1; + // rotate to make comparing easier + angle = fmod(angle + 180 + 22.5, 360); + + // reset state before applying + for (bool & joystick_status : m_joystick_status) + joystick_status = false; + + if (distance <= m_touchscreen_threshold) { + // do nothing + } else if (angle < 45) + m_joystick_status[j_left] = true; + else if (angle < 90) { + m_joystick_status[j_forward] = true; + m_joystick_status[j_left] = true; + } else if (angle < 135) + m_joystick_status[j_forward] = true; + else if (angle < 180) { + m_joystick_status[j_forward] = true; + m_joystick_status[j_right] = true; + } else if (angle < 225) + m_joystick_status[j_right] = true; + else if (angle < 270) { + m_joystick_status[j_backward] = true; + m_joystick_status[j_right] = true; + } else if (angle < 315) + m_joystick_status[j_backward] = true; + else if (angle <= 360) { + m_joystick_status[j_backward] = true; + m_joystick_status[j_left] = true; + } + + if (distance > button_size * 1.5) { + m_joystick_status[j_special1] = true; + // move joystick "button" + s32 ndx = button_size * dx / distance * 1.5f - button_size / 2.0f * 1.5f; + s32 ndy = button_size * dy / distance * 1.5f - button_size / 2.0f * 1.5f; + if (m_fixed_joystick) { + m_joystick_btn_center->guibutton->setRelativePosition(v2s32( + button_size * 5 / 2 + ndx, + m_screensize.Y - button_size * 5 / 2 + ndy)); + } else { + m_joystick_btn_center->guibutton->setRelativePosition(v2s32( + m_pointerpos[event.TouchInput.ID].X + ndx, + m_pointerpos[event.TouchInput.ID].Y + ndy)); + } + } else { + m_joystick_btn_center->guibutton->setRelativePosition(v2s32( + event.TouchInput.X - button_size / 2.0f * 1.5f, + event.TouchInput.Y - button_size / 2.0f * 1.5f)); + } +} + void TouchScreenGUI::translateEvent(const SEvent &event) { if (!m_visible) { @@ -752,22 +902,22 @@ void TouchScreenGUI::translateEvent(const SEvent &event) // handle button events if (button != after_last_element_id) { handleButtonEvent(button, eventID, true); - m_settingsbar.deactivate(); - m_rarecontrolsbar.deactivate(); + //m_settingsbar.deactivate(); + //m_rarecontrolsbar.deactivate(); } else if (isHUDButton(event)) { - m_settingsbar.deactivate(); - m_rarecontrolsbar.deactivate(); + //m_settingsbar.deactivate(); + //m_rarecontrolsbar.deactivate(); // already handled in isHUDButton() } else if (m_settingsbar.isButton(event)) { - m_rarecontrolsbar.deactivate(); + //m_rarecontrolsbar.deactivate(); // already handled in isSettingsBarButton() } else if (m_rarecontrolsbar.isButton(event)) { - m_settingsbar.deactivate(); + //m_settingsbar.deactivate(); // already handled in isSettingsBarButton() } else { // handle non button events - m_settingsbar.deactivate(); - m_rarecontrolsbar.deactivate(); + //m_settingsbar.deactivate(); + //m_rarecontrolsbar.deactivate(); s32 dxj = event.TouchInput.X - button_size * 5.0f / 2.0f; s32 dyj = event.TouchInput.Y - m_screensize.Y + button_size * 5.0f / 2.0f; @@ -775,8 +925,11 @@ void TouchScreenGUI::translateEvent(const SEvent &event) /* Select joystick when left 1/3 of screen dragged or * when joystick tapped (fixed joystick position) */ - if ((m_fixed_joystick && dxj * dxj + dyj * dyj <= button_size * button_size * 1.5 * 1.5) || - (!m_fixed_joystick && event.TouchInput.X < m_screensize.X / 3.0f)) { + bool inside_joystick = + m_fixed_joystick + ? dxj * dxj + dyj * dyj <= button_size * button_size * 1.5 * 1.5 + : event.TouchInput.X < m_screensize.X / 3.0f; + if (inside_joystick) { // If we don't already have a starting point for joystick make this the one. if (m_joystick_id == -1) { m_joystick_id = event.TouchInput.ID; @@ -787,14 +940,16 @@ void TouchScreenGUI::translateEvent(const SEvent &event) m_joystick_btn_center->guibutton->setVisible(true); // If it's a fixed joystick, don't move the joystick "button". - if (!m_fixed_joystick) + if (m_fixed_joystick) { + moveJoystick(event, dxj, dyj); + } else { m_joystick_btn_bg->guibutton->setRelativePosition(v2s32( - event.TouchInput.X - button_size * 3.0f / 2.0f, - event.TouchInput.Y - button_size * 3.0f / 2.0f)); - - m_joystick_btn_center->guibutton->setRelativePosition(v2s32( - event.TouchInput.X - button_size / 2.0f, - event.TouchInput.Y - button_size / 2.0f)); + event.TouchInput.X - button_size * 3.0f / 1.5f, + event.TouchInput.Y - button_size * 3.0f / 1.5f)); + m_joystick_btn_center->guibutton->setRelativePosition(v2s32( + event.TouchInput.X - button_size / 2.0f * 1.5f, + event.TouchInput.Y - button_size / 2.0f * 1.5f)); + } } } else { // If we don't already have a moving point make this the moving one. @@ -842,7 +997,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) s32 dy = Y - m_pointerpos[event.TouchInput.ID].Y; // adapt to similar behaviour as pc screen - double d = g_settings->getFloat("mouse_sensitivity") * 3.0f; + double d = g_settings->getFloat("mouse_sensitivity"); m_camera_yaw_change -= dx * d; m_camera_pitch = MYMIN(MYMAX(m_camera_pitch + (dy * d), -180), 180); @@ -875,8 +1030,6 @@ void TouchScreenGUI::translateEvent(const SEvent &event) dy = Y - m_screensize.Y + button_size * 5 / 2; } - double distance_sq = dx * dx + dy * dy; - s32 dxj = event.TouchInput.X - button_size * 5.0f / 2.0f; s32 dyj = event.TouchInput.Y - m_screensize.Y + button_size * 5.0f / 2.0f; bool inside_joystick = (dxj * dxj + dyj * dyj <= button_size * button_size * 1.5 * 1.5); @@ -884,63 +1037,8 @@ void TouchScreenGUI::translateEvent(const SEvent &event) if (m_joystick_has_really_moved || (!m_joystick_has_really_moved && inside_joystick) || (!m_fixed_joystick && - distance_sq > m_touchscreen_threshold * m_touchscreen_threshold)) { - m_joystick_has_really_moved = true; - double distance = sqrt(distance_sq); - - // angle in degrees - double angle = acos(dx / distance) * 180 / M_PI; - if (dy < 0) - angle *= -1; - // rotate to make comparing easier - angle = fmod(angle + 180 + 22.5, 360); - - // reset state before applying - for (bool & joystick_status : m_joystick_status) - joystick_status = false; - - if (distance <= m_touchscreen_threshold) { - // do nothing - } else if (angle < 45) - m_joystick_status[j_left] = true; - else if (angle < 90) { - m_joystick_status[j_forward] = true; - m_joystick_status[j_left] = true; - } else if (angle < 135) - m_joystick_status[j_forward] = true; - else if (angle < 180) { - m_joystick_status[j_forward] = true; - m_joystick_status[j_right] = true; - } else if (angle < 225) - m_joystick_status[j_right] = true; - else if (angle < 270) { - m_joystick_status[j_backward] = true; - m_joystick_status[j_right] = true; - } else if (angle < 315) - m_joystick_status[j_backward] = true; - else if (angle <= 360) { - m_joystick_status[j_backward] = true; - m_joystick_status[j_left] = true; - } - - if (distance > button_size) { - m_joystick_status[j_special1] = true; - // move joystick "button" - s32 ndx = button_size * dx / distance - button_size / 2.0f; - s32 ndy = button_size * dy / distance - button_size / 2.0f; - if (m_fixed_joystick) { - m_joystick_btn_center->guibutton->setRelativePosition(v2s32( - button_size * 5 / 2 + ndx, - m_screensize.Y - button_size * 5 / 2 + ndy)); - } else { - m_joystick_btn_center->guibutton->setRelativePosition(v2s32( - m_pointerpos[event.TouchInput.ID].X + ndx, - m_pointerpos[event.TouchInput.ID].Y + ndy)); - } - } else { - m_joystick_btn_center->guibutton->setRelativePosition( - v2s32(X - button_size / 2, Y - button_size / 2)); - } + dx * dx + dy * dy > m_touchscreen_threshold * m_touchscreen_threshold)) { + moveJoystick(event, dx, dy); } } @@ -988,26 +1086,16 @@ void TouchScreenGUI::handleChangedButton(const SEvent &event) event.TouchInput.ID, true); } -bool TouchScreenGUI::doubleTapDetection() +// Punch or left click +bool TouchScreenGUI::quickTapDetection() { m_key_events[0].down_time = m_key_events[1].down_time; m_key_events[0].x = m_key_events[1].x; m_key_events[0].y = m_key_events[1].y; - m_key_events[1].down_time = m_move_downtime; - m_key_events[1].x = m_move_downlocation.X; - m_key_events[1].y = m_move_downlocation.Y; - u64 delta = porting::getDeltaMs(m_key_events[0].down_time, porting::getTimeMs()); - if (delta > 400) - return false; - - double distance = sqrt( - (m_key_events[0].x - m_key_events[1].x) * - (m_key_events[0].x - m_key_events[1].x) + - (m_key_events[0].y - m_key_events[1].y) * - (m_key_events[0].y - m_key_events[1].y)); - - if (distance > (20 + m_touchscreen_threshold)) + // ignore the occasional touch + u64 delta = porting::getDeltaMs(m_move_downtime, porting::getTimeMs()); + if (delta < 50) return false; auto *translated = new SEvent(); @@ -1088,10 +1176,6 @@ void TouchScreenGUI::step(float dtime) if (!button.ids.empty()) { button.repeatcounter += dtime; - // in case we're moving around digging does not happen - if (m_move_id != -1) - m_move_has_really_moved = true; - if (button.repeatcounter < button.repeatdelay) continue; @@ -1120,7 +1204,6 @@ void TouchScreenGUI::step(float dtime) if ((m_move_id != -1) && (!m_move_has_really_moved) && (!m_move_sent_as_mouse_event)) { - u64 delta = porting::getDeltaMs(m_move_downtime, porting::getTimeMs()); if (delta > MIN_DIG_TIME_MS) { @@ -1128,7 +1211,7 @@ void TouchScreenGUI::step(float dtime) ->getSceneManager() ->getSceneCollisionManager() ->getRayFromScreenCoordinates( - v2s32(m_move_downlocation.X,m_move_downlocation.Y)); + v2s32(m_move_downlocation.X, m_move_downlocation.Y)); SEvent translated; memset(&translated, 0, sizeof(SEvent)); @@ -1145,8 +1228,8 @@ void TouchScreenGUI::step(float dtime) } } - m_settingsbar.step(dtime); - m_rarecontrolsbar.step(dtime); + //m_settingsbar.step(dtime); + //m_rarecontrolsbar.step(dtime); } void TouchScreenGUI::resetHud() @@ -1175,11 +1258,11 @@ void TouchScreenGUI::Toggle(bool visible) while (!m_known_ids.empty()) handleReleaseEvent(m_known_ids.begin()->id); - m_settingsbar.hide(); - m_rarecontrolsbar.hide(); + //m_settingsbar.hide(); + //m_rarecontrolsbar.hide(); } else { - m_settingsbar.show(); - m_rarecontrolsbar.show(); + //m_settingsbar.show(); + //m_rarecontrolsbar.show(); } } @@ -1201,9 +1284,8 @@ void TouchScreenGUI::show() void TouchScreenGUI::handleReleaseAll() { - m_known_ids.clear(); - if (m_move_id != -1) - handleReleaseEvent(m_move_id); - for (auto & m_button : m_buttons) - m_button.ids.clear(); + while (!m_known_ids.empty()) + handleReleaseEvent(m_known_ids.back().id); + for (auto &button : m_buttons) + button.ids.clear(); // should do nothing } diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index 27929bcc5..ea079ba7e 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -1,5 +1,6 @@ /* Copyright (C) 2014 sapier +Copyright (C) 2014-2020 Maksim Gamarnik [MoNTE48] MoNTE48@mail.ua This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -36,23 +37,24 @@ using namespace irr::gui; typedef enum { jump_id = 0, + drop_id, crunch_id, - zoom_id, - special1_id, + inventory_id, + // zoom_id, + // special1_id, + escape_id, + minimap_id, + range_id, + camera_id, + chat_id, after_last_element_id, - settings_starter_id, - rare_controls_starter_id, + // settings_starter_id, + // rare_controls_starter_id, fly_id, noclip_id, fast_id, debug_id, - camera_id, - range_id, - minimap_id, toggle_chat_id, - chat_id, - inventory_id, - drop_id, forward_id, backward_id, left_id, @@ -219,7 +221,7 @@ private: // forward, backward, left, right touch_gui_button_id m_joystick_names[5] = { - forward_id, backward_id, left_id, right_id, special1_id}; + forward_id, backward_id, left_id, right_id, /*special1_id*/}; bool m_joystick_status[5] = {false, false, false, false, false}; /* @@ -230,13 +232,13 @@ private: */ line3d m_shootline; - int m_move_id = -1; + size_t m_move_id = -1; bool m_move_has_really_moved = false; u64 m_move_downtime = 0; bool m_move_sent_as_mouse_event = false; v2s32 m_move_downlocation = v2s32(-10000, -10000); - int m_joystick_id = -1; + size_t m_joystick_id = -1; bool m_joystick_has_really_moved = false; bool m_fixed_joystick = false; bool m_joystick_triggers_special1 = false; @@ -258,13 +260,15 @@ private: // initialize a button void initButton(touch_gui_button_id id, const rect &button_rect, const std::wstring &caption, bool immediate_release, - float repeat_delay = BUTTON_REPEAT_DELAY); + float repeat_delay = SLOW_BUTTON_REPEAT); // initialize a joystick button button_info *initJoystickButton(touch_gui_button_id id, const rect &button_rect, int texture_id, bool visible = true); + void moveJoystick(const SEvent &event, float dx, float dy); + struct id_status { size_t id; @@ -281,8 +285,8 @@ private: // handle pressed hud buttons bool isHUDButton(const SEvent &event); - // handle double taps - bool doubleTapDetection(); + // handle quick taps + bool quickTapDetection(); // handle release event void handleReleaseEvent(size_t evt_id); @@ -290,7 +294,7 @@ private: // apply joystick status void applyJoystickStatus(); - // double-click detection variables + // long-click detection variables struct key_event { u64 down_time; @@ -301,7 +305,7 @@ private: // array for saving last known position of a pointer std::map m_pointerpos; - // array for double tap detection + // array for long-click detection key_event m_key_events[2]; // settings bar diff --git a/textures/base/pack/camera_btn.png b/textures/base/pack/camera_btn.png index 9327dc4a679e88a7cf15880fc926dda25a4e19a0..82beaa791df9e891754e26784e410b789f2d34b0 100644 GIT binary patch literal 332 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e#Q>iWS6yQ*TU%Rsd3m6~axh3q zNdbyPm zzOykXoL|N}PwHOsFNQ-pv-q6E9VWQ=3$^eSs5hSJVDacqe!$ltd6b7i>^Q@vHZyx~t$KdJe=d#Wzp$Pz$^nyVE literal 1859 zcmZ{ljXM*F1IIUcH#4)%)XMu?MpNg>%V?OFt%YsG+zH!ooXh)5bZE3i!(uVXZea~k zUdjo-%iCrs^sYNa=B2L4=q}3L{qzUi^L)PF@AG{Afp2k8fS<1RUTpvXpiA(_Q+BuD zYcy4NJN{@hZg*7Dya>UXnj!Cfze=rSe_9#^j> zkd>9?5P$lIG)8oCj6+gtT_vM$}VFF9i=sL}u8?)~qlbV0G-7}Ut|zmEBD^aO++ z?ZuREvV~6Xhu2`=o;mNrl^pYou$PN@hPH}@tM&Zt*%KNOci%_@U-%bY-{Lx9iN+B$ zP0ST|QP0^-$J(`CD1_;nOW=f89l^Ejo16EpaFePpr|J#&)C4deUpft9!l+>bIc1gK z@#*R}GV1N57M~2)rq!m4<6H=bqY)Kt&)AMAvxgqzP1MQn#TUx@aYzOF=P0UF_0ECY zOKSBaCGA(vzN(+3|Ms>X!yX`k(J1OA0~79)XMZZNz>p5n_rs6)8*bc)rF2PaQhMZY1m%LG< zmMUBlc>Wi5;!}pDucJ}IVK!B#2-%dw+;q*eej{1-)jPQUt#8#IDb_Nr-WKx5rB8`; zw|s@uM!du#dv8PV%B8`|t;=b3R}5Cq7~hkOO`qY@vGo=`buWXdE8l!M!_G`leVz

I2q=#=03=IdiSIP zF|54;BHY8}!B<^CMQ^Sn(SruBZzO<0)WKvI*7 zS<0QtZsO6-ZRAwuO)_Y0Agm3hJkZfyVXDK9ZY867+x4cf;(ZfJ)V1n`bses;tq

q!N zsg_#+p%L}pUC83)bXdt zsP!M`CyL@B3nyv3!j4l2EJ;K9+Q-Wx+)l@r0UKih+>{`y>pD~zIZ?9D@fBY!Cb6+$ z(!6jRH5^-uMzWO^tu_N)q_;Rn;kC{MD=w6_4%9y=IG*qNuvDcx1=_d2bKVX)5hHEO zF1ZXQ4R;YwF49{o)hvBv)P$2fC2wJEJffciW#crTGPz{cuigvn=h_ zqlw>BH81cU(B|`RSE~IuL$WV* z8)woSH59heXf2_^$KcOOlRQ0Ju$`mTSjk_BuR)o9HI{aVZHAE|kp_0<^I#6%puC_vEZxp(+ettJZsr8IQkVA*W;JV$_dCK|C!7KVkkk5wwzW z>`rz7PqHkHC|bvF!#$sx%QcXj8Aj8E=E&_9KlQHSd95S956YX1l)1I%4V?jUoAm(11Q^+SQe-E3=>81?EQ^>xiH3_Slys4j?mQq{9f)v&CC6nr!L<)NcFL>RICWbQ&iHUVQK#}F1E{-7;x89y=WId9=ct!7cLFWP5f@uHc1f9~emm8BIeCYvwKh~#ctBWv6ANTspvnMm83#4oMy zwzJH2xS{Hp{=sTVHp|tOZw?11Y+;K3;gs@_O+Yh`W#R=50iN$NY^vq%_jt@2G@rb! zVbk?){KnGdbD_#$N#~a*zYIbq?Y`3Fkr6A;wzm1(!}AM@H58u*Je67XM|?@@55`$b V4oM0+Y2||avd$@?2>{qRYApZ& literal 873 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2_SGreY`05Dt#eH*O$7&H|6fVg?50 zjUdeUwfU_lP*AeOHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXpfN8zT^vIy zZoQpj?=dw{qTPR1TZBZDgo*@*tJxNgtt?MPTJjnnw6-l+D7D(tDKm>xF)OR9BdSSb zdYhB>B890ZHZ3^gBG7W;U-qlZYTy4}TKMo!=jZBo75abfeJ-%PU;eKA{&h>m76B&? z81bL&F3%^u57`smg-pBetWy;f@y|1Fw`!P1@`czUFE9h6Jyf zJlh!kX5C@6O48XscmA>-Z^z5}Gu~A4wZ;95+c!&SU67zjy==J8zw&RbJ@?P53)gpl zJ-EMd>Ky~qnq|5nU&_*azSx?%+-zR8Bm32i)bNfQV#|ErC}%B>ZOy7k$eNkh{{F<; zJ?0brZ;E`iTQaSE*}Q&}-#yt6rgm04)_$?RXf<#4tb3b|#$Q>{DYe|NbF+u?<7Mjt zU;SbEI(r7^tVx!=W`>DbufGc$$A}sFdIzx=?Kb8A%_$kpIb*Tu&ig7+Gox4LpV{7E zI9=i1>&Xn96G%iS+z-sY!+PMS3@gt}d*yFW)fa@kxaR4_7@FE^vhSP5ub@x|*6XKU zRlU^L2xN^h3BCJGa_WL6C*S=y9-FV*zChuVXrpke-J!$(l!b#FPJUUZS8U>wqr~;% zN%@kvMEO>r^ece_m7EBuDAU5?sb2t$cD+0pJ%>KtPVe{CGksp z`%KNxos6rJ-X7Y^$Rd)LoB3dC<$upT&(0d$XHsscayzqIIj65yJ?xW_OKP1dkIyNfM37Z?~nn^63dD`LUroi(gSW=l_PX;`|o?^q>AhqZ<7 zu7=b;>*<>tF6)_}*?huS&;Har*LkItPMrr^+Lm*{5*#q;9r=G={+E?h&@w@WiNK7( N;OXk;vd$@?2>{tKc_sh= diff --git a/textures/base/pack/down.png b/textures/base/pack/down.png deleted file mode 100644 index c290d3a453d28d394d9798f803b22caca57e48c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1690 zcmbV`X;{(=7RLW_amgk1W`oOh8S7R$YFe24l!+FWs31`)1{G*$)y#$#1*oXNrALh$_pXWU9d4K0T=Q%e+P)7`O z&2<3)FhCwfpaDQ*v(*4}pqr*nC&)Gpl5`jurlW(M3-|`NP>-HU0s!qZ-%7(h?ZMb4 zG^6>Sq+t@y)9A#DB!Et*J6(v6O*%`YlAIDQMswue<^Z5&hD7*=rHsnPkrXV+^yMGJ z=n4V)pN;OsT9-3%E-3dfOeZ`yQ8(aw*Y3NToE)r>Wgu;&=tK+^5^DXqTAz%VrWI8$ z0%xKB*w*LYnR_zjeGD{vVo_bPQk?L0quF(;XfdN@vFJ<2d=nPC`P82gBM_b0JoNl@ z-BmpKRpnBWAnM-X^<9FfB)qWQUmP~ELrhMzU=Ydj2Sk=Ep>o2COouVBVPk$Z?=>GD z68MBsVGP&J7^?$l*Z@!lU<5!80ScXt!fAzMDxp^dFdutQSFLmZJNlo!{}(>&1I|8q z8M@{(ZfFxX;5~}@I4bH7C>3VOMrz^J*9+Q1OPAYrQv+kM$7<|DRN=K?zI8eT2YXlI zUX~4a5VQ9V9sQYKpGaC{sKEI$ww1-o3pY?CE9P|YHUz!a+Ma|NBLq5AmWc7SL ze}H0OYB*13dt@#r$FMHg#&G+3=WXWSjO6%vmt9A3D}Kb2R5J~~Jf4(JI6H-w<7j`) za~-C&MZrPZt-dc}2F^4dU7neiHEqscVq9?!`$AWFw#xTje8ZZx6fc6Oo}{onhhsa! zx*LQ*i^bcKm5XI#}Mh{3<0VJ>c%^daUmegYBa=96z5F32&O$~bMqOQITkHA1o8~52C}SjKhh+#nwVkX%<9h3$uh}tRmv&Y zi~O&X$73TF{U_JGf@Ujka90pR+tWlVU>s}&ao^J9*(EHq@?gXouVx|+-k`-+O%Rd%ZX`C%Ns%YNz2>z*@gXhSr(jr!q&}F`b7UMpKRPmIi!oj}R(Bi!<|FbLC3uP~n;itZiNgjvS3t`-50qQ? zQayJfet{bDF!+q)9gh#C*%nlm_0Kzq83>+YdzU}j1J98)~tyg*7`d+K$WZBlgJbP?+j?q)$K#z{->o{<{(5;1nJp26E z2{&}3BgRm2rMw67!)JY4h&plb{ed91TkCC}Q0jV15iSgx?};9Rk4@lBQg4=KZu?Qc zZGru0-!a+8-%Yp)b$$ek5*j?ddm+}!xZ!rN;fdtSo&%wMHnxPT*Zy@k*V2!rRzR5E zehqI|bqjjypQUQvwl=O3N%}Y}!jcI@QXi@(X*y?bO#Q0Fzn(7G5|t%&hNyAX_XX=O zYp5ApeX~#VC|AtX@liR&IOtqDwa#v7QhqLfKhsG0d(9*I#|Q0%HqeJ=v!MgO@K%X! z7;iMh=_$z$>G^|Oe9wFRA;aiW78d>ni5rcQJD|2C1+F@j+%VpgWFGAH!mGLvr9=7h z6f<-1*PCooB>7WiV(U*G`nwdDT)0Jv*@RR(F>iXYz&n8S{3hel;P9QC;~V1#1Zc3q zmSE{d%HRLVD6-P9Cw{}~#=&l8?~YBFr^1gr|HLVw*ezY*!;V11m6!i5o9x~b9m&dS z)R053w%QaMopif1ht>vj_d`0ng3LZM{|+5oL*YKP6YmE?%~ey#u?>B0ku>W=yO_tk zxC?gefWdleIw3HV%(b=4A(S+OmK`FO?|?rig%TEX>V`#XDn$A10MZ|Ys5?x!{vX=2 B{#XD2 diff --git a/textures/base/pack/down_btn.png b/textures/base/pack/down_btn.png new file mode 100644 index 0000000000000000000000000000000000000000..208b7d16d534b0b3d6f625fde31ce1cb3ce3b711 GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQgQ)4A+G=b|Cg7S*EQB!zI?f@ ztu0U(4uDcjXXV6!e2$VJzhH)SGtM+^p4qVB!t*ykv8kRejv*CsYtK6JG8^)^TnsW` z4F)0&)?f}Gy4_c{ZQ80Bx7FuPUaSv_`#)RuGUH}>=8KI#?@hGt-aFTc^{!xY!6RL! zZ#{M9yxQ|7idY>GSl6{#u3?o^!rCbR15q4nW-#d)E?_hWE8z?fVDV7ipw!NCDWAb6 zZ57KWZihVMtF8y;@i`jrKYic=qnl57qp#(%Mt&acn+KTQdAor;;pyt|+c BTh{;p literal 0 HcmV?d00001 diff --git a/textures/base/pack/drop_btn.png b/textures/base/pack/drop_btn.png index 4403ce67b8e2aa2f6505f45d26f427ac720ea793..e3dd57461b2f8317b488ce9e68468099837cfeed 100644 GIT binary patch literal 543 zcmV+)0^t3LP)CdF!ovCa`S9@Y7Gia00000AbW%=J0ROK4nC61a zv&_R_Z-@W@0ia1lK~#9!#nyp}q%aUgQAr9fr9uzzFXUX@M+R z7A<*ey56GPNC4K98SDPAmyrVbo{IJNb!2};MM4f}uXX!dPl$be+*{-hVV!+_-1EdC zBrs>61MCGzV9vfi?ALeZ5QYDVc?z)K&+IsX{i zBRznCQULDHrT`M~v_Fmj3WgnrgfSpi02DwZA_rKL-vJr|n3KEN4WI<*>>~>!0Cx$L z9KgQ?83&C5?gB^;T5AIU@#?BXjRpY>#XJSH4?ul=#q{-hH8ln(tv>;%{3u{H128nR z8NhwR`1}=$V@v=ghzUT#1Q1OC2=jo1&1?{m0Pr^WNleB#pw2I296;EL{`fNf57Z98 zlD4lYzmlggafIU~)wB(w{9wIBd>MkQe0OaMw1V9MOtguW9 hzY8GzDu6Hz`~kE^I37emdi?+Z002ovPDHLkV1l*t>lpw5 literal 1269 zcmVMzCV_|S* zE^l&Yo9;Xs000DZNkl1dQGG>}wC;kLAtEKBa6+$dT?WH;JkCu$0GHFsSKQ``CU zFzf6&=iZt98{T`)?{l7Z*}1dd&%Nj0?_AFl1VIo4K@bE%5ClOG1VNY;tRYQ5{iIpr zV)Ps;IY%`3q8BJQqJfnp`ANI$!*p?!L!99^O~bDoVJ$KHqbHSSr-o@ow^IYFX*T+L zo^}qGjjp!Cw39c+hGterDgHX;-=9hJN*W5Ri;jSda`*CNXB_@^%aT{Fl!=ajUFiHp zC+QhQPji+r<0`wNBcK7m2v8u;DN<8LPw_rO+6VyG0BDGsfDF%&Wkic|ll}_h!5e(b zKSuO-d4$HO3WyUYPCZ|8LyI-S84eit{WO;hRh?|5hH9##E+9^v4eVz?d$7mJae^dC z-lm^hT4xz#4@;;nH46k3+ZI0HPwhTm=eqXuMc!nY65TQZ#r6VU8C{~NqK!v=(XA8^ zC(e2f@bg5MC@{#5iQevvfMV+cptVAD%LQ}-&>{jvfC$iAJ-wW#mv&C`4zF_3Edlie zGt4Kv#Ht9CN9HKtYbtY*_jsJU+!avdcV1($TV24<-(*-~>mc|GmyLZwFxS}40(+;y zS{`B(rQJW zpDV?)?Pb63kfxyJ&I?$;KJ939jL+E3`e_TO;c4SUA;-S*%N=55H3d(EVbPf`-?TzoAUzkZm0=BabSTlr>Em@amIT!DET3wc`q;z$GyImc^7(JVxJ6n{N_)7+ zCT8(JwB9~MYIZAo?$uTW;e6SO7;8Ds)xa&yRgTZ?br=pRS342rf=LzIXjLBh8?>^G zsySbGDL0iNH_SC7&+|MMv6m4>*vq1MyJlPHJHh`fRjnqaTokZWnQJ;c7n#^M09qH|8*D}v4+(NJKN!RM165g=Va20=j(1VIo4K@bE% f5ClOG1i{aL0Y~DMOhWOm00000NkvXXu0mjf^{Fz> diff --git a/textures/base/pack/escape_btn.png b/textures/base/pack/escape_btn.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9d4669aa0ca12120f0947831de7f71b97d6f19 GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e#Q>iWS0F7fFRyE?Wov7@eED)9 z7XpCn|Ns93*}rNRgG4z?g8YIR*3D=-vw3F2x)~oQJpu|=dAc};RNQ)d%8~bg0Y~e@ zs1>X_XPCsY7J?Du)YG3%_3B)REqf6Ak7ZwwR;>PNz74E`vdkQRW)`|9Gt>)S+ttW* zCtCR0yvBQs7laMWBshgsesC(VdP}qQM>JVWu?qZNH&>4#QJ*2lFqUD_BwKlgjp1`1 a{4O%jmhHS1zwcNi$hDrXelF{r5}E*x)=~NZ literal 0 HcmV?d00001 diff --git a/textures/base/pack/fly_btn.png b/textures/base/pack/fly_btn.png deleted file mode 100644 index 641d0fa6eb43fc35c40c87c4dfd73aa67d5aad5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1559 zcmV+y2I%>TP)MzCV_|S* zE^l&Yo9;Xs000G+Nkls(-+{E#v;g~rXSzb2e7({t|nxo_`#KZAw@Gi9T|CH277@^N#a420glG97pQJ|94OK)L zkG=ecRa{HCrVAe7y@;@r5Vx^Fg^nfsf8OO8*6<0cRjAm_nQ?#)nyIBig@rG3W)0It zh(<0aph7?;{bU#AHU7Xs#-o=ot<-al@*C@Mj+5RH>-Z22gyWtHrk!qLH#^V5CTB)a6 z`G8e8zmr(O2{PMHGv)H&5*i87$q>0aNjL2@vxE{&9jZA&!Z33suI4SW>7j|BQZSoZ znrWw-@#v?M5RF`{sX#lWkgXyjr|2KL}A)oCo}7+w+lY+;FVKqbq#o6Yo+yBO;! z(M01LIFD%*i|EGdIEP3Tql1OY8T0rIYuU~qxoFfx<6I&nM5xgyDtQ905q{56Qbp-t zzQ%=87IP;X*+Y!<9@fO;ah%mkLVy-d;`IbS<~XT_SjQZ_2UK$tUHEI(#A6xG8ybTf zIgHmUe3&*Oq#B@&Dvb-X`6_SXZ#%Oz@d)sDoLY^+g}j7UAD`kP)^U88h z0-8L`VVHzL-X|Y4 zF@#r`YKd#vik}{u2+9|=go)v2hz>rY$;Xp8Uy(0rIe^z*u239x?849MG{}Q88h8#AI3(V0eRPZ(4CRb55bG`Bd7cfFXKb6XW zt9c8r{amBdIE(LblxzlhgoVl{JdJaQGNOj(@rv+8jp7`B!U@uOhaYgB@(uMkUCM$W zt;FzJN4Z9EJ`Xd@SbJz5SN`B166w6G zIDU%rSrrBr5F_CTGv$M7TIeN{L4p#mkPxLtg@Ua(D>Mf4d4PWW4dA?=xx`3#QH6ug z;cQb97SqlMexih_V>QllZpXPtg@bb5#kovzlu*wW{6*QsWs2hloV$4p=VK})ti`#X z3L1HXOrD}taa@42iFZioqfCW_4-g~a7zfF26D5k{C<(`Lo>ZY>8=3u)yBHwZ1_Ba0 z@N4J%0}N|@^uM;#H8Js|Nb{LELOVJ1gN)yG=qX%x3ILb5e{om78QA>!wF?c*-0 zGzKe)lI)kH3aJpWkbjf#7d}s!d~qkqVx+oRg^45ltIZ>x#{ zKO>!QsTdI8QT$z{;y{q!lB$=0iUk!s$5&%%m%a<<)3NE~R><~~5dr6RAFvGeTP0!Ap=~!lz0~DI<>Eakt!I-qbk|9K!U5tmp zQNT5OhFBf<8M}I?$w1edb+X*Lbes_2f!#~61 zfUba<#WfbYHLT};TPvLGGi$h}XIag=MQ*+NEr#m1v0Y{kZ)2CfuyqKXn#-Wf=`MYs zL3S_mq33`3K!&9=*s#2xCn;MX^u>WI>cQh@4>%cQm6IE4UMmBg$KdJe=d#Wzp$Pzk C?O@aZ literal 331 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H0wgodS2_SGreY`05Dt#eH*O$7&H|6fVg?50 zjUdeUwfU_lP*AeOHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXprTWrE{-7; zx8B~^$lGGT<8blJl)tZ2xK{NzCWhh e%LjJYpChbF7Z$W+)cSq{@jYGrT-G@yGywqKG;VDG diff --git a/textures/base/pack/joystick_bg.png b/textures/base/pack/joystick_bg.png index 406193998ec07b38d6cc9f55b00bffaacacead72..90f7a904888262946da895a0d1c3608b726335a7 100644 GIT binary patch literal 718 zcmV;<0x|uGP)hI1Z;u;#plvTqX$=7otuJpAAQS-W%P%2uGl2EwG$if>H1!`7cL6w` z@^Lt&TL9IJ^%sd-0A{;TN{*lh9_6(H<#H(eDR3;J;455KtRv~>@P?9 z7EM79u%84F5cB{yOo2pT&nkfZEl~o37GQsyK0y!g8I6ZCk^$^b6y(5~0{{TmEC3QG zggx%t#u*8Lj1~JMT(b-~pAZ7yoH~I0ubcC&bO{3BY(fCIw+_IBz-vDMu)I&u0Y)G? zn-(w`(DwJv1~0;20ll+vKn^5--@5~7022Z1j}s0Q3PS-j|I0uz|P1ST;4uZnyBvYWsJ%xq`?sQ)7Yz99f`Usp2)u;c@P zyB|;K2ms#HKNunKEZ`d8t+3Z0{ThHX!V&j=0chSf>Hyn|kCdzNr~T>yvszi)7uK_1 z1}s+joW|=3EHa?xym2p2{URX$6PpuK0u=K4rNHtHV9^2;viem3XOt+coRAQ(1OVWK z6hOY<4)#lc{53ncVmj4U(ekE`&0D*o1a4z_^1^VRxg}{L~DG(Qcr+zIEKllmv_TZ-&h#$UXJ?A3; zhCN|D`YHF(ZyFf=wujMg+!*}UlX>&Z0Js1A1FWRC_e|a`{Qv*}07*qoM6N<$f|`~n AjQ{`u literal 12481 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 diff --git a/textures/base/pack/joystick_center.png b/textures/base/pack/joystick_center.png index 1e4754d2491299095c20a00f4d12167d6f87ab48..9562687585cd5712d15fb149b85f4b963667e3db 100644 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|exd5LK*Z=?jFJ8QO^5n_8cJ0c| z&HeNDe|dR%LqkJnXJ>3|EYGJLZ=g!Xk|4ie28U-i(tw;Do-U3d6^w6BIZixcz~gdp zp#s+;AQIqObV0;LF{k{J=R`xWzMsQmQsL_cmhd}T6~CD!zeU@8QQ(LH`hmgI)z4*}Q$iB}PIP%? literal 2574 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 literal 14363 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 E0n`C2NdN!< diff --git a/textures/base/pack/jump_btn.png b/textures/base/pack/jump_btn.png index d21b4a9f8623197e0af9fd2601cdf7cb31a545a3..a91250f8c7e476506314968df38157fb4d8f25ad 100644 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|ei2$DvS9vhdHP*7VwOzDqZB=8} z|Ns9dO`k8na9S5o4Qok|UogYE8BJ%{cYK`-6xizN;uum9cl7E-&Lajq%om~^wJTbq z6}3xR*If8|p6}3%nwu{ke+ga0zAV?n&NSiGEd~aIwlt1Ke~l8CF(k}plVB{^SNTbh zxgn-|i5vHZ^u2x_8n+IddHwuI=S_x`{qudg*mnGm{=)eCy0am3TWMC?B2FfuJu{6K zGrwwis%h-jVB5;@?H}`n`%eES{kngpJY;5|`P*-GY)%Gmc0Uj+zt8ZAbMgG5U!JSy lfBV(D_RL^mDQ1lD znI;}E1s^4%a?mzY!-|uDVL5f?6AiIMTof|Es+evhQ={B2f z005XG1L2_nV6agd09&_gK$97#+`y(3Uu5{!t(Z56Poi;BU}Opa82$7q4UUq_MmI$3 zRR4(7FygsXQhf4RfJ7p>;x6G+&cr93btNXBuULZG0Dz$j5`HZF$}8nqbfP83cHr%c zP+opqtIK$c@AeUsenAAvO6u4jZTEc$6RNq&$YpoCy45w${JIsvo*yj40gZ z)Y`RbSipC3^6x8%(5@WAZ+WtmLrND{9$C@7!IMa{dc7)j_UZfTdkvd54*Q(=TitfD zYC+};D(Rbc8@|c<1{r1}2?gEas!4cX{pt;J{_!7g^}vep5I@iA`8ppRf6=*0+_41m z#i6sg$)0z8S>T!n`Qe_@30Btq5jLcj-ad_O4CoOpkX9AjYj59CyDO~e3;r?iX-Ubt z*D81La^RYU@Hs7(ZGdW|Tq_T->_zF*w1FW?tWnAKm9}PVPW`U+a5NbHJxA@1XB_P8 zwSnlyT)`H@Ns$=cI1z)v&|fTKdt>#Sfc(U*qUvS>YeGF5rBP+NN*7sciP#^^ zHC{UB)v|phVGHsy2O*KFP5od}s^Qa!(p4#ArlgvAiEcuD9 z>rXq7`Y7Fn@)wv^6EIgE((8_%KX%`O^lt9rLv^O@Fx^Tw?yRQ1rA(c=ZyBp?mOHSH ztn6i_R~VK1$XybgsMGSjL^7WYvHG^m}0co+ zUhJBM65tf^(HyMwuo>2rJlN(&Y&kj;^!No`GHCtSKk?TtOGz~)(@lK8MuRt2vTlFJ z4I;XqmZAI94ih#t*Cq`gk2F^HrAs-speK=BI}-)JNmNomt5a7^BTNP|$RIoe*(JMD z=EccvWBV{S+vBX~3wB>GG^6Kw%f3omi|&lv_3l|yy%FpZL;MKzaC9t$^wKjPw0|)r z4>D=Lu+%hU#(D1Z#C!-cqrAGTpNpj26e4LChXe;>n=5fr|JP@#G}(4#IMqHLI zVlLH+k{j8fWVNB`I~&!!3JEk4@#sL%8iMRwKNo;n{kU5xW!oMhC{@8^T|IuRPWNri z&Pk4_9q1=yF99d&;l-1tv-U}p3fP~Z<5mUCEOU;PH=&(NU&;R()R%jq$+TfCyyz9K z;Uyz7aL88bPZp0{BF9TA216U(J{s<}ToQ^1b!mrYpf?UOtR_nL^isPrxPukq2!1^^ z;kNaZC*jcgqo^2SlmOROY=5gZfXwSRE%D~0^YwQ%Hjs;K8)VG`=^NpWW@A}MY6|tR zBz7o2`oPVO%*Q;)y9n@{eaorL0(cfvQ1mi<`Ces(wW8R5f%ocEQcD)i?2Cs?%v2HO zZhDy6wm5;@-B}v4X$3rwH<(5iGyj>>efx7r=#=9+(-QasW^fYt|8O<2YbKvYpU%i( zU*G5PU*DlUFzSU&$GIi|vXfv&NWuax@KHY(*MV9@KL0%8uN?>ouCO#SAqdqpz+B{E zXz=mPv{&WNr@-LguNGd@=NtEr7#;td_q*YNIj(OqUCFap_>({TBFJBH+2n7HC|9>@6#1+WmDGBlmp3$`K*`b5aK0o`sj$tjs zvl5{A4Nn)xkczmsR|0vN6?u*)>YOK-78FD=YYJ{s+((HZmdq4viF@k zhf0lpOG}X4;ccD)Twm85%hFu1UFVvJ!qJ<;JZvKKg2W7turFrJ;C6VhH_&-9>wy=Z z!a59&>ph#J&N6*?E~9tJK~KqU>Lmq_DJ)lA1>%^}6dxVEeBcX@En~>aG>4c)#~W_> zJA4q!JRp0-^s+;fK?*O+$Hz81>_r*QHa~h435VwIsqaZkk@%&~0bJCARy8v>IEp&aRB+#kBoXM?e6j*rqqSvHLTYbFBrMKSwTe|W1*E8oT&(E2e_H0h~ z|NM1q=PKua|2fz4y=C#oe`i|+oH!I=1k2&7eJL}h&xrr*rJIvJ<#Ww}vz}T1r5?XY z$n0HZ@`)vK-MK4L$=WMZI3$)$NW50$9ICyfqWQ9j@yWcfivrslCN`{`t9sZrRN}YV zwGHi@hfZ8{F22OV;IpCq+^O~avME2BGoIW$IcW*!jAsU!&!$>Fs@Y}X@bgWwY4IdA zh6nj~%4+-AOM^`Ao> z8{W6iDff9}6e%~$a#JtQ;&WqGIRXnhIYX{HsxkBGJwJqDlZD5?txB6!IH>a|x{x=+6uX*Oo zGGnG;ze)St`t9GcWH2TmcD|9?gNe4JC<@W$vxgX z;q2FmK|sL;r+1duOXrGmXFN~c$9pp-{)FVONQvnUY-ZM%(Q+)1#XU6zOt+{W)@oSox{a>&ck@S$ARV)rp24q&A)oM zsUd2uVxV{M^(Nz2ItR}5sLgxM{hX<+Z~M$IcX!7B+;{d_`MuP_jI}#+o+Nl=on8GW zrkwHKm3OL#Tf3MiE?exMr}OyP>FF|?_c5J0vt#PJ2}|U^msaonW1{gcg?qo6PlNeZ z(S?Sdo2Q@pFMQydguooZ{XpN`coLKG`TphDxjtUEZivl@5?;>mKKG&PKF%38ShsCn zb873Xn`b^omVS#CdcbJ+g>|;fqt>XW&6f^nmHn3689PlRL-DX?QO+vowIY&!6CO{! jaoD^SDeEe&{KLL{MpU6sUzazq%wh0!^>bP0l+XkKy4w(v diff --git a/textures/base/pack/rangeview_btn.png b/textures/base/pack/rangeview_btn.png index e49a1b636e954ab350b30f292820ce02592ead26..0c1b9784046aaae393c7719560c514d595e65c00 100644 GIT binary patch literal 377 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