From dedabef6f692a1bf4333c7029693ce12783cfe45 Mon Sep 17 00:00:00 2001 From: Gregor Parzefall Date: Wed, 13 Mar 2024 17:56:40 +0100 Subject: [PATCH] Get rid of bug-prone "alloc in init function instead of constructor, free in destructor" pattern --- src/client/clientlauncher.cpp | 4 - src/client/game.cpp | 4 +- src/gui/touchscreengui.cpp | 306 +++++++++++++++------------------- src/gui/touchscreengui.h | 32 ++-- 4 files changed, 149 insertions(+), 197 deletions(-) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 56beba927..5ea089fea 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -206,10 +206,6 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) if (!m_rendering_engine->run() || *kill) break; - if (g_settings->getBool("enable_touch")) { - g_touchscreengui = new TouchScreenGUI(m_rendering_engine->get_raw_device(), receiver); - } - the_game( kill, input, diff --git a/src/client/game.cpp b/src/client/game.cpp index d89b6639c..4bd3d593d 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1555,8 +1555,8 @@ bool Game::initGui() gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), -1, chat_backend, client, &g_menumgr); - if (g_touchscreengui) - g_touchscreengui->init(texture_src); + if (g_settings->getBool("enable_touch")) + g_touchscreengui = new TouchScreenGUI(device, texture_src); return true; } diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index 9cb8419d2..fda9775da 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -146,27 +146,19 @@ static void load_button_texture(button_info &btn, const std::string &path, } } -AutoHideButtonBar::AutoHideButtonBar(IrrlichtDevice *device, - IEventReceiver *receiver) : +AutoHideButtonBar::AutoHideButtonBar(IrrlichtDevice *device, ISimpleTextureSource *tsrc, + const std::string &starter_img, touch_gui_button_id starter_id, + core::recti starter_rect, autohide_button_bar_dir dir, float timeout) : m_driver(device->getVideoDriver()), m_guienv(device->getGUIEnvironment()), - m_receiver(receiver) + m_receiver(device->getEventReceiver()), + m_texturesource(tsrc) { -} - -void AutoHideButtonBar::init(ISimpleTextureSource *tsrc, - const std::string &starter_img, int button_id, const v2s32 &UpperLeft, - const v2s32 &LowerRight, autohide_button_bar_dir dir, float timeout) -{ - m_texturesource = tsrc; - - m_upper_left = UpperLeft; - m_lower_right = LowerRight; - - rect starter_rect = rect(UpperLeft.X, UpperLeft.Y, LowerRight.X, LowerRight.Y); + m_upper_left = starter_rect.UpperLeftCorner; + m_lower_right = starter_rect.LowerRightCorner; IGUIButton *starter_gui_button = m_guienv->addButton(starter_rect, nullptr, - button_id, L"", nullptr); + starter_id, L"", nullptr); m_starter.gui_button = starter_gui_button; m_starter.gui_button->grab(); @@ -180,8 +172,6 @@ void AutoHideButtonBar::init(ISimpleTextureSource *tsrc, m_dir = dir; m_timeout_value = timeout; - - m_initialized = true; } AutoHideButtonBar::~AutoHideButtonBar() @@ -203,12 +193,6 @@ AutoHideButtonBar::~AutoHideButtonBar() void AutoHideButtonBar::addButton(touch_gui_button_id button_id, const wchar_t *caption, const std::string &btn_image) { - - if (!m_initialized) { - errorstream << "AutoHideButtonBar::addButton not yet initialized!" << std::endl; - return; - } - int button_size = 0; if (m_dir == AHBB_Dir_Top_Bottom || m_dir == AHBB_Dir_Bottom_Top) @@ -404,10 +388,11 @@ bool AutoHideButtonBar::operator!=(const AutoHideButtonBar &other) { return m_starter.gui_button != other.m_starter.gui_button; } -TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver): +TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, ISimpleTextureSource *tsrc): m_device(device), m_guienv(device->getGUIEnvironment()), - m_receiver(receiver) + m_receiver(device->getEventReceiver()), + m_texturesource(tsrc) { for (auto &button : m_buttons) { button.gui_button = nullptr; @@ -420,9 +405,125 @@ TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver) m_fixed_joystick = g_settings->getBool("fixed_virtual_joystick"); m_joystick_triggers_aux1 = g_settings->getBool("virtual_joystick_triggers_aux1"); m_screensize = m_device->getVideoDriver()->getScreenSize(); - button_size = MYMIN(m_screensize.Y / 4.5f, + m_button_size = MYMIN(m_screensize.Y / 4.5f, RenderingEngine::getDisplayDensity() * 65.0f * g_settings->getFloat("hud_scaling")); + + // Initialize joystick display "button". + // Joystick is placed on the bottom left of screen. + if (m_fixed_joystick) { + m_joystick_btn_off = initJoystickButton(joystick_off_id, + rect(m_button_size, + m_screensize.Y - m_button_size * 4, + m_button_size * 4, + m_screensize.Y - m_button_size), 0); + } else { + m_joystick_btn_off = initJoystickButton(joystick_off_id, + rect(m_button_size, + m_screensize.Y - m_button_size * 3, + m_button_size * 3, + m_screensize.Y - m_button_size), 0); + } + + m_joystick_btn_bg = initJoystickButton(joystick_bg_id, + rect(m_button_size, + m_screensize.Y - m_button_size * 4, + m_button_size * 4, + m_screensize.Y - m_button_size), + 1, false); + + m_joystick_btn_center = initJoystickButton(joystick_center_id, + rect(0, 0, m_button_size, m_button_size), 2, false); + + // init jump button + initButton(jump_id, + rect(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), + L"x", false); + + // init crunch button + initButton(crunch_id, + rect(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), + L"H", false); + + // init zoom button + initButton(zoom_id, + rect(m_screensize.X - 1.25f * m_button_size, + m_screensize.Y - 4 * m_button_size, + m_screensize.X - 0.25f * m_button_size, + m_screensize.Y - 3 * m_button_size), + L"z", false); + + // init aux1 button + if (!m_joystick_triggers_aux1) + initButton(aux1_id, + rect(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), + L"spc1", false); + + AutoHideButtonBar &settings_bar = m_buttonbars.emplace_back(m_device, m_texturesource, + "gear_icon.png", settings_starter_id, + core::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, 3.0f); + + const static std::map settings_bar_buttons { + {fly_id, "fly"}, + {noclip_id, "noclip"}, + {fast_id, "fast"}, + {debug_id, "debug"}, + {camera_id, "camera"}, + {range_id, "rangeview"}, + {minimap_id, "minimap"}, + }; + for (const auto &pair : settings_bar_buttons) { + if (id_to_keycode(pair.first) == KEY_UNKNOWN) + continue; + + std::wstring wide = utf8_to_wide(pair.second); + settings_bar.addButton(pair.first, wide.c_str(), + pair.second + "_btn.png"); + } + + // Chat is shown by default, so chat_hide_btn.png is shown first. + settings_bar.addToggleButton(toggle_chat_id, L"togglechat", + "chat_hide_btn.png", "chat_show_btn.png"); + + AutoHideButtonBar &rare_controls_bar = m_buttonbars.emplace_back(m_device, m_texturesource, + "rare_controls.png", rare_controls_starter_id, + core::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, 2.0f); + + const static std::map rare_controls_bar_buttons { + {chat_id, "chat"}, + {inventory_id, "inventory"}, + {drop_id, "drop"}, + {exit_id, "exit"}, + }; + for (const auto &pair : rare_controls_bar_buttons) { + if (id_to_keycode(pair.first) == KEY_UNKNOWN) + continue; + + std::wstring wide = utf8_to_wide(pair.second); + rare_controls_bar.addButton(pair.first, wide.c_str(), + pair.second + "_btn.png"); + } } void TouchScreenGUI::initButton(touch_gui_button_id id, const rect &button_rect, @@ -460,133 +561,6 @@ button_info TouchScreenGUI::initJoystickButton(touch_gui_button_id id, return btn; } -void TouchScreenGUI::init(ISimpleTextureSource *tsrc) -{ - assert(tsrc); - - m_visible = true; - m_texturesource = tsrc; - - // Initialize joystick display "button". - // Joystick is placed on the bottom left of screen. - 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); - } 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); - } - - 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), - 1, false); - - m_joystick_btn_center = initJoystickButton(joystick_center_id, - rect(0, 0, button_size, button_size), 2, false); - - // init jump button - initButton(jump_id, - rect(m_screensize.X - 1.75f * button_size, - m_screensize.Y - button_size, - m_screensize.X - 0.25f * button_size, - m_screensize.Y), - L"x", false); - - // init crunch button - initButton(crunch_id, - rect(m_screensize.X - 3.25f * button_size, - m_screensize.Y - button_size, - m_screensize.X - 1.75f * button_size, - m_screensize.Y), - L"H", false); - - // init zoom button - initButton(zoom_id, - rect(m_screensize.X - 1.25f * button_size, - m_screensize.Y - 4 * button_size, - m_screensize.X - 0.25f * button_size, - m_screensize.Y - 3 * button_size), - L"z", false); - - // init aux1 button - if (!m_joystick_triggers_aux1) - initButton(aux1_id, - rect(m_screensize.X - 1.25f * button_size, - m_screensize.Y - 2.5f * button_size, - m_screensize.X - 0.25f * button_size, - m_screensize.Y - 1.5f * button_size), - L"spc1", false); - - AutoHideButtonBar &settings_bar = m_buttonbars.emplace_back(m_device, m_receiver); - settings_bar.init(m_texturesource, "gear_icon.png", settings_starter_id, - v2s32(m_screensize.X - 1.25f * button_size, - m_screensize.Y - (SETTINGS_BAR_Y_OFFSET + 1.0f) * button_size - + 0.5f * button_size), - v2s32(m_screensize.X - 0.25f * button_size, - m_screensize.Y - SETTINGS_BAR_Y_OFFSET * button_size - + 0.5f * button_size), - AHBB_Dir_Right_Left, 3.0f); - - const static std::map settings_bar_buttons { - {fly_id, "fly"}, - {noclip_id, "noclip"}, - {fast_id, "fast"}, - {debug_id, "debug"}, - {camera_id, "camera"}, - {range_id, "rangeview"}, - {minimap_id, "minimap"}, - }; - for (const auto &pair : settings_bar_buttons) { - if (id_to_keycode(pair.first) == KEY_UNKNOWN) - continue; - - std::wstring wide = utf8_to_wide(pair.second); - settings_bar.addButton(pair.first, wide.c_str(), - pair.second + "_btn.png"); - } - - // Chat is shown by default, so chat_hide_btn.png is shown first. - settings_bar.addToggleButton(toggle_chat_id, L"togglechat", - "chat_hide_btn.png", "chat_show_btn.png"); - - AutoHideButtonBar &rare_controls_bar = m_buttonbars.emplace_back(m_device, m_receiver); - rare_controls_bar.init(m_texturesource, "rare_controls.png", - rare_controls_starter_id, - v2s32(0.25f * button_size, - m_screensize.Y - (RARE_CONTROLS_BAR_Y_OFFSET + 1.0f) * button_size - + 0.5f * button_size), - v2s32(0.75f * button_size, - m_screensize.Y - RARE_CONTROLS_BAR_Y_OFFSET * button_size - + 0.5f * button_size), - AHBB_Dir_Left_Right, 2.0f); - - const static std::map rare_controls_bar_buttons { - {chat_id, "chat"}, - {inventory_id, "inventory"}, - {drop_id, "drop"}, - {exit_id, "exit"}, - }; - for (const auto &pair : rare_controls_bar_buttons) { - if (id_to_keycode(pair.first) == KEY_UNKNOWN) - continue; - - std::wstring wide = utf8_to_wide(pair.second); - rare_controls_bar.addButton(pair.first, wide.c_str(), - pair.second + "_btn.png"); - } - - m_initialized = true; -} - touch_gui_button_id TouchScreenGUI::getButtonID(s32 x, s32 y) { IGUIElement *rootguielement = m_guienv->getRootGUIElement(); @@ -729,9 +703,6 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id) void TouchScreenGUI::translateEvent(const SEvent &event) { - if (!m_initialized) - return; - if (!m_visible) { infostream << "TouchScreenGUI::translateEvent got event but is not visible!" << std::endl; @@ -741,7 +712,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) if (event.EventType != EET_TOUCH_INPUT_EVENT) return; - const s32 half_button_size = button_size / 2.0f; + const s32 half_button_size = m_button_size / 2.0f; const s32 fixed_joystick_range_sq = half_button_size * half_button_size * 3 * 3; const s32 X = event.TouchInput.X; const s32 Y = event.TouchInput.Y; @@ -872,16 +843,16 @@ void TouchScreenGUI::translateEvent(const SEvent &event) if (distance <= m_touchscreen_threshold) { m_joystick_speed = 0.0f; } else { - m_joystick_speed = distance / button_size; + m_joystick_speed = distance / m_button_size; if (m_joystick_speed > 1.0f) m_joystick_speed = 1.0f; } m_joystick_status_aux1 = distance > (half_button_size * 3); - if (distance > button_size) { + if (distance > m_button_size) { // move joystick "button" - v2s32 new_offset = dir * button_size / distance - half_button_size; + v2s32 new_offset = dir * m_button_size / distance - half_button_size; if (m_fixed_joystick) m_joystick_btn_center.gui_button->setRelativePosition( fixed_joystick_center + new_offset); @@ -953,9 +924,6 @@ void TouchScreenGUI::applyJoystickStatus() TouchScreenGUI::~TouchScreenGUI() { - if (!m_initialized) - return; - for (auto &button : m_buttons) { if (button.gui_button) { button.gui_button->drop(); @@ -981,9 +949,6 @@ TouchScreenGUI::~TouchScreenGUI() void TouchScreenGUI::step(float dtime) { - if (!m_initialized) - return; - // simulate keyboard repeats for (auto &button : m_buttons) { if (!button.ids.empty()) { @@ -1047,9 +1012,6 @@ void TouchScreenGUI::registerHotbarRect(u16 index, const rect &rect) void TouchScreenGUI::setVisible(bool visible) { - if (!m_initialized) - return; - m_visible = visible; for (auto &button : m_buttons) { if (button.gui_button) @@ -1073,7 +1035,7 @@ void TouchScreenGUI::setVisible(bool visible) void TouchScreenGUI::hide() { - if (!m_visible) +if (!m_visible) return; setVisible(false); @@ -1081,7 +1043,7 @@ void TouchScreenGUI::hide() void TouchScreenGUI::show() { - if (m_visible) + if (m_visible) return; setVisible(true); diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index b9f8ff7f5..9102b107f 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -111,11 +111,9 @@ struct button_info class AutoHideButtonBar { public: - AutoHideButtonBar(IrrlichtDevice *device, IEventReceiver *receiver); - - void init(ISimpleTextureSource *tsrc, const std::string &starter_img, int button_id, - const v2s32 &UpperLeft, const v2s32 &LowerRight, - autohide_button_bar_dir dir, float timeout); + AutoHideButtonBar(IrrlichtDevice *device, ISimpleTextureSource *tsrc, + const std::string &starter_img, touch_gui_button_id starter_id, + core::recti starter_rect, autohide_button_bar_dir dir, float timeout); ~AutoHideButtonBar(); @@ -148,10 +146,10 @@ public: bool operator!=(const AutoHideButtonBar &other); private: + irr::video::IVideoDriver *m_driver = nullptr; + IGUIEnvironment *m_guienv = nullptr; + IEventReceiver *m_receiver = nullptr; ISimpleTextureSource *m_texturesource = nullptr; - irr::video::IVideoDriver *m_driver; - IGUIEnvironment *m_guienv; - IEventReceiver *m_receiver; button_info m_starter; std::vector m_buttons; @@ -165,21 +163,18 @@ private: // button bar timeout float m_timeout = 0.0f; float m_timeout_value = 3.0f; - bool m_initialized = false; autohide_button_bar_dir m_dir = AHBB_Dir_Right_Left; }; class TouchScreenGUI { public: - TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver); + TouchScreenGUI(IrrlichtDevice *device, ISimpleTextureSource *tsrc); ~TouchScreenGUI(); void translateEvent(const SEvent &event); void applyContextControls(const TouchInteractionMode &mode); - void init(ISimpleTextureSource *tsrc); - double getYawChange() { double res = m_camera_yaw_change; @@ -218,16 +213,15 @@ public: std::optional getHotbarSelection(); private: - bool m_initialized = false; - IrrlichtDevice *m_device; - IGUIEnvironment *m_guienv; - IEventReceiver *m_receiver; - ISimpleTextureSource *m_texturesource; + IrrlichtDevice *m_device = nullptr; + IGUIEnvironment *m_guienv = nullptr; + IEventReceiver *m_receiver = nullptr; + ISimpleTextureSource *m_texturesource = nullptr; v2u32 m_screensize; - s32 button_size; + s32 m_button_size; double m_touchscreen_threshold; u16 m_long_tap_delay; - bool m_visible; // is the whole touch screen gui visible + bool m_visible = true; // is the whole touch screen gui visible std::unordered_map> m_hotbar_rects; std::optional m_hotbar_selection = std::nullopt;