mirror of
https://github.com/minetest/minetest.git
synced 2025-03-06 20:48:40 +01:00
TouchControls: touch_use_crosshair, dig/place simulation refactoring (#15800)
- get rid of simulated mouse events for digging/placing, use keyboard events instead - consistent with other simulated events, less code, no need for a pointer position - more correct: touch controls no longer break if you have custom dig/place keybindings set - move reading of "touch_use_crosshair" setting from Game to TouchControls
This commit is contained in:
parent
abcd2e0b81
commit
5e89371ecd
5 changed files with 53 additions and 63 deletions
|
@ -772,9 +772,10 @@ private:
|
|||
bool m_is_paused = false;
|
||||
|
||||
bool m_touch_simulate_aux1 = false;
|
||||
bool m_touch_use_crosshair;
|
||||
inline bool isTouchCrosshairDisabled() {
|
||||
return !m_touch_use_crosshair && camera->getCameraMode() == CAMERA_MODE_FIRST;
|
||||
inline bool isTouchShootlineUsed()
|
||||
{
|
||||
return g_touchcontrols && g_touchcontrols->isShootlineAvailable() &&
|
||||
camera->getCameraMode() == CAMERA_MODE_FIRST;
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
bool m_android_chat_open;
|
||||
|
@ -823,8 +824,6 @@ Game::Game() :
|
|||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("pause_on_lost_focus",
|
||||
&settingChangedCallback, this);
|
||||
g_settings->registerChangedCallback("touch_use_crosshair",
|
||||
&settingChangedCallback, this);
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
@ -1380,10 +1379,8 @@ bool Game::initGui()
|
|||
gui_chat_console = make_irr<GUIChatConsole>(guienv, guienv->getRootGUIElement(),
|
||||
-1, chat_backend, client, &g_menumgr);
|
||||
|
||||
if (shouldShowTouchControls()) {
|
||||
if (shouldShowTouchControls())
|
||||
g_touchcontrols = new TouchControls(device, texture_src);
|
||||
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2980,9 +2977,6 @@ void Game::updateCameraMode()
|
|||
if (player->allowed_camera_mode != CAMERA_MODE_ANY)
|
||||
camera->setCameraMode(player->allowed_camera_mode);
|
||||
|
||||
if (g_touchcontrols)
|
||||
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
|
||||
|
||||
GenericCAO *playercao = player->getCAO();
|
||||
if (playercao) {
|
||||
// Make the player visible depending on camera mode.
|
||||
|
@ -3086,7 +3080,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||
}
|
||||
shootline.end = shootline.start + camera_direction * BS * d;
|
||||
|
||||
if (g_touchcontrols && isTouchCrosshairDisabled()) {
|
||||
if (isTouchShootlineUsed()) {
|
||||
shootline = g_touchcontrols->getShootline();
|
||||
// Scale shootline to the acual distance the player can reach
|
||||
shootline.end = shootline.start +
|
||||
|
@ -4059,7 +4053,7 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
|
|||
(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
|
||||
(this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
|
||||
|
||||
if (g_touchcontrols && isTouchCrosshairDisabled())
|
||||
if (isTouchShootlineUsed())
|
||||
draw_crosshair = false;
|
||||
|
||||
this->m_rendering_engine->draw_scene(sky_color, this->m_game_ui->m_flags.show_hud,
|
||||
|
@ -4139,10 +4133,6 @@ void Game::readSettings()
|
|||
m_invert_hotbar_mouse_wheel = g_settings->getBool("invert_hotbar_mouse_wheel");
|
||||
|
||||
m_does_lost_focus_pause_game = g_settings->getBool("pause_on_lost_focus");
|
||||
|
||||
m_touch_use_crosshair = g_settings->getBool("touch_use_crosshair");
|
||||
if (g_touchcontrols)
|
||||
g_touchcontrols->setUseCrosshair(!isTouchCrosshairDisabled());
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
@ -142,6 +142,12 @@ static EKEY_CODE id_to_keycode(touch_gui_button_id id)
|
|||
|
||||
std::string key = "";
|
||||
switch (id) {
|
||||
case dig_id:
|
||||
key = "dig";
|
||||
break;
|
||||
case place_id:
|
||||
key = "place";
|
||||
break;
|
||||
case jump_id:
|
||||
key = "jump";
|
||||
break;
|
||||
|
@ -204,6 +210,7 @@ static EKEY_CODE id_to_keycode(touch_gui_button_id id)
|
|||
|
||||
|
||||
static const char *setting_names[] = {
|
||||
"touch_use_crosshair",
|
||||
"touchscreen_threshold", "touch_long_tap_delay",
|
||||
"fixed_virtual_joystick", "virtual_joystick_triggers_aux1",
|
||||
"touch_layout",
|
||||
|
@ -230,6 +237,7 @@ void TouchControls::settingChangedCallback(const std::string &name, void *data)
|
|||
|
||||
void TouchControls::readSettings()
|
||||
{
|
||||
m_use_crosshair = g_settings->getBool("touch_use_crosshair");
|
||||
m_touchscreen_threshold = g_settings->getU16("touchscreen_threshold");
|
||||
m_long_tap_delay = g_settings->getU16("touch_long_tap_delay");
|
||||
m_fixed_joystick = g_settings->getBool("fixed_virtual_joystick");
|
||||
|
@ -542,10 +550,11 @@ void TouchControls::translateEvent(const SEvent &event)
|
|||
m_move_has_really_moved = false;
|
||||
m_move_downtime = porting::getTimeMs();
|
||||
m_move_pos = touch_pos;
|
||||
// DON'T reset m_tap_state here, otherwise many short taps
|
||||
// will be ignored if you tap very fast.
|
||||
m_had_move_id = true;
|
||||
m_move_prevent_short_tap = prevent_short_tap;
|
||||
|
||||
// DON'T reset m_tap_state here, otherwise many short taps
|
||||
// will be ignored if you tap very fast.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -663,15 +672,13 @@ void TouchControls::step(float dtime)
|
|||
// Since not only the pointer position, but also the player position and
|
||||
// thus the camera position can change, it doesn't suffice to update the
|
||||
// shootline when a touch event occurs.
|
||||
// Note that the shootline isn't used if touch_use_crosshair is enabled.
|
||||
// Only updating when m_has_move_id means that the shootline will stay at
|
||||
// it's last in-world position when the player doesn't need it.
|
||||
if (!m_draw_crosshair && (m_has_move_id || m_had_move_id)) {
|
||||
v2s32 pointer_pos = getPointerPos();
|
||||
if (!m_use_crosshair && (m_has_move_id || m_had_move_id)) {
|
||||
m_shootline = m_device
|
||||
->getSceneManager()
|
||||
->getSceneCollisionManager()
|
||||
->getRayFromScreenCoordinates(pointer_pos);
|
||||
->getRayFromScreenCoordinates(m_move_pos);
|
||||
}
|
||||
m_had_move_id = false;
|
||||
}
|
||||
|
@ -734,11 +741,11 @@ void TouchControls::releaseAll()
|
|||
// Release those manually too since the change initiated by
|
||||
// handleReleaseEvent will only be applied later by applyContextControls.
|
||||
if (m_dig_pressed) {
|
||||
emitMouseEvent(EMIE_LMOUSE_LEFT_UP);
|
||||
emitKeyboardEvent(id_to_keycode(dig_id), false);
|
||||
m_dig_pressed = false;
|
||||
}
|
||||
if (m_place_pressed) {
|
||||
emitMouseEvent(EMIE_RMOUSE_LEFT_UP);
|
||||
emitKeyboardEvent(id_to_keycode(place_id), false);
|
||||
m_place_pressed = false;
|
||||
}
|
||||
}
|
||||
|
@ -753,31 +760,6 @@ void TouchControls::show()
|
|||
setVisible(true);
|
||||
}
|
||||
|
||||
v2s32 TouchControls::getPointerPos()
|
||||
{
|
||||
if (m_draw_crosshair)
|
||||
return v2s32(m_screensize.X / 2, m_screensize.Y / 2);
|
||||
// We can't just use m_pointer_pos[m_move_id] because applyContextControls
|
||||
// may emit release events after m_pointer_pos[m_move_id] is erased.
|
||||
return m_move_pos;
|
||||
}
|
||||
|
||||
void TouchControls::emitMouseEvent(EMOUSE_INPUT_EVENT type)
|
||||
{
|
||||
v2s32 pointer_pos = getPointerPos();
|
||||
|
||||
SEvent event{};
|
||||
event.EventType = EET_MOUSE_INPUT_EVENT;
|
||||
event.MouseInput.X = pointer_pos.X;
|
||||
event.MouseInput.Y = pointer_pos.Y;
|
||||
event.MouseInput.Shift = false;
|
||||
event.MouseInput.Control = false;
|
||||
event.MouseInput.ButtonStates = 0;
|
||||
event.MouseInput.Event = type;
|
||||
event.MouseInput.Simulated = true;
|
||||
m_receiver->OnEvent(event);
|
||||
}
|
||||
|
||||
void TouchControls::applyContextControls(const TouchInteractionMode &mode)
|
||||
{
|
||||
// Since the pointed thing has already been determined when this function
|
||||
|
@ -844,20 +826,20 @@ void TouchControls::applyContextControls(const TouchInteractionMode &mode)
|
|||
target_place_pressed |= now < m_place_pressed_until;
|
||||
|
||||
if (target_dig_pressed && !m_dig_pressed) {
|
||||
emitMouseEvent(EMIE_LMOUSE_PRESSED_DOWN);
|
||||
emitKeyboardEvent(id_to_keycode(dig_id), true);
|
||||
m_dig_pressed = true;
|
||||
|
||||
} else if (!target_dig_pressed && m_dig_pressed) {
|
||||
emitMouseEvent(EMIE_LMOUSE_LEFT_UP);
|
||||
emitKeyboardEvent(id_to_keycode(dig_id), false);
|
||||
m_dig_pressed = false;
|
||||
}
|
||||
|
||||
if (target_place_pressed && !m_place_pressed) {
|
||||
emitMouseEvent(EMIE_RMOUSE_PRESSED_DOWN);
|
||||
emitKeyboardEvent(id_to_keycode(place_id), true);
|
||||
m_place_pressed = true;
|
||||
|
||||
} else if (!target_place_pressed && m_place_pressed) {
|
||||
emitMouseEvent(EMIE_RMOUSE_LEFT_UP);
|
||||
emitKeyboardEvent(id_to_keycode(place_id), false);
|
||||
m_place_pressed = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@ public:
|
|||
return res;
|
||||
}
|
||||
|
||||
bool isShootlineAvailable() { return !m_use_crosshair; }
|
||||
|
||||
/**
|
||||
* Returns a line which describes what the player is pointing at.
|
||||
* The starting point and looking direction are significant,
|
||||
|
@ -100,6 +102,9 @@ public:
|
|||
* the player can reach.
|
||||
* The line starts at the camera and ends on the camera's far plane.
|
||||
* The coordinates do not contain the camera offset.
|
||||
*
|
||||
* This may only be used if isShootlineAvailable returns true.
|
||||
* Otherwise, the normal crosshair must be used.
|
||||
*/
|
||||
line3d<f32> getShootline() { return m_shootline; }
|
||||
|
||||
|
@ -107,7 +112,6 @@ public:
|
|||
float getJoystickSpeed() { return m_joystick_speed; }
|
||||
|
||||
void step(float dtime);
|
||||
inline void setUseCrosshair(bool use_crosshair) { m_draw_crosshair = use_crosshair; }
|
||||
|
||||
void setVisible(bool visible);
|
||||
void hide();
|
||||
|
@ -132,6 +136,7 @@ private:
|
|||
s32 m_button_size;
|
||||
|
||||
// cached settings
|
||||
bool m_use_crosshair;
|
||||
double m_touchscreen_threshold;
|
||||
u16 m_long_tap_delay;
|
||||
bool m_fixed_joystick;
|
||||
|
@ -143,9 +148,6 @@ private:
|
|||
ButtonLayout m_layout;
|
||||
void applyLayout(const ButtonLayout &layout);
|
||||
|
||||
// not read from a setting, but set by Game via setUseCrosshair
|
||||
bool m_draw_crosshair = false;
|
||||
|
||||
std::unordered_map<u16, recti> m_hotbar_rects;
|
||||
std::optional<u16> m_hotbar_selection = std::nullopt;
|
||||
|
||||
|
@ -157,6 +159,8 @@ private:
|
|||
* A line starting at the camera and pointing towards the selected object.
|
||||
* The line ends on the camera's far plane.
|
||||
* The coordinates do not contain the camera offset.
|
||||
*
|
||||
* Only valid if !m_use_crosshair
|
||||
*/
|
||||
line3d<f32> m_shootline;
|
||||
|
||||
|
@ -164,7 +168,9 @@ private:
|
|||
size_t m_move_id;
|
||||
bool m_move_has_really_moved = false;
|
||||
u64 m_move_downtime = 0;
|
||||
// m_move_pos stays valid even after m_move_id has been released.
|
||||
// m_move_pos stays valid even after the m_move_id pointer has been
|
||||
// released and m_pointer_pos[m_move_id] has been erased
|
||||
// (or even overwritten by a new pointer reusing the same id).
|
||||
v2s32 m_move_pos;
|
||||
// This is needed so that we don't miss if m_has_move_id is true for less
|
||||
// than one client step, i.e. press and release happen in the same step.
|
||||
|
@ -236,8 +242,6 @@ private:
|
|||
// map to store the IDs and positions of currently pressed pointers
|
||||
std::unordered_map<size_t, v2s32> m_pointer_pos;
|
||||
|
||||
v2s32 getPointerPos();
|
||||
void emitMouseEvent(EMOUSE_INPUT_EVENT type);
|
||||
TouchInteractionMode m_last_mode = TouchInteractionMode_END;
|
||||
TapState m_tap_state = TapState::None;
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "IGUIStaticText.h"
|
||||
|
||||
const char *button_names[] = {
|
||||
"dig",
|
||||
"place",
|
||||
|
||||
"jump",
|
||||
"sneak",
|
||||
"zoom",
|
||||
|
@ -41,6 +44,9 @@ const char *button_names[] = {
|
|||
|
||||
// compare with GUIKeyChangeMenu::init_keys
|
||||
const char *button_titles[] = {
|
||||
N_("Dig/punch/use"),
|
||||
N_("Place/use"),
|
||||
|
||||
N_("Jump"),
|
||||
N_("Sneak"),
|
||||
N_("Zoom"),
|
||||
|
@ -67,6 +73,9 @@ const char *button_titles[] = {
|
|||
};
|
||||
|
||||
const char *button_image_names[] = {
|
||||
"",
|
||||
"",
|
||||
|
||||
"jump_btn.png",
|
||||
"down.png",
|
||||
"zoom.png",
|
||||
|
@ -123,7 +132,8 @@ void ButtonMeta::setPos(v2s32 pos, v2u32 screensize, s32 button_size)
|
|||
|
||||
bool ButtonLayout::isButtonAllowed(touch_gui_button_id id)
|
||||
{
|
||||
return id != joystick_off_id && id != joystick_bg_id && id != joystick_center_id &&
|
||||
return id != dig_id && id != place_id &&
|
||||
id != joystick_off_id && id != joystick_bg_id && id != joystick_center_id &&
|
||||
id != touch_gui_button_id_END;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,11 @@ namespace irr::video
|
|||
|
||||
enum touch_gui_button_id : u8
|
||||
{
|
||||
jump_id = 0,
|
||||
// these two are no actual buttons ... yet
|
||||
dig_id = 0,
|
||||
place_id,
|
||||
|
||||
jump_id,
|
||||
sneak_id,
|
||||
zoom_id,
|
||||
aux1_id,
|
||||
|
|
Loading…
Add table
Reference in a new issue