From 92b6ff4721103389f81d725b4ae599f2a8450cc8 Mon Sep 17 00:00:00 2001 From: Gregor Parzefall <82708541+grorp@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:45:51 +0200 Subject: [PATCH] TouchScreenGUI: Fix only 9 hotbar slots being usable (#13698) Co-authored-by: Muhammad Rifqi Priyo Susanto --- src/client/game.cpp | 8 ++++++++ src/client/hud.cpp | 39 ++++++++++++++++++++------------------ src/client/hud.h | 2 +- src/gui/touchscreengui.cpp | 39 ++++++++++++++++++++------------------ src/gui/touchscreengui.h | 20 +++++++++++-------- 5 files changed, 63 insertions(+), 45 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index a9c26db2e..827e14678 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2168,6 +2168,14 @@ void Game::processItemSelection(u16 *new_playeritem) } } +#ifdef HAVE_TOUCHSCREENGUI + if (g_touchscreengui) { + std::optional selection = g_touchscreengui->getHotbarSelection(); + if (selection) + *new_playeritem = *selection; + } +#endif + // Clamp selection again in case it wasn't changed but max_item was *new_playeritem = MYMIN(*new_playeritem, max_item); } diff --git a/src/client/hud.cpp b/src/client/hud.cpp index f05131e1f..3fbb69f5a 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -223,16 +223,12 @@ void Hud::drawItem(const ItemStack &item, const core::rect& rect, client, selected ? IT_ROT_SELECTED : IT_ROT_NONE); } -//NOTE: selectitem = 0 -> no selected; selectitem 1-based +// NOTE: selectitem = 0 -> no selected; selectitem is 1-based // mainlist can be NULL, but draw the frame anyway. void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount, - s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction) + s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction, + bool is_hotbar) { -#ifdef HAVE_TOUCHSCREENGUI - if (g_touchscreengui && inv_offset == 0) - g_touchscreengui->resetHud(); -#endif - s32 height = m_hotbar_imagesize + m_padding * 2; s32 width = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2); @@ -292,11 +288,13 @@ void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount, break; } - drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem); + core::rect item_rect = imgrect + pos + steppos; + + drawItem(mainlist->getItem(i), item_rect, (i + 1) == selectitem); #ifdef HAVE_TOUCHSCREENGUI - if (g_touchscreengui) - g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos)); + if (is_hotbar && g_touchscreengui) + g_touchscreengui->registerHotbarRect(i, item_rect); #endif } } @@ -406,7 +404,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) if (!inv) warningstream << "HUD: Unknown inventory list. name=" << e->text << std::endl; drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0, - inv, e->item, e->dir); + inv, e->item, e->dir, false); break; } case HUD_ELEM_WAYPOINT: { if (!calculateScreenPos(camera_offset, e, &pos)) @@ -739,16 +737,21 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, } -void Hud::drawHotbar(u16 playeritem) { - - v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y); +void Hud::drawHotbar(u16 playeritem) +{ +#ifdef HAVE_TOUCHSCREENGUI + if (g_touchscreengui) + g_touchscreengui->resetHotbarRects(); +#endif InventoryList *mainlist = inventory->getList("main"); if (mainlist == NULL) { - //silently ignore this we may not be initialized completely + // Silently ignore this. We may not be initialized completely. return; } + v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y); + s32 hotbar_itemcount = player->hud_hotbar_itemcount; s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3); @@ -757,7 +760,7 @@ void Hud::drawHotbar(u16 playeritem) { if ((float) width / (float) window_size.X <= g_settings->getFloat("hud_hotbar_max_width")) { if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) { - drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0); + drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0, true); } } else { pos.X += width/4; @@ -767,9 +770,9 @@ void Hud::drawHotbar(u16 playeritem) { if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) { drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0, - mainlist, playeritem + 1, 0); + mainlist, playeritem + 1, 0, true); drawItems(secondpos, v2s32(0, 0), hotbar_itemcount, - hotbar_itemcount / 2, mainlist, playeritem + 1, 0); + hotbar_itemcount / 2, mainlist, playeritem + 1, 0, true); } } } diff --git a/src/client/hud.h b/src/client/hud.h index b6ff84243..303feb783 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -101,7 +101,7 @@ private: void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount, s32 inv_offset, InventoryList *mainlist, u16 selectitem, - u16 direction); + u16 direction, bool is_hotbar); void drawItem(const ItemStack &item, const core::rect &rect, bool selected); diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index 3d676cebb..90d163fb6 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -583,25 +583,28 @@ touch_gui_button_id TouchScreenGUI::getButtonID(size_t eventID) return after_last_element_id; } -bool TouchScreenGUI::isHUDButton(const SEvent &event) +bool TouchScreenGUI::isHotbarButton(const SEvent &event) { - // check if hud item is pressed - for (auto &hud_rect : m_hud_rects) { - if (hud_rect.second.isPointInside(v2s32(event.TouchInput.X, event.TouchInput.Y))) { - SEvent translated{}; - translated.EventType = irr::EET_KEY_INPUT_EVENT; - translated.KeyInput.Key = (irr::EKEY_CODE) (KEY_KEY_1 + hud_rect.first); - translated.KeyInput.Control = false; - translated.KeyInput.Shift = false; - translated.KeyInput.PressedDown = true; - m_receiver->OnEvent(translated); - m_hud_ids[event.TouchInput.ID] = translated.KeyInput.Key; + const v2s32 touch_pos = v2s32(event.TouchInput.X, event.TouchInput.Y); + // check if hotbar item is pressed + for (auto &[index, rect] : m_hotbar_rects) { + if (rect.isPointInside(touch_pos)) { + // We can't just emit a keypress event because the number keys + // range from 1 to 9, but there may be more hotbar items. + m_hotbar_selection = index; return true; } } return false; } +std::optional TouchScreenGUI::getHotbarSelection() +{ + auto selection = m_hotbar_selection; + m_hotbar_selection = std::nullopt; + return selection; +} + void TouchScreenGUI::handleButtonEvent(touch_gui_button_id button, size_t eventID, bool action) { @@ -745,10 +748,10 @@ void TouchScreenGUI::translateEvent(const SEvent &event) handleButtonEvent(button, eventID, true); m_settings_bar.deactivate(); m_rare_controls_bar.deactivate(); - } else if (isHUDButton(event)) { + } else if (isHotbarButton(event)) { m_settings_bar.deactivate(); m_rare_controls_bar.deactivate(); - // already handled in isHUDButton() + // already handled in isHotbarButton() } else if (m_settings_bar.isButton(event)) { m_rare_controls_bar.deactivate(); // already handled in isSettingsBarButton() @@ -1071,14 +1074,14 @@ void TouchScreenGUI::step(float dtime) m_rare_controls_bar.step(dtime); } -void TouchScreenGUI::resetHud() +void TouchScreenGUI::resetHotbarRects() { - m_hud_rects.clear(); + m_hotbar_rects.clear(); } -void TouchScreenGUI::registerHudItem(int index, const rect &rect) +void TouchScreenGUI::registerHotbarRect(u16 index, const rect &rect) { - m_hud_rects[index] = rect; + m_hotbar_rects[index] = rect; } void TouchScreenGUI::setVisible(bool visible) diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index 2ef0bd3bd..ff5219f3a 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -24,8 +24,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -#include #include +#include +#include #include #include "client/tile.h" @@ -186,14 +187,16 @@ public: float getMovementSpeed() { return m_joystick_speed; } void step(float dtime); - void resetHud(); - void registerHudItem(int index, const rect &rect); inline void setUseCrosshair(bool use_crosshair) { m_draw_crosshair = use_crosshair; } void setVisible(bool visible); void hide(); void show(); + void resetHotbarRects(); + void registerHotbarRect(u16 index, const rect &rect); + std::optional getHotbarSelection(); + private: bool m_initialized = false; IrrlichtDevice *m_device; @@ -203,10 +206,11 @@ private: v2u32 m_screensize; s32 button_size; double m_touchscreen_threshold; - std::map> m_hud_rects; - std::map m_hud_ids; bool m_visible; // is the whole touch screen gui visible + std::unordered_map> m_hotbar_rects; + std::optional m_hotbar_selection = std::nullopt; + // value in degree double m_camera_yaw_change = 0.0; double m_camera_pitch = 0.0; @@ -272,8 +276,8 @@ private: // handle a button event void handleButtonEvent(touch_gui_button_id bID, size_t eventID, bool action); - // handle pressed hud buttons - bool isHUDButton(const SEvent &event); + // handle pressing hotbar items + bool isHotbarButton(const SEvent &event); // do a right-click bool doRightClick(); @@ -285,7 +289,7 @@ private: void applyJoystickStatus(); // array for saving last known position of a pointer - std::map m_pointer_pos; + std::unordered_map m_pointer_pos; // settings bar AutoHideButtonBar m_settings_bar;