mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 04:54:18 +02:00
TouchScreenGUI dehardcoding refactor (#14472)
This commit is contained in:
parent
b2057a5da7
commit
f2b5c35fa2
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user