diff --git a/android/icons/gear_icon.svg b/android/icons/gear_icon.svg
deleted file mode 100644
index b44685ade..000000000
--- a/android/icons/gear_icon.svg
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
-
-
diff --git a/android/icons/rare_controls.svg b/android/icons/overflow_btn.svg
similarity index 90%
rename from android/icons/rare_controls.svg
rename to android/icons/overflow_btn.svg
index c9991ec7a..455dcc35a 100644
--- a/android/icons/rare_controls.svg
+++ b/android/icons/overflow_btn.svg
@@ -2,23 +2,23 @@
diff --git a/doc/texture_packs.md b/doc/texture_packs.md
index b6f9306d9..890f5a950 100644
--- a/doc/texture_packs.md
+++ b/doc/texture_packs.md
@@ -151,8 +151,7 @@ are placeholders intended to be overwritten by the game.
* `rangeview_btn.png`
* `debug_btn.png`
-* `gear_icon.png`
-* `rare_controls.png`
+* `overflow_btn.png`
* `exit_btn.png`
Texture Overrides
diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp
index b8c1143f2..7e6c486e0 100644
--- a/src/gui/guiKeyChangeMenu.cpp
+++ b/src/gui/guiKeyChangeMenu.cpp
@@ -377,6 +377,7 @@ void GUIKeyChangeMenu::add_key(int id, std::wstring button_name, const std::stri
key_settings.push_back(k);
}
+// compare with button_titles in touchscreengui.cpp
void GUIKeyChangeMenu::init_keys()
{
this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wstrgettext("Forward"), "keymap_forward");
diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp
index 2504c4eb5..c428ef52e 100644
--- a/src/gui/touchscreengui.cpp
+++ b/src/gui/touchscreengui.cpp
@@ -31,6 +31,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/keycode.h"
#include "client/renderingengine.h"
#include "util/numeric.h"
+#include "gettext.h"
+#include "IGUIStaticText.h"
+#include "IGUIFont.h"
#include
#include
@@ -43,8 +46,7 @@ static const char *button_image_names[] = {
"down.png",
"zoom.png",
"aux1_btn.png",
- "gear_icon.png",
- "rare_controls.png",
+ "overflow_btn.png",
"fly_btn.png",
"noclip_btn.png",
@@ -65,6 +67,33 @@ static const char *button_image_names[] = {
"joystick_center.png",
};
+// compare with GUIKeyChangeMenu::init_keys
+static const char *button_titles[] = {
+ N_("Jump"),
+ N_("Sneak"),
+ N_("Zoom"),
+ N_("Aux1"),
+ N_("Overflow menu"),
+
+ N_("Toggle fly"),
+ N_("Toggle noclip"),
+ N_("Toggle fast"),
+ N_("Toggle debug"),
+ N_("Change camera"),
+ N_("Range select"),
+ N_("Toggle minimap"),
+ N_("Toggle chat log"),
+
+ N_("Chat"),
+ N_("Inventory"),
+ N_("Drop"),
+ N_("Exit"),
+
+ N_("Joystick"),
+ N_("Joystick"),
+ N_("Joystick"),
+};
+
static void load_button_texture(IGUIImage *gui_button, const std::string &path,
const recti &button_rect, ISimpleTextureSource *tsrc, video::IVideoDriver *driver)
{
@@ -243,165 +272,6 @@ static EKEY_CODE id_to_keycode(touch_gui_button_id id)
return code;
}
-AutoHideButtonBar::AutoHideButtonBar(IrrlichtDevice *device, ISimpleTextureSource *tsrc,
- touch_gui_button_id starter_id, const std::string &starter_img,
- recti starter_rect, autohide_button_bar_dir dir) :
- m_driver(device->getVideoDriver()),
- m_guienv(device->getGUIEnvironment()),
- m_receiver(device->getEventReceiver()),
- m_texturesource(tsrc)
-{
- m_upper_left = starter_rect.UpperLeftCorner;
- m_lower_right = starter_rect.LowerRightCorner;
-
- IGUIImage *starter_gui_button = m_guienv->addImage(starter_rect, nullptr,
- starter_id);
- load_button_texture(starter_gui_button, starter_img, starter_rect,
- m_texturesource, m_driver);
-
- m_starter = grab_gui_element(starter_gui_button);
- m_dir = dir;
-}
-
-void AutoHideButtonBar::addButton(touch_gui_button_id id, const std::string &image)
-{
- int button_size = 0;
-
- if (m_dir == AHBB_Dir_Top_Bottom || m_dir == AHBB_Dir_Bottom_Top)
- button_size = m_lower_right.X - m_upper_left.X;
- else
- button_size = m_lower_right.Y - m_upper_left.Y;
-
- recti current_button;
-
- if (m_dir == AHBB_Dir_Right_Left || m_dir == AHBB_Dir_Left_Right) {
- int x_start = 0;
- int x_end = 0;
-
- if (m_dir == AHBB_Dir_Left_Right) {
- x_start = m_lower_right.X + button_size * 1.25f * m_buttons.size()
- + button_size * 0.25f;
- x_end = x_start + button_size;
- } else {
- x_end = m_upper_left.X - button_size * 1.25f * m_buttons.size()
- - button_size * 0.25f;
- x_start = x_end - button_size;
- }
-
- current_button = recti(x_start, m_upper_left.Y, x_end, m_lower_right.Y);
- } else {
- double y_start = 0;
- double y_end = 0;
-
- if (m_dir == AHBB_Dir_Top_Bottom) {
- y_start = m_lower_right.X + button_size * 1.25f * m_buttons.size()
- + button_size * 0.25f;
- y_end = y_start + button_size;
- } else {
- y_end = m_upper_left.X - button_size * 1.25f * m_buttons.size()
- - button_size * 0.25f;
- y_start = y_end - button_size;
- }
-
- current_button = recti(m_upper_left.X, y_start, m_lower_right.Y, y_end);
- }
-
- IGUIImage *btn_gui_button = m_guienv->addImage(current_button, nullptr, id);
- btn_gui_button->setVisible(false);
- btn_gui_button->setEnabled(false);
- load_button_texture(btn_gui_button, image, current_button, m_texturesource, m_driver);
-
- button_info btn{};
- btn.keycode = id_to_keycode(id);
- btn.gui_button = grab_gui_element(btn_gui_button);
- m_buttons.push_back(btn);
-}
-
-void AutoHideButtonBar::addToggleButton(touch_gui_button_id id,
- const std::string &image_1, const std::string &image_2)
-{
- addButton(id, image_1);
- button_info &btn = m_buttons.back();
- btn.toggleable = button_info::FIRST_TEXTURE;
- btn.toggle_textures[0] = image_1;
- btn.toggle_textures[1] = image_2;
-}
-
-bool AutoHideButtonBar::handlePress(size_t pointer_id, IGUIElement *element)
-{
- if (m_active) {
- return buttons_handlePress(m_buttons, pointer_id, element, m_driver,
- m_receiver, m_texturesource);
- }
- if (m_starter.get() == element) {
- activate();
- return true;
- }
- return false;
-}
-
-bool AutoHideButtonBar::handleRelease(size_t pointer_id)
-{
- return buttons_handleRelease(m_buttons, pointer_id, m_driver,
- m_receiver, m_texturesource);
-}
-
-void AutoHideButtonBar::step(float dtime)
-{
- // Since buttons can stay pressed after the buttonbar is deactivated,
- // we call the step function even if the buttonbar is inactive.
- bool has_pointers = buttons_step(m_buttons, dtime, m_driver, m_receiver,
- m_texturesource);
-
- if (m_active) {
- if (!has_pointers) {
- m_timeout += dtime;
- if (m_timeout > BUTTONBAR_HIDE_DELAY)
- deactivate();
- } else {
- m_timeout = 0.0f;
- }
- }
-
-}
-
-void AutoHideButtonBar::updateVisibility() {
- bool starter_visible = m_visible && !m_active;
- bool inner_visible = m_visible && m_active;
-
- m_starter->setVisible(starter_visible);
- m_starter->setEnabled(starter_visible);
-
- for (auto &button : m_buttons) {
- button.gui_button->setVisible(inner_visible);
- button.gui_button->setEnabled(inner_visible);
- }
-}
-
-void AutoHideButtonBar::activate()
-{
- m_active = true;
- m_timeout = 0.0f;
- updateVisibility();
-}
-
-void AutoHideButtonBar::deactivate()
-{
- m_active = false;
- updateVisibility();
-}
-
-void AutoHideButtonBar::show()
-{
- m_visible = true;
- updateVisibility();
-}
-
-void AutoHideButtonBar::hide()
-{
- m_visible = false;
- updateVisibility();
-}
TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, ISimpleTextureSource *tsrc):
m_device(device),
@@ -421,44 +291,44 @@ TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, ISimpleTextureSource *tsr
// Initialize joystick display "button".
// Joystick is placed on the bottom left of screen.
if (m_fixed_joystick) {
- m_joystick_btn_off = grab_gui_element(makeJoystickButton(joystick_off_id,
+ m_joystick_btn_off = grab_gui_element(makeButtonDirect(joystick_off_id,
recti(m_button_size,
m_screensize.Y - m_button_size * 4,
m_button_size * 4,
m_screensize.Y - m_button_size), true));
} else {
- m_joystick_btn_off = grab_gui_element(makeJoystickButton(joystick_off_id,
+ m_joystick_btn_off = grab_gui_element(makeButtonDirect(joystick_off_id,
recti(m_button_size,
m_screensize.Y - m_button_size * 3,
m_button_size * 3,
m_screensize.Y - m_button_size), true));
}
- m_joystick_btn_bg = grab_gui_element(makeJoystickButton(joystick_bg_id,
+ m_joystick_btn_bg = grab_gui_element(makeButtonDirect(joystick_bg_id,
recti(m_button_size,
m_screensize.Y - m_button_size * 4,
m_button_size * 4,
m_screensize.Y - m_button_size), false));
- m_joystick_btn_center = grab_gui_element(makeJoystickButton(joystick_center_id,
+ m_joystick_btn_center = grab_gui_element(makeButtonDirect(joystick_center_id,
recti(0, 0, m_button_size, m_button_size), false));
// init jump button
- addButton(jump_id, button_image_names[jump_id],
+ addButton(m_buttons, jump_id, button_image_names[jump_id],
recti(m_screensize.X - 1.75f * m_button_size,
m_screensize.Y - m_button_size,
m_screensize.X - 0.25f * m_button_size,
m_screensize.Y));
// init sneak button
- addButton(sneak_id, button_image_names[sneak_id],
+ addButton(m_buttons, sneak_id, button_image_names[sneak_id],
recti(m_screensize.X - 3.25f * m_button_size,
m_screensize.Y - m_button_size,
m_screensize.X - 1.75f * m_button_size,
m_screensize.Y));
// init zoom button
- addButton(zoom_id, button_image_names[zoom_id],
+ addButton(m_buttons, zoom_id, button_image_names[zoom_id],
recti(m_screensize.X - 1.25f * m_button_size,
m_screensize.Y - 4 * m_button_size,
m_screensize.X - 0.25f * m_button_size,
@@ -466,72 +336,112 @@ TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, ISimpleTextureSource *tsr
// init aux1 button
if (!m_joystick_triggers_aux1)
- addButton(aux1_id, button_image_names[aux1_id],
+ addButton(m_buttons, aux1_id, button_image_names[aux1_id],
recti(m_screensize.X - 1.25f * m_button_size,
m_screensize.Y - 2.5f * m_button_size,
m_screensize.X - 0.25f * m_button_size,
m_screensize.Y - 1.5f * m_button_size));
- AutoHideButtonBar &settings_bar = m_buttonbars.emplace_back(m_device, m_texturesource,
- settings_starter_id, button_image_names[settings_starter_id],
- recti(m_screensize.X - 1.25f * m_button_size,
- m_screensize.Y - (SETTINGS_BAR_Y_OFFSET + 1.0f) * m_button_size
- + 0.5f * m_button_size,
- m_screensize.X - 0.25f * m_button_size,
- m_screensize.Y - SETTINGS_BAR_Y_OFFSET * m_button_size
- + 0.5f * m_button_size),
- AHBB_Dir_Right_Left);
+ // init overflow button
+ m_overflow_btn = grab_gui_element(makeButtonDirect(overflow_id,
+ recti(m_screensize.X - 1.25f * m_button_size,
+ m_screensize.Y - 5.5f * m_button_size,
+ m_screensize.X - 0.25f * m_button_size,
+ m_screensize.Y - 4.5f * m_button_size), true));
- const static touch_gui_button_id settings_bar_buttons[] {
+ const static touch_gui_button_id overflow_buttons[] {
+ chat_id, inventory_id, drop_id, exit_id,
fly_id, noclip_id, fast_id, debug_id, camera_id, range_id, minimap_id,
+ toggle_chat_id,
};
- for (auto id : settings_bar_buttons) {
- if (id_to_keycode(id) == KEY_UNKNOWN)
- continue;
- settings_bar.addButton(id, button_image_names[id]);
+
+ IGUIStaticText *background = m_guienv->addStaticText(L"",
+ recti(v2s32(0, 0), dimension2du(m_screensize)));
+ background->setBackgroundColor(video::SColor(140, 0, 0, 0));
+ background->setVisible(false);
+ m_overflow_bg = grab_gui_element(background);
+
+ s32 cols = 4;
+ s32 rows = 3;
+ f32 screen_aspect = (f32)m_screensize.X / (f32)m_screensize.Y;
+ while ((s32)ARRLEN(overflow_buttons) > cols * rows) {
+ f32 aspect = (f32)cols / (f32)rows;
+ if (aspect > screen_aspect)
+ rows++;
+ else
+ cols++;
}
- // Chat is shown by default, so chat_hide_btn.png is shown first.
- settings_bar.addToggleButton(toggle_chat_id,
- "chat_hide_btn.png", "chat_show_btn.png");
+ v2s32 size(m_button_size, m_button_size);
+ v2s32 spacing(m_screensize.X / (cols + 1), m_screensize.Y / (rows + 1));
+ v2s32 pos(spacing);
- AutoHideButtonBar &rare_controls_bar = m_buttonbars.emplace_back(m_device, m_texturesource,
- rare_controls_starter_id, button_image_names[rare_controls_starter_id],
- recti(0.25f * m_button_size,
- m_screensize.Y - (RARE_CONTROLS_BAR_Y_OFFSET + 1.0f) * m_button_size
- + 0.5f * m_button_size,
- 0.75f * m_button_size,
- m_screensize.Y - RARE_CONTROLS_BAR_Y_OFFSET * m_button_size
- + 0.5f * m_button_size),
- AHBB_Dir_Left_Right);
-
- const static touch_gui_button_id rare_controls_bar_buttons[] {
- chat_id, inventory_id, drop_id, exit_id,
- };
- for (auto id : rare_controls_bar_buttons) {
+ for (auto id : overflow_buttons) {
if (id_to_keycode(id) == KEY_UNKNOWN)
continue;
- rare_controls_bar.addButton(id, button_image_names[id]);
+
+ recti rect(pos - size / 2, dimension2du(size.X, size.Y));
+ if (rect.LowerRightCorner.X > (s32)m_screensize.X) {
+ pos.X = spacing.X;
+ pos.Y += spacing.Y;
+ rect = recti(pos - size / 2, dimension2du(size.X, size.Y));
+ }
+
+ if (id == toggle_chat_id)
+ // Chat is shown by default, so chat_hide_btn.png is shown first.
+ addToggleButton(m_overflow_buttons, id, "chat_hide_btn.png",
+ "chat_show_btn.png", rect, false);
+ else
+ addButton(m_overflow_buttons, id, button_image_names[id], rect, false);
+
+ std::wstring str = wstrgettext(button_titles[id]);
+ IGUIStaticText *text = m_guienv->addStaticText(str.c_str(), recti());
+ IGUIFont *font = text->getActiveFont();
+ dimension2du dim = font->getDimension(str.c_str());
+ dim = dimension2du(dim.Width * 1.25f, dim.Height * 1.25f); // avoid clipping
+ text->setRelativePosition(recti(pos.X - dim.Width / 2, pos.Y + size.Y / 2,
+ pos.X + dim.Width / 2, pos.Y + size.Y / 2 + dim.Height));
+ text->setTextAlignment(EGUIA_CENTER, EGUIA_UPPERLEFT);
+ text->setVisible(false);
+ m_overflow_button_titles.push_back(grab_gui_element(text));
+
+ rect.addInternalPoint(text->getRelativePosition().UpperLeftCorner);
+ rect.addInternalPoint(text->getRelativePosition().LowerRightCorner);
+ m_overflow_button_rects.push_back(rect);
+
+ pos.X += spacing.X;
}
}
-void TouchScreenGUI::addButton(touch_gui_button_id id, const std::string &image, const recti &rect)
+void TouchScreenGUI::addButton(std::vector &buttons, touch_gui_button_id id,
+ const std::string &image, const recti &rect, bool visible)
{
IGUIImage *btn_gui_button = m_guienv->addImage(rect, nullptr, id);
+ btn_gui_button->setVisible(visible);
load_button_texture(btn_gui_button, image, rect,
m_texturesource, m_device->getVideoDriver());
- button_info &btn = m_buttons.emplace_back();
+ button_info &btn = buttons.emplace_back();
btn.keycode = id_to_keycode(id);
btn.gui_button = grab_gui_element(btn_gui_button);
}
-IGUIImage *TouchScreenGUI::makeJoystickButton(touch_gui_button_id id,
- const recti &button_rect, bool visible)
+void TouchScreenGUI::addToggleButton(std::vector &buttons, touch_gui_button_id id,
+ const std::string &image_1, const std::string &image_2, const recti &rect, bool visible)
{
- IGUIImage *btn_gui_button = m_guienv->addImage(button_rect, nullptr, id);
+ addButton(buttons, id, image_1, rect, visible);
+ button_info &btn = buttons.back();
+ btn.toggleable = button_info::FIRST_TEXTURE;
+ btn.toggle_textures[0] = image_1;
+ btn.toggle_textures[1] = image_2;
+}
+
+IGUIImage *TouchScreenGUI::makeButtonDirect(touch_gui_button_id id,
+ const recti &rect, bool visible)
+{
+ IGUIImage *btn_gui_button = m_guienv->addImage(rect, nullptr, id);
btn_gui_button->setVisible(visible);
- load_button_texture(btn_gui_button, button_image_names[id], button_rect,
+ load_button_texture(btn_gui_button, button_image_names[id], rect,
m_texturesource, m_device->getVideoDriver());
return btn_gui_button;
@@ -566,17 +476,17 @@ void TouchScreenGUI::handleReleaseEvent(size_t pointer_id)
m_pointer_downpos.erase(pointer_id);
m_pointer_pos.erase(pointer_id);
+ if (m_overflow_open) {
+ buttons_handleRelease(m_overflow_buttons, pointer_id, m_device->getVideoDriver(),
+ m_receiver, m_texturesource);
+ return;
+ }
+
// handle buttons
if (buttons_handleRelease(m_buttons, pointer_id, m_device->getVideoDriver(),
m_receiver, m_texturesource))
return;
- // handle buttonbars
- for (AutoHideButtonBar &bar : m_buttonbars) {
- if (bar.handleRelease(pointer_id))
- return;
- }
-
if (m_has_move_id && pointer_id == m_move_id) {
// handle the point used for moving view
m_has_move_id = false;
@@ -584,7 +494,8 @@ void TouchScreenGUI::handleReleaseEvent(size_t pointer_id)
// If m_tap_state is already set to TapState::ShortTap, we must keep
// that value. Otherwise, many short taps will be ignored if you tap
// very fast.
- if (!m_move_has_really_moved && m_tap_state != TapState::LongTap) {
+ if (!m_move_has_really_moved && !m_move_prevent_short_tap &&
+ m_tap_state != TapState::LongTap) {
m_tap_state = TapState::ShortTap;
} else {
m_tap_state = TapState::None;
@@ -635,41 +546,48 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
m_pointer_downpos[pointer_id] = touch_pos;
m_pointer_pos[pointer_id] = touch_pos;
+ bool prevent_short_tap = false;
+
IGUIElement *element = m_guienv->getRootGUIElement()->getElementFromPoint(touch_pos);
+ // handle overflow menu
+ if (!m_overflow_open) {
+ if (element == m_overflow_btn.get()) {
+ toggleOverflowMenu();
+ return;
+ }
+ } else {
+ for (size_t i = 0; i < m_overflow_buttons.size(); i++) {
+ if (m_overflow_button_rects[i].isPointInside(touch_pos)) {
+ element = m_overflow_buttons[i].gui_button.get();
+ break;
+ }
+ }
+
+ if (buttons_handlePress(m_overflow_buttons, pointer_id, element,
+ m_device->getVideoDriver(), m_receiver, m_texturesource))
+ return;
+
+ toggleOverflowMenu();
+ // refresh since visibility of buttons has changed
+ element = m_guienv->getRootGUIElement()->getElementFromPoint(touch_pos);
+ // restore after releaseAll in toggleOverflowMenu
+ m_pointer_downpos[pointer_id] = touch_pos;
+ m_pointer_pos[pointer_id] = touch_pos;
+ // continue processing, but avoid accidentally placing a node
+ // when closing the overflow menu
+ prevent_short_tap = true;
+ }
+
// handle buttons
if (buttons_handlePress(m_buttons, pointer_id, element,
- m_device->getVideoDriver(), m_receiver, m_texturesource)) {
- for (AutoHideButtonBar &bar : m_buttonbars)
- bar.deactivate();
+ m_device->getVideoDriver(), m_receiver, m_texturesource))
return;
- }
-
- // handle buttonbars
- for (AutoHideButtonBar &bar : m_buttonbars) {
- if (bar.handlePress(pointer_id, element)) {
- for (AutoHideButtonBar &other : m_buttonbars)
- if (other != bar)
- other.deactivate();
- return;
- }
- }
// handle hotbar
- if (isHotbarButton(event)) {
+ if (isHotbarButton(event))
// already handled in isHotbarButton()
- for (AutoHideButtonBar &bar : m_buttonbars)
- bar.deactivate();
return;
- }
-
- // handle non button events
- for (AutoHideButtonBar &bar : m_buttonbars) {
- if (bar.isActive()) {
- bar.deactivate();
- return;
- }
- }
// Select joystick when joystick tapped (fixed joystick position) or
// when left 1/3 of screen dragged (free joystick position)
@@ -704,6 +622,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
// DON'T reset m_tap_state here, otherwise many short taps
// will be ignored if you tap very fast.
m_had_move_id = true;
+ m_move_prevent_short_tap = prevent_short_tap;
}
}
}
@@ -713,6 +632,9 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
} else {
assert(event.TouchInput.Event == ETIE_MOVED);
+ if (m_overflow_open)
+ return;
+
if (!(m_has_joystick_id && m_fixed_joystick) &&
m_pointer_pos[event.TouchInput.ID] == touch_pos)
return;
@@ -798,10 +720,13 @@ void TouchScreenGUI::applyJoystickStatus()
void TouchScreenGUI::step(float dtime)
{
+ if (m_overflow_open) {
+ buttons_step(m_overflow_buttons, dtime, m_device->getVideoDriver(), m_receiver, m_texturesource);
+ return;
+ }
+
// simulate keyboard repeats
buttons_step(m_buttons, dtime, m_device->getVideoDriver(), m_receiver, m_texturesource);
- for (AutoHideButtonBar &bar : m_buttonbars)
- bar.step(dtime);
// joystick
applyJoystickStatus();
@@ -844,42 +769,65 @@ void TouchScreenGUI::registerHotbarRect(u16 index, const recti &rect)
void TouchScreenGUI::setVisible(bool visible)
{
+ if (m_visible == visible)
+ return;
+
m_visible = visible;
- for (auto &button : m_buttons) {
- if (button.gui_button)
- button.gui_button->setVisible(visible);
- }
-
- if (m_joystick_btn_off)
- m_joystick_btn_off->setVisible(visible);
-
- // clear all active buttons
+ // order matters
if (!visible) {
- while (!m_pointer_pos.empty())
- handleReleaseEvent(m_pointer_pos.begin()->first);
- for (AutoHideButtonBar &bar : m_buttonbars) {
- bar.deactivate();
- bar.hide();
- }
- } else {
- for (AutoHideButtonBar &bar : m_buttonbars)
- bar.show();
+ releaseAll();
+ m_overflow_open = false;
+ }
+ updateVisibility();
+}
+
+void TouchScreenGUI::toggleOverflowMenu()
+{
+ releaseAll(); // must be done first
+ m_overflow_open = !m_overflow_open;
+ updateVisibility();
+}
+
+void TouchScreenGUI::updateVisibility()
+{
+ bool regular_visible = m_visible && !m_overflow_open;
+ for (auto &button : m_buttons)
+ button.gui_button->setVisible(regular_visible);
+ m_overflow_btn->setVisible(regular_visible);
+ m_joystick_btn_off->setVisible(regular_visible);
+
+ bool overflow_visible = m_visible && m_overflow_open;
+ m_overflow_bg->setVisible(overflow_visible);
+ for (auto &button : m_overflow_buttons)
+ button.gui_button->setVisible(overflow_visible);
+ for (auto &text : m_overflow_button_titles)
+ text->setVisible(overflow_visible);
+}
+
+void TouchScreenGUI::releaseAll()
+{
+ while (!m_pointer_pos.empty())
+ handleReleaseEvent(m_pointer_pos.begin()->first);
+
+ // Release those manually too since the change initiated by
+ // handleReleaseEvent will only be applied later by applyContextControls.
+ if (m_dig_pressed) {
+ emitMouseEvent(EMIE_LMOUSE_LEFT_UP);
+ m_dig_pressed = false;
+ }
+ if (m_place_pressed) {
+ emitMouseEvent(EMIE_RMOUSE_LEFT_UP);
+ m_place_pressed = false;
}
}
void TouchScreenGUI::hide()
{
- if (!m_visible)
- return;
-
setVisible(false);
}
void TouchScreenGUI::show()
{
- if (m_visible)
- return;
-
setVisible(true);
}
diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h
index ca6c05e18..2da9d8151 100644
--- a/src/gui/touchscreengui.h
+++ b/src/gui/touchscreengui.h
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
+#include "IGUIStaticText.h"
#include "irrlichttypes.h"
#include
#include
@@ -74,8 +75,7 @@ enum touch_gui_button_id
sneak_id,
zoom_id,
aux1_id,
- settings_starter_id,
- rare_controls_starter_id,
+ overflow_id,
// usually in the "settings bar"
fly_id,
@@ -99,25 +99,16 @@ enum touch_gui_button_id
joystick_center_id,
};
-enum autohide_button_bar_dir
-{
- AHBB_Dir_Top_Bottom,
- AHBB_Dir_Bottom_Top,
- AHBB_Dir_Left_Right,
- AHBB_Dir_Right_Left
-};
#define BUTTON_REPEAT_DELAY 0.5f
#define BUTTON_REPEAT_INTERVAL 0.333f
-#define BUTTONBAR_HIDE_DELAY 3.0f
-#define SETTINGS_BAR_Y_OFFSET 5
-#define RARE_CONTROLS_BAR_Y_OFFSET 5
// Our simulated clicks last some milliseconds so that server-side mods have a
// chance to detect them via l_get_player_control.
// If you tap faster than this value, the simulated clicks are of course shorter.
#define SIMULATED_CLICK_DURATION_MS 50
+
struct button_info
{
float repeat_counter;
@@ -136,52 +127,6 @@ struct button_info
IEventReceiver *receiver, ISimpleTextureSource *tsrc);
};
-class AutoHideButtonBar
-{
-public:
- AutoHideButtonBar(IrrlichtDevice *device, ISimpleTextureSource *tsrc,
- touch_gui_button_id starter_id, const std::string &starter_image,
- recti starter_rect, autohide_button_bar_dir dir);
-
- void addButton(touch_gui_button_id id, const std::string &image);
- void addToggleButton(touch_gui_button_id id,
- const std::string &image_1, const std::string &image_2);
-
- bool handlePress(size_t pointer_id, IGUIElement *element);
- bool handleRelease(size_t pointer_id);
-
- void step(float dtime);
-
- void activate();
- void deactivate();
- bool isActive() { return m_active; }
-
- void show();
- void hide();
-
- bool operator==(const AutoHideButtonBar &other)
- { return m_starter.get() == other.m_starter.get(); }
- bool operator!=(const AutoHideButtonBar &other)
- { return m_starter.get() != other.m_starter.get(); }
-
-private:
- irr::video::IVideoDriver *m_driver = nullptr;
- IGUIEnvironment *m_guienv = nullptr;
- IEventReceiver *m_receiver = nullptr;
- ISimpleTextureSource *m_texturesource = nullptr;
- std::shared_ptr m_starter;
- std::vector m_buttons;
-
- v2s32 m_upper_left;
- v2s32 m_lower_right;
-
- bool m_active = false;
- bool m_visible = true;
- float m_timeout = 0.0f;
- autohide_button_bar_dir m_dir = AHBB_Dir_Right_Left;
-
- void updateVisibility();
-};
class TouchScreenGUI
{
@@ -262,6 +207,7 @@ private:
// This is needed so that we don't miss if m_has_move_id is true for less
// than one client step, i.e. press and release happen in the same step.
bool m_had_move_id = false;
+ bool m_move_prevent_short_tap = false;
bool m_has_joystick_id = false;
size_t m_joystick_id;
@@ -277,13 +223,28 @@ private:
std::shared_ptr m_joystick_btn_center;
std::vector m_buttons;
+ std::shared_ptr m_overflow_btn;
+
+ bool m_overflow_open = false;
+ std::shared_ptr m_overflow_bg;
+ std::vector m_overflow_buttons;
+ std::vector> m_overflow_button_titles;
+ std::vector m_overflow_button_rects;
+
+ void toggleOverflowMenu();
+ void updateVisibility();
+ void releaseAll();
// initialize a button
- void addButton(touch_gui_button_id id, const std::string &image,
- const recti &rect);
+ void addButton(std::vector &buttons,
+ touch_gui_button_id id, const std::string &image,
+ const recti &rect, bool visible=true);
+ void addToggleButton(std::vector &buttons,
+ touch_gui_button_id id,
+ const std::string &image_1, const std::string &image_2,
+ const recti &rect, bool visible=true);
- // initialize a joystick button
- IGUIImage *makeJoystickButton(touch_gui_button_id id,
+ IGUIImage *makeButtonDirect(touch_gui_button_id id,
const recti &rect, bool visible);
// handle pressing hotbar items
@@ -300,8 +261,6 @@ private:
// map to store the IDs and positions of currently pressed pointers
std::unordered_map m_pointer_pos;
- std::vector m_buttonbars;
-
v2s32 getPointerPos();
void emitMouseEvent(EMOUSE_INPUT_EVENT type);
TouchInteractionMode m_last_mode = TouchInteractionMode_END;
diff --git a/textures/base/pack/gear_icon.png b/textures/base/pack/gear_icon.png
deleted file mode 100644
index 6ca451046..000000000
Binary files a/textures/base/pack/gear_icon.png and /dev/null differ
diff --git a/textures/base/pack/overflow_btn.png b/textures/base/pack/overflow_btn.png
new file mode 100644
index 000000000..9afaed2c7
Binary files /dev/null and b/textures/base/pack/overflow_btn.png differ
diff --git a/textures/base/pack/rare_controls.png b/textures/base/pack/rare_controls.png
deleted file mode 100644
index 16bf61a8f..000000000
Binary files a/textures/base/pack/rare_controls.png and /dev/null differ