TouchScreenGUI dehardcoding refactor (#14472)

This commit is contained in:
grorp 2024-04-17 15:59:52 +02:00 committed by GitHub
parent b2057a5da7
commit f2b5c35fa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 491 additions and 699 deletions

@ -206,10 +206,6 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
if (!m_rendering_engine->run() || *kill) if (!m_rendering_engine->run() || *kill)
break; break;
if (g_settings->getBool("enable_touch")) {
g_touchscreengui = new TouchScreenGUI(m_rendering_engine->get_raw_device(), receiver);
}
the_game( the_game(
kill, kill,
input, input,

@ -1555,8 +1555,8 @@ bool Game::initGui()
gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(),
-1, chat_backend, client, &g_menumgr); -1, chat_backend, client, &g_menumgr);
if (g_touchscreengui) if (g_settings->getBool("enable_touch"))
g_touchscreengui->init(texture_src); g_touchscreengui = new TouchScreenGUI(device, texture_src);
return true; return true;
} }

File diff suppressed because it is too large Load Diff

@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h" #include "irrlichttypes.h"
#include <IEventReceiver.h> #include <IEventReceiver.h>
#include <IGUIButton.h> #include <IGUIImage.h>
#include <IGUIEnvironment.h> #include <IGUIEnvironment.h>
#include <IrrlichtDevice.h> #include <IrrlichtDevice.h>
@ -38,6 +38,29 @@ using namespace irr;
using namespace irr::core; using namespace irr::core;
using namespace irr::gui; 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 <typename T>
std::shared_ptr<T> grab_gui_element(T *element)
{
static_assert(std::is_base_of_v<IGUIElement, T>,
"grab_gui_element only works for IGUIElement");
return std::shared_ptr<T>(element, [](T *e) {
e->remove();
});
}
enum class TapState enum class TapState
{ {
None, None,
@ -45,15 +68,16 @@ enum class TapState
LongTap, LongTap,
}; };
typedef enum enum touch_gui_button_id
{ {
jump_id = 0, jump_id = 0,
crunch_id, sneak_id,
zoom_id, zoom_id,
aux1_id, aux1_id,
after_last_element_id,
settings_starter_id, settings_starter_id,
rare_controls_starter_id, rare_controls_starter_id,
// usually in the "settings bar"
fly_id, fly_id,
noclip_id, noclip_id,
fast_id, fast_id,
@ -62,24 +86,30 @@ typedef enum
range_id, range_id,
minimap_id, minimap_id,
toggle_chat_id, toggle_chat_id,
// usually in the "rare controls bar"
chat_id, chat_id,
inventory_id, inventory_id,
drop_id, drop_id,
exit_id, exit_id,
// the joystick
joystick_off_id, joystick_off_id,
joystick_bg_id, joystick_bg_id,
joystick_center_id joystick_center_id,
} touch_gui_button_id; };
typedef enum enum autohide_button_bar_dir
{ {
AHBB_Dir_Top_Bottom, AHBB_Dir_Top_Bottom,
AHBB_Dir_Bottom_Top, AHBB_Dir_Bottom_Top,
AHBB_Dir_Left_Right, AHBB_Dir_Left_Right,
AHBB_Dir_Right_Left AHBB_Dir_Right_Left
} autohide_button_bar_dir; };
#define BUTTON_REPEAT_DELAY 0.2f #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 SETTINGS_BAR_Y_OFFSET 5
#define RARE_CONTROLS_BAR_Y_OFFSET 5 #define RARE_CONTROLS_BAR_Y_OFFSET 5
@ -88,96 +118,79 @@ typedef enum
// If you tap faster than this value, the simulated clicks are of course shorter. // If you tap faster than this value, the simulated clicks are of course shorter.
#define SIMULATED_CLICK_DURATION_MS 50 #define SIMULATED_CLICK_DURATION_MS 50
extern const std::string button_image_names[];
extern const std::string joystick_image_names[];
struct button_info struct button_info
{ {
float repeat_counter; float repeat_counter;
float repeat_delay;
EKEY_CODE keycode; EKEY_CODE keycode;
std::vector<size_t> ids; std::vector<size_t> pointer_ids;
IGUIButton *gui_button = nullptr; std::shared_ptr<IGUIImage> gui_button = nullptr;
bool immediate_release;
enum { enum {
NOT_TOGGLEABLE, NOT_TOGGLEABLE,
FIRST_TEXTURE, FIRST_TEXTURE,
SECOND_TEXTURE SECOND_TEXTURE
} toggleable = NOT_TOGGLEABLE; } toggleable = NOT_TOGGLEABLE;
std::vector<std::string> textures; std::string toggle_textures[2];
void emitAction(bool action, video::IVideoDriver *driver,
IEventReceiver *receiver, ISimpleTextureSource *tsrc);
}; };
class AutoHideButtonBar class AutoHideButtonBar
{ {
public: public:
AutoHideButtonBar(IrrlichtDevice *device, IEventReceiver *receiver); 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 init(ISimpleTextureSource *tsrc, const std::string &starter_img, int button_id, void addButton(touch_gui_button_id id, const std::string &image);
const v2s32 &UpperLeft, const v2s32 &LowerRight, void addToggleButton(touch_gui_button_id id,
autohide_button_bar_dir dir, float timeout); const std::string &image_1, const std::string &image_2);
~AutoHideButtonBar(); bool handlePress(size_t pointer_id, IGUIElement *element);
bool handleRelease(size_t pointer_id);
// add button to be shown
void addButton(touch_gui_button_id id, const wchar_t *caption,
const std::string &btn_image);
// add toggle button to be shown
void addToggleButton(touch_gui_button_id id, const wchar_t *caption,
const std::string &btn_image_1, const std::string &btn_image_2);
// detect button bar button events
bool isButton(const SEvent &event);
// step handler
void step(float dtime); void step(float dtime);
// return whether the button bar is active void activate();
bool active() { return m_active; }
// deactivate the button bar
void deactivate(); void deactivate();
bool isActive() { return m_active; }
// hide the whole button bar void show();
void hide(); void hide();
// unhide the button bar bool operator==(const AutoHideButtonBar &other)
void show(); { return m_starter.get() == other.m_starter.get(); }
bool operator!=(const AutoHideButtonBar &other)
{ return m_starter.get() != other.m_starter.get(); }
private: private:
irr::video::IVideoDriver *m_driver = nullptr;
IGUIEnvironment *m_guienv = nullptr;
IEventReceiver *m_receiver = nullptr;
ISimpleTextureSource *m_texturesource = nullptr; ISimpleTextureSource *m_texturesource = nullptr;
irr::video::IVideoDriver *m_driver; std::shared_ptr<IGUIImage> m_starter;
IGUIEnvironment *m_guienv; std::vector<button_info> m_buttons;
IEventReceiver *m_receiver;
button_info m_starter;
std::vector<std::shared_ptr<button_info>> m_buttons;
v2s32 m_upper_left; v2s32 m_upper_left;
v2s32 m_lower_right; v2s32 m_lower_right;
// show button bar
bool m_active = false; bool m_active = false;
bool m_visible = true; bool m_visible = true;
// button bar timeout
float m_timeout = 0.0f; 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; autohide_button_bar_dir m_dir = AHBB_Dir_Right_Left;
void updateVisibility();
}; };
class TouchScreenGUI class TouchScreenGUI
{ {
public: public:
TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver); TouchScreenGUI(IrrlichtDevice *device, ISimpleTextureSource *tsrc);
~TouchScreenGUI();
void translateEvent(const SEvent &event); void translateEvent(const SEvent &event);
void applyContextControls(const TouchInteractionMode &mode); void applyContextControls(const TouchInteractionMode &mode);
void init(ISimpleTextureSource *tsrc);
double getYawChange() double getYawChange()
{ {
double res = m_camera_yaw_change; double res = m_camera_yaw_change;
@ -212,22 +225,21 @@ public:
void show(); void show();
void resetHotbarRects(); void resetHotbarRects();
void registerHotbarRect(u16 index, const rect<s32> &rect); void registerHotbarRect(u16 index, const recti &rect);
std::optional<u16> getHotbarSelection(); std::optional<u16> getHotbarSelection();
private: private:
bool m_initialized = false; IrrlichtDevice *m_device = nullptr;
IrrlichtDevice *m_device; IGUIEnvironment *m_guienv = nullptr;
IGUIEnvironment *m_guienv; IEventReceiver *m_receiver = nullptr;
IEventReceiver *m_receiver; ISimpleTextureSource *m_texturesource = nullptr;
ISimpleTextureSource *m_texturesource;
v2u32 m_screensize; v2u32 m_screensize;
s32 button_size; s32 m_button_size;
double m_touchscreen_threshold; double m_touchscreen_threshold;
u16 m_long_tap_delay; 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<u16, rect<s32>> m_hotbar_rects; std::unordered_map<u16, recti> m_hotbar_rects;
std::optional<u16> m_hotbar_selection = std::nullopt; std::optional<u16> m_hotbar_selection = std::nullopt;
// value in degree // value in degree
@ -257,39 +269,25 @@ private:
bool m_fixed_joystick = false; bool m_fixed_joystick = false;
bool m_joystick_triggers_aux1 = false; bool m_joystick_triggers_aux1 = false;
bool m_draw_crosshair = false; bool m_draw_crosshair = false;
std::shared_ptr<button_info> m_joystick_btn_off = nullptr; std::shared_ptr<IGUIImage> m_joystick_btn_off;
std::shared_ptr<button_info> m_joystick_btn_bg = nullptr; std::shared_ptr<IGUIImage> m_joystick_btn_bg;
std::shared_ptr<button_info> m_joystick_btn_center = nullptr; std::shared_ptr<IGUIImage> m_joystick_btn_center;
button_info m_buttons[after_last_element_id]; std::vector<button_info> m_buttons;
// gui button detection
touch_gui_button_id getButtonID(s32 x, s32 y);
// gui button by eventID
touch_gui_button_id getButtonID(size_t eventID);
// check if a button has changed
void handleChangedButton(const SEvent &event);
// initialize a button // initialize a button
void initButton(touch_gui_button_id id, const rect<s32> &button_rect, void addButton(touch_gui_button_id id, const std::string &image,
const std::wstring &caption, bool immediate_release, const recti &rect);
float repeat_delay = BUTTON_REPEAT_DELAY);
// initialize a joystick button // initialize a joystick button
std::shared_ptr<button_info> initJoystickButton(touch_gui_button_id id, IGUIImage *makeJoystickButton(touch_gui_button_id id,
const rect<s32> &button_rect, int texture_id, const recti &rect, bool visible);
bool visible = true);
// handle a button event
void handleButtonEvent(touch_gui_button_id bID, size_t eventID, bool action);
// handle pressing hotbar items // handle pressing hotbar items
bool isHotbarButton(const SEvent &event); bool isHotbarButton(const SEvent &event);
// handle release event // handle release event
void handleReleaseEvent(size_t evt_id); void handleReleaseEvent(size_t pointer_id);
// apply joystick status // apply joystick status
void applyJoystickStatus(); void applyJoystickStatus();
@ -299,11 +297,7 @@ private:
// map to store the IDs and positions of currently pressed pointers // map to store the IDs and positions of currently pressed pointers
std::unordered_map<size_t, v2s32> m_pointer_pos; std::unordered_map<size_t, v2s32> m_pointer_pos;
// settings bar std::vector<AutoHideButtonBar> m_buttonbars;
AutoHideButtonBar m_settings_bar;
// rare controls bar
AutoHideButtonBar m_rare_controls_bar;
v2s32 getPointerPos(); v2s32 getPointerPos();
void emitMouseEvent(EMOUSE_INPUT_EVENT type); void emitMouseEvent(EMOUSE_INPUT_EVENT type);