diff --git a/README.md b/README.md index 318dd35c8..14408bbf4 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ General options and their default values: RUN_IN_PLACE=FALSE - Create a portable install (worlds, settings etc. in current directory) USE_GPROF=FALSE - Enable profiling using GProf VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> MultiCraft 0.4.9-foobar) + ENABLE_TOUCH=FALSE - Enable Touchscreen support (requires support by IrrlichtMt) Library specific options: diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index f800f71ab..aff93227b 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -910,6 +910,9 @@ screenshot_quality (Screenshot quality) int 0 0 100 # Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens. screen_dpi (DPI) int 72 1 +# Adjust the detected display density, used for scaling UI elements. +display_density_factor (Display Density Scaling Factor) float 1 + # Windows systems only: Start Minetest with the command line window in the background. # Contains the same information as the file debug.txt (default name). enable_console (Enable console window) bool false diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8636916b7..c925d348e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -102,6 +102,12 @@ endif() option(ENABLE_GLES "Use OpenGL ES instead of OpenGL" FALSE) mark_as_advanced(ENABLE_GLES) + +option(ENABLE_TOUCH "Enable Touchscreen support" FALSE) +if(ENABLE_TOUCH) + add_definitions(-DHAVE_TOUCHSCREENGUI) +endif() + if(BUILD_CLIENT) if(ENABLE_GLES) find_package(OpenGLES2 REQUIRED) diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 9dbf19fe2..64bb95837 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -46,9 +46,6 @@ namespace irr { }; } #endif -#if defined(__ANDROID__) || defined(__IOS__) - #include "porting.h" -#endif /* mainmenumanager.h */ @@ -161,8 +158,8 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args) skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255, 0, 0, 0)); skin->setColor(gui::EGDC_HIGH_LIGHT, video::SColor(255, 70, 120, 50)); skin->setColor(gui::EGDC_HIGH_LIGHT_TEXT, video::SColor(255, 255, 255, 255)); -#if defined(__ANDROID__) || defined(__IOS__) - float density = porting::getDisplayDensity(); +#ifdef HAVE_TOUCHSCREENGUI + float density = RenderingEngine::getDisplayDensity(); skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density)); skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(14.0f * density)); skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density)); diff --git a/src/client/game.cpp b/src/client/game.cpp index c00e6e04d..db1b07dc6 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -927,9 +927,10 @@ private: bool m_does_lost_focus_pause_game = false; int m_reset_HW_buffer_counter = 0; - -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI bool m_cache_hold_aux1; +#endif +#if defined(__ANDROID__) || defined(__IOS__) bool m_android_chat_open; #endif }; @@ -967,7 +968,7 @@ Game::Game() : readSettings(); -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI m_cache_hold_aux1 = false; // This is initialised properly later #endif @@ -1091,7 +1092,7 @@ void Game::run() set_light_table(g_settings->getFloat("display_gamma")); -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI m_cache_hold_aux1 = g_settings->getBool("fast_move") && client->checkPrivilege("fast"); #endif @@ -1858,6 +1859,7 @@ void Game::processUserInput(f32 dtime) else if (g_touchscreengui) { /* on touchscreengui step may generate own input events which ain't * what we want in case we just did clear them */ + g_touchscreengui->show(); g_touchscreengui->step(dtime); } #endif @@ -2213,7 +2215,7 @@ void Game::toggleFast() m_game_ui->showTranslatedStatusText("Fast mode disabled"); } -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI m_cache_hold_aux1 = fast_move && has_fast_privs; #endif } @@ -2527,10 +2529,10 @@ void Game::updatePlayerControl(const CameraOrientation &cam) ( (u32)(isKeyDown(KeyType::ZOOM) & 0x1) << 9) ); -#if defined(__ANDROID__) || defined(__IOS__) - /* For Android, simulate holding down AUX1 (fast move) if the user has +#ifdef HAVE_TOUCHSCREENGUI + /* For touch, simulate holding down AUX1 (fast move) if the user has * the fast_move setting toggled on. If there is an aux1 key defined for - * Android then its meaning is inverted (i.e. holding aux1 means walk and + * touch then its meaning is inverted (i.e. holding aux1 means walk and * not fast) */ if (m_cache_hold_aux1 && !porting::hasRealKeyboard()) { @@ -4290,7 +4292,7 @@ void Game::showDeathFormspec() #define GET_KEY_NAME(KEY) gettext(getKeySetting(#KEY).name()) void Game::showPauseMenu() { -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI static const std::string control_text = strgettext("Default Controls:\n" "No menu visible:\n" "- single tap: button activate\n" diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index 2f2fb704c..9620302ef 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -763,7 +763,7 @@ static float calcDisplayDensity() float RenderingEngine::getDisplayDensity() { static float cached_display_density = calcDisplayDensity(); - return cached_display_density; + return cached_display_density * g_settings->getFloat("display_density_factor"); } #elif defined(_WIN32) @@ -791,14 +791,14 @@ float RenderingEngine::getDisplayDensity() display_density = calcDisplayDensity(get_video_driver()); cached = true; } - return display_density; + return display_density * g_settings->getFloat("display_density_factor"); } #else float RenderingEngine::getDisplayDensity() { - return g_settings->getFloat("screen_dpi") / 96.0; + return (g_settings->getFloat("screen_dpi") / 96.0) * g_settings->getFloat("display_density_factor"); } #endif diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index aa75b2b8c..a35d891a1 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -487,6 +487,7 @@ void set_default_settings() settings->setDefault("high_precision_fpu", "true"); settings->setDefault("enable_console", "false"); settings->setDefault("screen_dpi", "72"); + settings->setDefault("display_density_factor", "1"); settings->setDefault("mainmenu_last_selected_world", "1"); settings->setDefault("device_is_tablet", "false"); @@ -509,13 +510,16 @@ void set_default_settings() settings->setDefault("serverlist_url", "servers.multicraft.world"); #endif - // Mobile Platform -#if defined(__ANDROID__) || defined(__IOS__) - settings->setDefault("fullscreen", "true"); +#ifdef HAVE_TOUCHSCREENGUI settings->setDefault("touchtarget", "true"); settings->setDefault("touchscreen_threshold", "20"); settings->setDefault("fixed_virtual_joystick", "true"); settings->setDefault("virtual_joystick_triggers_aux", "false"); +#endif + + // Mobile Platform +#if defined(__ANDROID__) || defined(__IOS__) + settings->setDefault("fullscreen", "true"); settings->setDefault("emergequeue_limit_diskonly", "16"); settings->setDefault("emergequeue_limit_generate", "16"); settings->setDefault("curl_verify_cert", "false"); diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index fdd36914a..af007648f 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1,3 +1,8 @@ +set(extra_gui_SRCS "") +if(ENABLE_TOUCH) + set(extra_gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/touchscreengui.cpp) +endif() + set(gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/guiAnimatedImage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiBackgroundImage.cpp @@ -26,5 +31,6 @@ set(gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/intlGUIEditBox.cpp ${CMAKE_CURRENT_SOURCE_DIR}/modalMenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/profilergraph.cpp + ${extra_gui_SRCS} PARENT_SCOPE ) diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp index 7c271149f..879ee593b 100644 --- a/src/gui/guiConfirmRegistration.cpp +++ b/src/gui/guiConfirmRegistration.cpp @@ -28,6 +28,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "intlGUIEditBox.h" #include "porting.h" +#ifdef HAVE_TOUCHSCREENGUI + #include "client/renderingengine.h" +#endif + #include "gettext.h" // Continuing from guiPasswordChange.cpp @@ -45,7 +49,7 @@ GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env, m_client(client), m_playername(playername), m_password(password), m_aborted(aborted), m_tsrc(tsrc) { -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI m_touchscreen_visible = false; #endif } @@ -73,8 +77,8 @@ void GUIConfirmRegistration::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ -#ifdef __ANDROID__ - const float s = m_gui_scale * porting::getDisplayDensity() / 2; +#ifdef HAVE_TOUCHSCREENGUI + const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2; #else const float s = m_gui_scale; #endif diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index e956f4086..07ebad44c 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -309,7 +309,7 @@ void GUIFormSpecMenu::parseSize(parserData* data, const std::string &element) data->invsize.Y = MYMAX(0, stof(parts[1])); lockSize(false); -#if !defined(__ANDROID__) && !defined(__IOS__) +#ifndef HAVE_TOUCHSCREENGUI if (parts.size() == 3) { if (parts[2] == "true") { lockSize(true,v2u32(800,600)); @@ -3317,7 +3317,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) ((15.0 / 13.0) * (0.85 + mydata.invsize.Y)); } -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI // In Android, the preferred imgsize should be larger to accommodate the // smaller screensize. double prefer_imgsize = padded_screensize.Y / 10 * gui_scaling; @@ -3784,7 +3784,7 @@ void GUIFormSpecMenu::showTooltip(const std::wstring &text, v2u32 screenSize = Environment->getVideoDriver()->getScreenSize(); int tooltip_offset_x = m_btn_height; int tooltip_offset_y = m_btn_height; -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI tooltip_offset_x *= 3; tooltip_offset_y = 0; if (m_pointer.X > (s32)screenSize.X / 2) diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index de1b2e6a3..0e1316f64 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -120,7 +120,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { removeChildren(); -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2; #elif defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) const float s = m_gui_scale * RenderingEngine::getDisplayDensity() * 1.5; diff --git a/src/gui/guiPasswordChange.cpp b/src/gui/guiPasswordChange.cpp index cf6ac4b4e..e72f8acaa 100644 --- a/src/gui/guiPasswordChange.cpp +++ b/src/gui/guiPasswordChange.cpp @@ -25,6 +25,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#ifdef HAVE_TOUCHSCREENGUI + #include "client/renderingengine.h" +#endif + #include "porting.h" #include "gettext.h" #include "client/renderingengine.h" @@ -80,8 +84,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ -#if defined(__ANDROID__) || defined(__IOS__) - const float s = m_gui_scale * porting::getDisplayDensity() / 2; +#ifdef HAVE_TOUCHSCREENGUI + const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2; #elif defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) const float s = m_gui_scale * RenderingEngine::getDisplayDensity() * 1.5; #else diff --git a/src/gui/guiTable.cpp b/src/gui/guiTable.cpp index fdcf6fcd9..c9715b289 100644 --- a/src/gui/guiTable.cpp +++ b/src/gui/guiTable.cpp @@ -81,7 +81,7 @@ GUITable::GUITable(gui::IGUIEnvironment *env, float gui_scaling = g_settings->getFloat("gui_scaling"); scale = density * gui_scaling; core::rect relative_rect = m_scrollbar->getRelativePosition(); - s32 width = (relative_rect.getWidth() / (2.0 / 3.0)) * density * + s32 width = (relative_rect.getWidth() / (2.0 / 3.0)) * gui_scaling; m_scrollbar->setRelativePosition(core::rect( relative_rect.LowerRightCorner.X-width,relative_rect.UpperLeftCorner.Y, diff --git a/src/gui/guiVolumeChange.cpp b/src/gui/guiVolumeChange.cpp index 4d7195405..fd6db660e 100644 --- a/src/gui/guiVolumeChange.cpp +++ b/src/gui/guiVolumeChange.cpp @@ -75,7 +75,9 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize) /* Calculate new sizes and positions */ -#if defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI + const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2; +#elif defined(__MACH__) && defined(__APPLE__) && !defined(__IOS__) const float s = m_gui_scale * RenderingEngine::getDisplayDensity() * 1.5; #else const float s = m_gui_scale; diff --git a/src/gui/modalMenu.cpp b/src/gui/modalMenu.cpp index 35aa0a6c6..ff5fadb6d 100644 --- a/src/gui/modalMenu.cpp +++ b/src/gui/modalMenu.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef HAVE_TOUCHSCREENGUI #include "touchscreengui.h" +#include "client/renderingengine.h" #endif // clang-format off @@ -40,8 +41,8 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, m_remap_dbl_click(remap_dbl_click) { m_gui_scale = g_settings->getFloat("gui_scaling"); -#if defined(__ANDROID__) || defined(__IOS__) - float d = porting::getDisplayDensity(); +#ifdef HAVE_TOUCHSCREENGUI + float d = RenderingEngine::getDisplayDensity(); m_gui_scale *= 1.1 - 0.3 * d + 0.2 * d * d; #endif setVisible(true); @@ -183,7 +184,7 @@ static bool isChild(gui::IGUIElement *tocheck, gui::IGUIElement *parent) return false; } -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI bool GUIModalMenu::simulateMouseEvent( gui::IGUIElement *target, ETOUCH_INPUT_EVENT touch_event) @@ -217,6 +218,8 @@ bool GUIModalMenu::simulateMouseEvent( void GUIModalMenu::enter(gui::IGUIElement *hovered) { + if (!hovered) + return; sanity_check(!m_hovered); m_hovered.grab(hovered); SEvent gui_event{}; @@ -287,7 +290,9 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) return retval; } } +#endif +#ifdef HAVE_TOUCHSCREENGUI if (event.EventType == EET_TOUCH_INPUT_EVENT) { irr_ptr holder; holder.grab(this); // keep this alive until return (it might be dropped downstream [?]) diff --git a/src/gui/modalMenu.h b/src/gui/modalMenu.h index 895f91dfc..8762b1d81 100644 --- a/src/gui/modalMenu.h +++ b/src/gui/modalMenu.h @@ -75,10 +75,10 @@ protected: v2u32 m_screensize_old; float m_gui_scale; #if defined(__ANDROID__) || defined(__IOS__) - v2s32 m_down_pos; std::string m_jni_field_name; #endif #ifdef HAVE_TOUCHSCREENGUI + v2s32 m_down_pos; bool m_touchscreen_visible = true; #endif @@ -102,7 +102,7 @@ private: // wants to launch other menus bool m_allow_focus_removal = false; -#if defined(__ANDROID__) || defined(__IOS__) +#ifdef HAVE_TOUCHSCREENGUI irr_ptr m_hovered; bool simulateMouseEvent(gui::IGUIElement *target, ETOUCH_INPUT_EVENT touch_event); diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index 316b592b2..5c0893893 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "porting.h" #include "client/guiscalingfilter.h" +#include "client/renderingengine.h" #include #include @@ -438,7 +439,7 @@ TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver) m_joystick_triggers_special1 = g_settings->getBool("virtual_joystick_triggers_aux"); m_screensize = m_device->getVideoDriver()->getScreenSize(); button_size = MYMIN(m_screensize.Y / 4.5f, - porting::getDisplayDensity() * + RenderingEngine::getDisplayDensity() * g_settings->getFloat("hud_scaling") * 65.0f); } @@ -745,9 +746,9 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id) if (button != after_last_element_id) { // handle button events handleButtonEvent(button, evt_id, false); - } else if (evt_id == m_move_id) { + } else if (m_has_move_id && evt_id == m_move_id) { // handle the point used for moving view - m_move_id = -1; + m_has_move_id = false; // if this pointer issued a mouse event issue symmetric release here if (m_move_sent_as_mouse_event) { @@ -784,8 +785,8 @@ void TouchScreenGUI::handleReleaseEvent(size_t evt_id) } // handle joystick - else if (evt_id == m_joystick_id) { - m_joystick_id = -1; + else if (m_has_joystick_id && evt_id == m_joystick_id) { + m_has_joystick_id = false; // reset joystick for (unsigned int i = 0; i < 4; i++) @@ -931,7 +932,8 @@ void TouchScreenGUI::translateEvent(const SEvent &event) : event.TouchInput.X < m_screensize.X / 3.0f; if (inside_joystick) { // If we don't already have a starting point for joystick make this the one. - if (m_joystick_id == -1) { + if (!m_has_joystick_id) { + m_has_joystick_id = true; m_joystick_id = event.TouchInput.ID; m_joystick_has_really_moved = false; @@ -953,7 +955,8 @@ void TouchScreenGUI::translateEvent(const SEvent &event) } } else { // If we don't already have a moving point make this the moving one. - if (m_move_id == -1) { + if (!m_has_move_id) { + m_has_move_id = true; m_move_id = event.TouchInput.ID; m_move_has_really_moved = false; m_move_downtime = porting::getTimeMs(); @@ -976,7 +979,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) v2s32(event.TouchInput.X, event.TouchInput.Y)) return; - if (m_move_id != -1) { + if (m_has_move_id) { if ((event.TouchInput.ID == m_move_id) && (!m_move_sent_as_mouse_event)) { @@ -1019,7 +1022,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) } } - if (m_joystick_id != -1 && event.TouchInput.ID == m_joystick_id) { + if (m_has_joystick_id && event.TouchInput.ID == m_joystick_id) { s32 X = event.TouchInput.X; s32 Y = event.TouchInput.Y; @@ -1041,7 +1044,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) } } - if (m_move_id == -1 && m_joystick_id == -1) + if (!m_has_move_id && !m_has_joystick_id) handleChangedButton(event); } } @@ -1175,6 +1178,10 @@ void TouchScreenGUI::step(float dtime) if (!button.ids.empty()) { button.repeatcounter += dtime; + // in case we're moving around digging does not happen + if (m_has_move_id) + m_move_has_really_moved = true; + if (button.repeatcounter < button.repeatdelay) continue; @@ -1200,7 +1207,7 @@ void TouchScreenGUI::step(float dtime) } // if a new placed pointer isn't moved for some time start digging - if ((m_move_id != -1) && + if (m_has_move_id && (!m_move_has_really_moved) && (!m_move_sent_as_mouse_event)) { u64 delta = porting::getDeltaMs(m_move_downtime, porting::getTimeMs()); diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index 75885ff31..d3ad7e365 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -233,13 +233,15 @@ private: */ line3d m_shootline; - size_t m_move_id = -1; + bool m_has_move_id = false; + size_t m_move_id; bool m_move_has_really_moved = false; u64 m_move_downtime = 0; bool m_move_sent_as_mouse_event = false; v2s32 m_move_downlocation = v2s32(-10000, -10000); - size_t m_joystick_id = -1; + bool m_has_joystick_id = false; + size_t m_joystick_id; bool m_joystick_has_really_moved = false; bool m_fixed_joystick = false; bool m_joystick_triggers_special1 = false;