mirror of
https://github.com/minetest/minetest.git
synced 2024-12-23 22:52:25 +01:00
Add crosshair support for Android (#7865)
If enabled, a crosshair will be shown to select object. This will give Android players a way to play like they play on desktop. On third-person back camera mode, player is forced to use crosshair. On third-person front camera mode, player is unable to select anything. Co-authored-by: ROllerozxa <temporaryemail4meh+github@gmail.com> Co-authored-by: rubenwardy <rw@rubenwardy.com>
This commit is contained in:
parent
b1233056b7
commit
3978b9b8ed
@ -308,10 +308,6 @@ local function handle_settings_buttons(this, fields, tabname, tabdata)
|
||||
core.show_keys_menu()
|
||||
return true
|
||||
end
|
||||
if fields["cb_touchscreen_target"] then
|
||||
core.settings:set("touchtarget", fields["cb_touchscreen_target"])
|
||||
return true
|
||||
end
|
||||
|
||||
--Note dropdowns have to be handled LAST!
|
||||
local ddhandled = false
|
||||
|
@ -117,6 +117,10 @@ mouse_sensitivity (Mouse sensitivity) float 0.2 0.001 10.0
|
||||
# The length in pixels it takes for touch screen interaction to start.
|
||||
touchscreen_threshold (Touch screen threshold) int 20 0 100
|
||||
|
||||
# Use crosshair to select object instead of whole screen.
|
||||
# If enabled, a crosshair will be shown and will be used for selecting object.
|
||||
touch_use_crosshair (Use crosshair for touch screen) bool false
|
||||
|
||||
# (Android) Fixes the position of virtual joystick.
|
||||
# If disabled, virtual joystick will center to first-touch's position.
|
||||
fixed_virtual_joystick (Fixed virtual joystick) bool false
|
||||
|
@ -920,6 +920,10 @@ private:
|
||||
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
bool m_cache_hold_aux1;
|
||||
bool m_touch_use_crosshair;
|
||||
inline bool isNoCrosshairAllowed() {
|
||||
return !m_touch_use_crosshair && camera->getCameraMode() == CAMERA_MODE_FIRST;
|
||||
}
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
bool m_android_chat_open;
|
||||
@ -1051,6 +1055,10 @@ bool Game::startup(bool *kill,
|
||||
m_invert_mouse = g_settings->getBool("invert_mouse");
|
||||
m_first_loop_after_window_activation = true;
|
||||
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
m_touch_use_crosshair = g_settings->getBool("touch_use_crosshair");
|
||||
#endif
|
||||
|
||||
g_client_translations->clear();
|
||||
|
||||
// address can change if simple_singleplayer_mode
|
||||
@ -2981,6 +2989,11 @@ void Game::updateCamera(f32 dtime)
|
||||
|
||||
camera->toggleCameraMode();
|
||||
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
if (g_touchscreengui)
|
||||
g_touchscreengui->setUseCrosshair(!isNoCrosshairAllowed());
|
||||
#endif
|
||||
|
||||
// Make the player visible depending on camera mode.
|
||||
playercao->updateMeshCulling();
|
||||
playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST);
|
||||
@ -3091,16 +3104,14 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
||||
shootline.end = shootline.start + camera_direction * BS * d;
|
||||
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
|
||||
if ((g_settings->getBool("touchtarget")) && (g_touchscreengui)) {
|
||||
if (g_touchscreengui && isNoCrosshairAllowed()) {
|
||||
shootline = g_touchscreengui->getShootline();
|
||||
// Scale shootline to the acual distance the player can reach
|
||||
shootline.end = shootline.start
|
||||
+ shootline.getVector().normalize() * BS * d;
|
||||
shootline.end = shootline.start +
|
||||
shootline.getVector().normalize() * BS * d;
|
||||
shootline.start += intToFloat(camera_offset, BS);
|
||||
shootline.end += intToFloat(camera_offset, BS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
PointedThing pointed = updatePointedThing(shootline,
|
||||
@ -3991,10 +4002,8 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
|
||||
(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
|
||||
(camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
try {
|
||||
draw_crosshair = !g_settings->getBool("touchtarget");
|
||||
} catch (SettingNotFoundException) {
|
||||
}
|
||||
if (isNoCrosshairAllowed())
|
||||
draw_crosshair = false;
|
||||
#endif
|
||||
m_rendering_engine->draw_scene(skycolor, m_game_ui->m_flags.show_hud,
|
||||
m_game_ui->m_flags.show_minimap, draw_wield_tool, draw_crosshair);
|
||||
|
@ -465,8 +465,8 @@ void set_default_settings()
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TOUCHSCREENGUI
|
||||
settings->setDefault("touchtarget", "true");
|
||||
settings->setDefault("touchscreen_threshold","20");
|
||||
settings->setDefault("touch_use_crosshair", "false");
|
||||
settings->setDefault("fixed_virtual_joystick", "false");
|
||||
settings->setDefault("virtual_joystick_triggers_aux1", "false");
|
||||
settings->setDefault("clickable_chat_weblinks", "false");
|
||||
|
@ -684,6 +684,10 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id)
|
||||
translated->MouseInput.Control = false;
|
||||
translated->MouseInput.ButtonStates = 0;
|
||||
translated->MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
|
||||
if (m_draw_crosshair) {
|
||||
translated->MouseInput.X = m_screensize.X / 2;
|
||||
translated->MouseInput.Y = m_screensize.Y / 2;
|
||||
}
|
||||
m_receiver->OnEvent(*translated);
|
||||
delete translated;
|
||||
} else {
|
||||
@ -805,6 +809,8 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||
m_move_downtime = porting::getTimeMs();
|
||||
m_move_downlocation = v2s32(event.TouchInput.X, event.TouchInput.Y);
|
||||
m_move_sent_as_mouse_event = false;
|
||||
if (m_draw_crosshair)
|
||||
m_move_downlocation = v2s32(m_screensize.X / 2, m_screensize.Y / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -823,9 +829,8 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||
return;
|
||||
|
||||
if (m_has_move_id) {
|
||||
if ((event.TouchInput.ID == m_move_id) &&
|
||||
(!m_move_sent_as_mouse_event)) {
|
||||
|
||||
if (event.TouchInput.ID == m_move_id &&
|
||||
(!m_move_sent_as_mouse_event || m_draw_crosshair)) {
|
||||
double distance = sqrt(
|
||||
(m_pointerpos[event.TouchInput.ID].X - event.TouchInput.X) *
|
||||
(m_pointerpos[event.TouchInput.ID].X - event.TouchInput.X) +
|
||||
@ -841,6 +846,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||
// update camera_yaw and camera_pitch
|
||||
s32 dx = X - m_pointerpos[event.TouchInput.ID].X;
|
||||
s32 dy = Y - m_pointerpos[event.TouchInput.ID].Y;
|
||||
m_pointerpos[event.TouchInput.ID] = v2s32(X, Y);
|
||||
|
||||
// adapt to similar behaviour as pc screen
|
||||
const double d = g_settings->getFloat("mouse_sensitivity", 0.001f, 10.0f) * 3.0f;
|
||||
@ -849,11 +855,11 @@ void TouchScreenGUI::translateEvent(const SEvent &event)
|
||||
m_camera_pitch = MYMIN(MYMAX(m_camera_pitch + (dy * d), -180), 180);
|
||||
|
||||
// update shootline
|
||||
// no need to update (X, Y) when using crosshair since the shootline is not used
|
||||
m_shootline = m_device
|
||||
->getSceneManager()
|
||||
->getSceneCollisionManager()
|
||||
->getRayFromScreenCoordinates(v2s32(X, Y));
|
||||
m_pointerpos[event.TouchInput.ID] = v2s32(X, Y);
|
||||
}
|
||||
} else if ((event.TouchInput.ID == m_move_id) &&
|
||||
(m_move_sent_as_mouse_event)) {
|
||||
@ -1010,11 +1016,17 @@ bool TouchScreenGUI::doubleTapDetection()
|
||||
if (distance > (20 + m_touchscreen_threshold))
|
||||
return false;
|
||||
|
||||
v2s32 mPos = v2s32(m_key_events[0].x, m_key_events[0].y);
|
||||
if (m_draw_crosshair) {
|
||||
mPos.X = m_screensize.X / 2;
|
||||
mPos.Y = m_screensize.Y / 2;
|
||||
}
|
||||
|
||||
auto *translated = new SEvent();
|
||||
memset(translated, 0, sizeof(SEvent));
|
||||
translated->EventType = EET_MOUSE_INPUT_EVENT;
|
||||
translated->MouseInput.X = m_key_events[0].x;
|
||||
translated->MouseInput.Y = m_key_events[0].y;
|
||||
translated->MouseInput.X = mPos.X;
|
||||
translated->MouseInput.Y = mPos.Y;
|
||||
translated->MouseInput.Shift = false;
|
||||
translated->MouseInput.Control = false;
|
||||
translated->MouseInput.ButtonStates = EMBSM_RIGHT;
|
||||
@ -1023,7 +1035,7 @@ bool TouchScreenGUI::doubleTapDetection()
|
||||
m_shootline = m_device
|
||||
->getSceneManager()
|
||||
->getSceneCollisionManager()
|
||||
->getRayFromScreenCoordinates(v2s32(m_key_events[0].x, m_key_events[0].y));
|
||||
->getRayFromScreenCoordinates(mPos);
|
||||
|
||||
translated->MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN;
|
||||
verbosestream << "TouchScreenGUI::translateEvent right click press" << std::endl;
|
||||
@ -1124,17 +1136,23 @@ void TouchScreenGUI::step(float dtime)
|
||||
u64 delta = porting::getDeltaMs(m_move_downtime, porting::getTimeMs());
|
||||
|
||||
if (delta > MIN_DIG_TIME_MS) {
|
||||
s32 mX = m_move_downlocation.X;
|
||||
s32 mY = m_move_downlocation.Y;
|
||||
if (m_draw_crosshair) {
|
||||
mX = m_screensize.X / 2;
|
||||
mY = m_screensize.Y / 2;
|
||||
}
|
||||
m_shootline = m_device
|
||||
->getSceneManager()
|
||||
->getSceneCollisionManager()
|
||||
->getRayFromScreenCoordinates(
|
||||
v2s32(m_move_downlocation.X,m_move_downlocation.Y));
|
||||
v2s32(mX, mY));
|
||||
|
||||
SEvent translated;
|
||||
memset(&translated, 0, sizeof(SEvent));
|
||||
translated.EventType = EET_MOUSE_INPUT_EVENT;
|
||||
translated.MouseInput.X = m_move_downlocation.X;
|
||||
translated.MouseInput.Y = m_move_downlocation.Y;
|
||||
translated.MouseInput.X = mX;
|
||||
translated.MouseInput.Y = mY;
|
||||
translated.MouseInput.Shift = false;
|
||||
translated.MouseInput.Control = false;
|
||||
translated.MouseInput.ButtonStates = EMBSM_LEFT;
|
||||
|
@ -194,6 +194,7 @@ public:
|
||||
void step(float dtime);
|
||||
void resetHud();
|
||||
void registerHudItem(int index, const rect<s32> &rect);
|
||||
inline void setUseCrosshair(bool use_crosshair) { m_draw_crosshair = use_crosshair; }
|
||||
void Toggle(bool visible);
|
||||
|
||||
void hide();
|
||||
@ -240,6 +241,7 @@ private:
|
||||
bool m_joystick_has_really_moved = false;
|
||||
bool m_fixed_joystick = false;
|
||||
bool m_joystick_triggers_aux1 = false;
|
||||
bool m_draw_crosshair = false;
|
||||
button_info *m_joystick_btn_off = nullptr;
|
||||
button_info *m_joystick_btn_bg = nullptr;
|
||||
button_info *m_joystick_btn_center = nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user