diff options
-rw-r--r-- | doc/classes/Camera3D.xml | 7 | ||||
-rw-r--r-- | platform/android/display_server_android.cpp | 7 | ||||
-rw-r--r-- | platform/android/export/export.cpp | 21 | ||||
-rw-r--r-- | platform/android/java/app/res/values/themes.xml | 1 | ||||
-rw-r--r-- | platform/android/java/lib/src/org/godotengine/godot/GodotIO.java | 26 | ||||
-rw-r--r-- | platform/android/java_godot_io_wrapper.cpp | 14 | ||||
-rw-r--r-- | platform/android/java_godot_io_wrapper.h | 2 | ||||
-rw-r--r-- | platform/linuxbsd/os_linuxbsd.cpp | 33 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 92 | ||||
-rw-r--r-- | scene/gui/tab_container.h | 1 |
10 files changed, 145 insertions, 59 deletions
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml index b6a108fb25..b3fe452b12 100644 --- a/doc/classes/Camera3D.xml +++ b/doc/classes/Camera3D.xml @@ -163,6 +163,13 @@ </argument> <description> Returns the 2D coordinate in the [Viewport] rectangle that maps to the given 3D point in worldspace. + [b]Note:[/b] When using this to position GUI elements over a 3D viewport, use [method is_position_behind] to prevent them from appearing if the 3D point is behind the camera: + [codeblock] + # This code block is part of a script that inherits from Node3D. + # `control` is a reference to a node inheriting from Control. + control.visible = not get_viewport().get_camera().is_position_behind(global_transform.origin) + control.rect_position = get_viewport().get_camera().unproject_position(global_transform.origin) + [/codeblock] </description> </method> </methods> diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 3aa2fb5451..23452b2833 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -137,8 +137,11 @@ Size2i DisplayServerAndroid::screen_get_size(int p_screen) const { } Rect2i DisplayServerAndroid::screen_get_usable_rect(int p_screen) const { - Size2i display_size = OS_Android::get_singleton()->get_display_size(); - return Rect2i(0, 0, display_size.width, display_size.height); + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); + ERR_FAIL_COND_V(!godot_io_java, Rect2i()); + int xywh[4]; + godot_io_java->screen_get_usable_rect(xywh); + return Rect2i(xywh[0], xywh[1], xywh[2], xywh[3]); } int DisplayServerAndroid::screen_get_dpi(int p_screen) const { diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 37da1dbd4d..943a473717 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -2297,15 +2297,18 @@ public: if (use_custom_build) { //test that installed build version is alright - FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ); - if (!f) { - EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu.")); - return ERR_UNCONFIGURED; - } - String version = f->get_line().strip_edges(); - if (version != VERSION_FULL_CONFIG) { - EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG)); - return ERR_UNCONFIGURED; + { + FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ); + if (!f) { + EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu.")); + return ERR_UNCONFIGURED; + } + String version = f->get_line().strip_edges(); + f->close(); + if (version != VERSION_FULL_CONFIG) { + EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG)); + return ERR_UNCONFIGURED; + } } String sdk_path = EDITOR_GET("export/android/custom_build_sdk_path"); ERR_FAIL_COND_V_MSG(sdk_path == "", ERR_UNCONFIGURED, "Android SDK path must be configured in Editor Settings at 'export/android/custom_build_sdk_path'."); diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index 26912538d3..99f723f5ba 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -5,5 +5,6 @@ <style name="GodotAppSplashTheme" parent="@style/GodotAppMainTheme"> <item name="android:windowBackground">@drawable/splash_drawable</item> + <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> </style> </resources> diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index c2f3c88416..874fd88848 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -37,12 +37,16 @@ import android.content.*; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.AssetManager; +import android.graphics.Point; import android.media.*; import android.net.Uri; import android.os.*; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; +import android.view.Display; +import android.view.DisplayCutout; +import android.view.WindowInsets; import java.io.IOException; import java.io.InputStream; @@ -461,6 +465,28 @@ public class GodotIO { return (int)(metrics.density * 160f); } + public int[] screenGetUsableRect() { + DisplayMetrics metrics = activity.getResources().getDisplayMetrics(); + Display display = activity.getWindowManager().getDefaultDisplay(); + Point size = new Point(); + display.getRealSize(size); + + int result[] = { 0, 0, size.x, size.y }; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); + DisplayCutout cutout = insets.getDisplayCutout(); + if (cutout != null) { + int insetLeft = cutout.getSafeInsetLeft(); + int insetTop = cutout.getSafeInsetTop(); + result[0] = insetLeft; + result[1] = insetTop; + result[2] -= insetLeft + cutout.getSafeInsetRight(); + result[3] -= insetTop + cutout.getSafeInsetBottom(); + } + } + return result; + } + public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (edit != null) edit.showKeyboard(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 4ccbc6b97e..eec385f44e 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -52,6 +52,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;"); _get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;"); _get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I"); + _screen_get_usable_rect = p_env->GetMethodID(cls, "screenGetUsableRect", "()[I"), _get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;"); _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;ZIII)V"); _hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V"); @@ -118,6 +119,19 @@ int GodotIOJavaWrapper::get_screen_dpi() { } } +void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) { + if (_screen_get_usable_rect) { + JNIEnv *env = ThreadAndroid::get_env(); + jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _screen_get_usable_rect); + ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4); + jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE); + for (int i = 0; i < 4; i++) { + p_rect_xywh[i] = arrayBody[i]; + } + env->ReleaseIntArrayElements(returnArray, arrayBody, 0); + } +} + String GodotIOJavaWrapper::get_unique_id() { if (_get_unique_id) { JNIEnv *env = ThreadAndroid::get_env(); diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 6465ded985..13270c794b 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -50,6 +50,7 @@ private: jmethodID _get_locale = 0; jmethodID _get_model = 0; jmethodID _get_screen_DPI = 0; + jmethodID _screen_get_usable_rect = 0; jmethodID _get_unique_id = 0; jmethodID _show_keyboard = 0; jmethodID _hide_keyboard = 0; @@ -68,6 +69,7 @@ public: String get_locale(); String get_model(); int get_screen_dpi(); + void screen_get_usable_rect(int (&p_rect_xywh)[4]); String get_unique_id(); bool has_vk(); void show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index e00a32e3ba..e569aa03d7 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -123,18 +123,39 @@ String OS_LinuxBSD::get_name() const { Error OS_LinuxBSD::shell_open(String p_uri) { Error ok; + int err_code; List<String> args; args.push_back(p_uri); - ok = execute("xdg-open", args, false); - if (ok == OK) { + + // Agnostic + ok = execute("xdg-open", args, true, nullptr, nullptr, &err_code); + if (ok == OK && !err_code) { + return OK; + } else if (err_code == 2) { + return ERR_FILE_NOT_FOUND; + } + // GNOME + args.push_front("open"); // The command is `gio open`, so we need to add it to args + ok = execute("gio", args, true, nullptr, nullptr, &err_code); + if (ok == OK && !err_code) { + return OK; + } else if (err_code == 2) { + return ERR_FILE_NOT_FOUND; + } + args.pop_front(); + ok = execute("gvfs-open", args, true, nullptr, nullptr, &err_code); + if (ok == OK && !err_code) { return OK; + } else if (err_code == 2) { + return ERR_FILE_NOT_FOUND; } - ok = execute("gnome-open", args, false); - if (ok == OK) { + // KDE + ok = execute("kde-open5", args, true, nullptr, nullptr, &err_code); + if (ok == OK && !err_code) { return OK; } - ok = execute("kde-open", args, false); - return ok; + ok = execute("kde-open", args, true, nullptr, nullptr, &err_code); + return !err_code ? ok : FAILED; } bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index a1f93094c4..4074c75dd7 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -282,7 +282,6 @@ void TabContainer::_notification(int p_what) { Color font_color_bg = get_theme_color("font_color_bg"); Color font_color_disabled = get_theme_color("font_color_disabled"); int side_margin = get_theme_constant("side_margin"); - int icon_text_distance = get_theme_constant("icon_separation"); // Find out start and width of the header area. int header_x = side_margin; @@ -348,61 +347,33 @@ void TabContainer::_notification(int p_what) { break; } - // Draw the tab area. - panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height)); - - // Draw all visible tabs. + // Draw unselected tabs in back int x = 0; + int x_current = 0; for (int i = 0; i < tab_widths.size(); i++) { if (get_tab_hidden(i)) { continue; } - Ref<StyleBox> tab_style; - Color font_color; + + int tab_width = tab_widths[i]; if (get_tab_disabled(i + first_tab_cache)) { - tab_style = tab_disabled; - font_color = font_color_disabled; + _draw_tab(tab_disabled, font_color_disabled, i, tabs_ofs_cache + x); } else if (i + first_tab_cache == current) { - tab_style = tab_fg; - font_color = font_color_fg; + x_current = x; } else { - tab_style = tab_bg; - font_color = font_color_bg; - } - - // Draw the tab background. - int tab_width = tab_widths[i]; - Rect2 tab_rect(tabs_ofs_cache + x, 0, tab_width, header_height); - tab_style->draw(canvas, tab_rect); - - // Draw the tab contents. - Control *control = Object::cast_to<Control>(tabs[i + first_tab_cache]); - String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name())); - - int x_content = tab_rect.position.x + tab_style->get_margin(MARGIN_LEFT); - int top_margin = tab_style->get_margin(MARGIN_TOP); - int y_center = top_margin + (tab_rect.size.y - tab_style->get_minimum_size().y) / 2; - - // Draw the tab icon. - if (control->has_meta("_tab_icon")) { - Ref<Texture2D> icon = control->get_meta("_tab_icon"); - if (icon.is_valid()) { - int y = y_center - (icon->get_height() / 2); - icon->draw(canvas, Point2i(x_content, y)); - if (text != "") { - x_content += icon->get_width() + icon_text_distance; - } - } + _draw_tab(tab_bg, font_color_bg, i, tabs_ofs_cache + x); } - // Draw the tab text. - Point2i text_pos(x_content, y_center - (font->get_height() / 2) + font->get_ascent()); - font->draw(canvas, text_pos, text, font_color); - x += tab_width; last_tab_cache = i + first_tab_cache; } + // Draw the tab area. + panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height)); + + // Draw selected tab in front + _draw_tab(tab_fg, font_color_fg, current, tabs_ofs_cache + x_current); + // Draw the popup menu. x = get_size().width; if (popup) { @@ -438,6 +409,43 @@ void TabContainer::_notification(int p_what) { } } +void TabContainer::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x) { + Vector<Control *> tabs = _get_tabs(); + RID canvas = get_canvas_item(); + Ref<Font> font = get_theme_font("font"); + int icon_text_distance = get_theme_constant("icon_separation"); + int tab_width = _get_tab_width(p_index); + int header_height = _get_top_margin(); + + // Draw the tab background. + Rect2 tab_rect(p_x, 0, tab_width, header_height); + p_tab_style->draw(canvas, tab_rect); + + // Draw the tab contents. + Control *control = Object::cast_to<Control>(tabs[p_index + first_tab_cache]); + String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name())); + + int x_content = tab_rect.position.x + p_tab_style->get_margin(MARGIN_LEFT); + int top_margin = p_tab_style->get_margin(MARGIN_TOP); + int y_center = top_margin + (tab_rect.size.y - p_tab_style->get_minimum_size().y) / 2; + + // Draw the tab icon. + if (control->has_meta("_tab_icon")) { + Ref<Texture2D> icon = control->get_meta("_tab_icon"); + if (icon.is_valid()) { + int y = y_center - (icon->get_height() / 2); + icon->draw(canvas, Point2i(x_content, y)); + if (text != "") { + x_content += icon->get_width() + icon_text_distance; + } + } + } + + // Draw the tab text. + Point2i text_pos(x_content, y_center - (font->get_height() / 2) + font->get_ascent()); + font->draw(canvas, text_pos, text, p_font_color); +} + void TabContainer::_on_theme_changed() { if (get_tab_count() > 0) { _repaint(); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 7ea667d60f..6ac07b5845 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -68,6 +68,7 @@ private: void _repaint(); void _on_mouse_exited(); void _update_current_tab(); + void _draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x); protected: void _child_renamed_callback(); |