1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-27 17:28:41 +00:00

Implement an editor to customize the touchscreen controls (#14933)

- The editor is accessible via the pause menu and the settings menu.
- Buttons can be moved via drag & drop.
- Buttons can be added/removed. The grid menu added by #14918 is used to show
  all buttons not included in the layout.
- Custom layouts are responsive and adapt to changed screen size / DPI /
  hud_scaling.
- The layout is saved as JSON in the "touch_layout" setting.
This commit is contained in:
grorp 2024-11-24 11:33:39 +01:00 committed by GitHub
parent 4faa16fe0d
commit 6a1d22b2c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 1122 additions and 195 deletions

View file

@ -5,11 +5,8 @@
#pragma once
#include "IGUIStaticText.h"
#include "irrlichttypes.h"
#include <IEventReceiver.h>
#include <IGUIImage.h>
#include <IGUIEnvironment.h>
#include "IEventReceiver.h"
#include <memory>
#include <optional>
@ -17,41 +14,29 @@
#include <vector>
#include "itemdef.h"
#include "client/game.h"
#include "touchscreenlayout.h"
#include "util/basic_macros.h"
#include "client/texturesource.h"
namespace irr
{
class IrrlichtDevice;
namespace gui
{
class IGUIEnvironment;
class IGUIImage;
class IGUIStaticText;
}
namespace video
{
class IVideoDriver;
}
}
class ISimpleTextureSource;
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 <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
{
None,
@ -59,36 +44,6 @@ enum class TapState
LongTap,
};
enum touch_gui_button_id
{
jump_id = 0,
sneak_id,
zoom_id,
aux1_id,
overflow_id,
// usually in the "settings bar"
fly_id,
noclip_id,
fast_id,
debug_id,
camera_id,
range_id,
minimap_id,
toggle_chat_id,
// usually in the "rare controls bar"
chat_id,
inventory_id,
drop_id,
exit_id,
// the joystick
joystick_off_id,
joystick_bg_id,
joystick_center_id,
};
#define BUTTON_REPEAT_DELAY 0.5f
#define BUTTON_REPEAT_INTERVAL 0.333f
@ -168,6 +123,9 @@ public:
bool isStatusTextOverriden() { return m_overflow_open; }
IGUIStaticText *getStatusText() { return m_status_text.get(); }
ButtonLayout getLayout() { return m_layout; }
void applyLayout(const ButtonLayout &layout);
private:
IrrlichtDevice *m_device = nullptr;
IGUIEnvironment *m_guienv = nullptr;
@ -233,13 +191,14 @@ private:
void releaseAll();
// initialize a button
bool mayAddButton(touch_gui_button_id id);
void addButton(std::vector<button_info> &buttons,
touch_gui_button_id id, const std::string &image,
const recti &rect, bool visible=true);
const recti &rect, bool visible);
void addToggleButton(std::vector<button_info> &buttons,
touch_gui_button_id id,
const std::string &image_1, const std::string &image_2,
const recti &rect, bool visible=true);
const recti &rect, bool visible);
IGUIImage *makeButtonDirect(touch_gui_button_id id,
const recti &rect, bool visible);
@ -268,6 +227,8 @@ private:
bool m_place_pressed = false;
u64 m_place_pressed_until = 0;
ButtonLayout m_layout;
};
extern TouchControls *g_touchcontrols;