From 16e3161d307d25fc8a42551a08499f69633f5dd5 Mon Sep 17 00:00:00 2001 From: Gregor Parzefall Date: Sat, 13 Apr 2024 16:51:46 +0200 Subject: [PATCH] Fix memory management (take 2) --- src/gui/touchscreengui.cpp | 14 +++++++------- src/gui/touchscreengui.h | 34 ++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index e2f62982f..9cf7d38f6 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -271,7 +271,7 @@ AutoHideButtonBar::AutoHideButtonBar(IrrlichtDevice *device, ISimpleTextureSourc load_button_texture(starter_gui_button, starter_img, starter_rect, m_texturesource, m_driver); - m_starter.grab(starter_gui_button); + m_starter = grab_gui_element(starter_gui_button); m_dir = dir; } @@ -325,7 +325,7 @@ void AutoHideButtonBar::addButton(touch_gui_button_id id, const std::string &ima button_info btn{}; btn.keycode = id_to_keycode(id); - btn.gui_button.grab(btn_gui_button); + btn.gui_button = grab_gui_element(btn_gui_button); m_buttons.push_back(btn); } @@ -437,26 +437,26 @@ 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(makeJoystickButton(joystick_off_id, + m_joystick_btn_off = grab_gui_element(makeJoystickButton(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(makeJoystickButton(joystick_off_id, + m_joystick_btn_off = grab_gui_element(makeJoystickButton(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(makeJoystickButton(joystick_bg_id, + m_joystick_btn_bg = grab_gui_element(makeJoystickButton(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(makeJoystickButton(joystick_center_id, + m_joystick_btn_center = grab_gui_element(makeJoystickButton(joystick_center_id, recti(0, 0, m_button_size, m_button_size), false)); // init jump button @@ -539,7 +539,7 @@ void TouchScreenGUI::addButton(touch_gui_button_id id, const std::string &image, button_info &btn = m_buttons.emplace_back(); btn.keycode = id_to_keycode(id); - btn.gui_button.grab(btn_gui_button); + btn.gui_button = grab_gui_element(btn_gui_button); } IGUIButton *TouchScreenGUI::makeJoystickButton(touch_gui_button_id id, diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index f5f3f1a7e..0624bec8f 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -20,7 +20,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once -#include "irr_ptr.h" #include "irrlichttypes.h" #include #include @@ -39,6 +38,29 @@ using namespace irr; using namespace irr::core; using namespace irr::gui; + +// We cannot use irr_ptr for Irrlicht GUI elements we own. +// Option 1: Pass IGUIElement* returned by IGUIEnvironment::add* into irr_ptr +// constructor. +// -> We steal the reference owned by IGUIEnvironment and drop it later, +// causing the IGUIElement to be deleted while IGUIEnvironment still +// references it. +// Option 2: Pass IGUIElement* returned by IGUIEnvironment::add* into irr_ptr::grab. +// -> We add another reference and drop it later, but since IGUIEnvironment +// still references the IGUIElement, it is never deleted. +// To make IGUIEnvironment drop its reference to the IGUIElement, we have to call +// IGUIElement::remove, so that's what we'll do. +template +std::shared_ptr grab_gui_element(T *element) +{ + static_assert(std::is_base_of_v, + "grab_gui_element only works for IGUIElement"); + return std::shared_ptr(element, [](T *e) { + e->remove(); + }); +} + + enum class TapState { None, @@ -101,7 +123,7 @@ struct button_info float repeat_counter; EKEY_CODE keycode; std::vector pointer_ids; - irr_ptr gui_button = nullptr; + std::shared_ptr gui_button = nullptr; enum { NOT_TOGGLEABLE, @@ -144,7 +166,7 @@ private: IGUIEnvironment *m_guienv = nullptr; IEventReceiver *m_receiver = nullptr; ISimpleTextureSource *m_texturesource = nullptr; - irr_ptr m_starter; + std::shared_ptr m_starter; std::vector m_buttons; v2s32 m_upper_left; @@ -244,9 +266,9 @@ private: bool m_fixed_joystick = false; bool m_joystick_triggers_aux1 = false; bool m_draw_crosshair = false; - irr_ptr m_joystick_btn_off; - irr_ptr m_joystick_btn_bg; - irr_ptr m_joystick_btn_center; + std::shared_ptr m_joystick_btn_off; + std::shared_ptr m_joystick_btn_bg; + std::shared_ptr m_joystick_btn_center; std::vector m_buttons;