summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/dir_access_jandroid.cpp1
-rw-r--r--platform/android/export/export.cpp461
-rw-r--r--platform/android/java/app/AndroidManifest.xml2
-rw-r--r--platform/android/java/lib/AndroidManifest.xml2
-rw-r--r--platform/android/java/lib/res/drawable-nodpi/icon.pngbin7569 -> 0 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml5
-rw-r--r--platform/android/java/lib/res/mipmap-hdpi/icon.pngbin0 -> 3762 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-hdpi/icon_background.pngbin0 -> 375 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-hdpi/icon_foreground.pngbin0 -> 2998 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-mdpi/icon.pngbin0 -> 2672 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-mdpi/icon_background.pngbin0 -> 240 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-mdpi/icon_foreground.pngbin0 -> 1909 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xhdpi/icon.pngbin0 -> 5186 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xhdpi/icon_background.pngbin0 -> 517 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.pngbin0 -> 4490 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxhdpi/icon.pngbin0 -> 8154 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxhdpi/icon_background.pngbin0 -> 905 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.pngbin0 -> 7415 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxxhdpi/icon.pngbin0 -> 11749 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.pngbin0 -> 1360 bytes
-rw-r--r--platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.pngbin0 -> 11325 bytes
-rw-r--r--platform/android/java/lib/res/mipmap/icon.pngbin0 -> 11749 bytes
-rw-r--r--platform/android/java/lib/res/mipmap/icon_background.pngbin0 -> 240 bytes
-rw-r--r--platform/android/java/lib/res/mipmap/icon_foreground.pngbin0 -> 1909 bytes
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotLib.java10
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotView.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java106
-rw-r--r--platform/android/java_godot_lib_jni.cpp14
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/android/os_android.cpp20
-rw-r--r--platform/android/os_android.h3
31 files changed, 441 insertions, 190 deletions
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 69178317f7..f52b511522 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -110,7 +110,6 @@ String DirAccessJAndroid::get_drive(int p_drive) {
Error DirAccessJAndroid::change_dir(String p_dir) {
JNIEnv *env = ThreadAndroid::get_env();
- p_dir = p_dir.simplify_path();
if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))
return OK;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 9167a291f8..eb461860ed 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -30,6 +30,7 @@
#include "export.h"
+#include "core/io/image_loader.h"
#include "core/io/marshalls.h"
#include "core/io/zip_io.h"
#include "core/os/dir_access.h"
@@ -37,6 +38,7 @@
#include "core/os/os.h"
#include "core/project_settings.h"
#include "core/version.h"
+#include "drivers/png/png_driver_common.h"
#include "editor/editor_export.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
@@ -196,16 +198,40 @@ static const char *android_perms[] = {
};
struct LauncherIcon {
- const char *option_id;
const char *export_path;
+ int dimensions;
};
-static const LauncherIcon launcher_icons[] = {
- { "launcher_icons/xxxhdpi_192x192", "res/drawable-xxxhdpi-v4/icon.png" },
- { "launcher_icons/xxhdpi_144x144", "res/drawable-xxhdpi-v4/icon.png" },
- { "launcher_icons/xhdpi_96x96", "res/drawable-xhdpi-v4/icon.png" },
- { "launcher_icons/hdpi_72x72", "res/drawable-hdpi-v4/icon.png" },
- { "launcher_icons/mdpi_48x48", "res/drawable-mdpi-v4/icon.png" }
+static const int icon_densities_count = 6;
+static const char *launcher_icon_option = "launcher_icon/xxxhdpi_192x192";
+static const char *launcher_adaptive_icon_foreground_option = "launcher_adaptive_icon_foreground/xxxhdpi_432x432";
+static const char *launcher_adaptive_icon_background_option = "launcher_adaptive_icon_background/xxxhdpi_432x432";
+
+static const LauncherIcon launcher_icons[icon_densities_count] = {
+ { "res/mipmap-xxxhdpi-v4/icon.png", 192 },
+ { "res/mipmap-xxhdpi-v4/icon.png", 144 },
+ { "res/mipmap-xhdpi-v4/icon.png", 96 },
+ { "res/mipmap-hdpi-v4/icon.png", 72 },
+ { "res/mipmap-mdpi-v4/icon.png", 48 },
+ { "res/mipmap/icon.png", 192 }
+};
+
+static const LauncherIcon launcher_adaptive_icon_foregrounds[icon_densities_count] = {
+ { "res/mipmap-xxxhdpi-v4/icon_foreground.png", 432 },
+ { "res/mipmap-xxhdpi-v4/icon_foreground.png", 324 },
+ { "res/mipmap-xhdpi-v4/icon_foreground.png", 216 },
+ { "res/mipmap-hdpi-v4/icon_foreground.png", 162 },
+ { "res/mipmap-mdpi-v4/icon_foreground.png", 108 },
+ { "res/mipmap/icon_foreground.png", 432 }
+};
+
+static const LauncherIcon launcher_adaptive_icon_backgrounds[icon_densities_count] = {
+ { "res/mipmap-xxxhdpi-v4/icon_background.png", 432 },
+ { "res/mipmap-xxhdpi-v4/icon_background.png", 324 },
+ { "res/mipmap-xhdpi-v4/icon_background.png", 216 },
+ { "res/mipmap-hdpi-v4/icon_background.png", 162 },
+ { "res/mipmap-mdpi-v4/icon_background.png", 108 },
+ { "res/mipmap/icon_background.png", 432 }
};
class EditorExportPlatformAndroid : public EditorExportPlatform {
@@ -680,7 +706,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
bool screen_support_large = p_preset->get("screen/support_large");
bool screen_support_xlarge = p_preset->get("screen/support_xlarge");
- int xr_mode_index = p_preset->get("graphics/xr_mode");
+ int xr_mode_index = p_preset->get("xr_features/xr_mode");
Vector<String> perms;
@@ -859,135 +885,174 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
uint32_t name = decode_uint32(&p_manifest[iofs + 12]);
String tname = string_table[name];
- int dof_index = p_preset->get("graphics/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof
+ if (tname == "uses-feature") {
+ Vector<String> feature_names;
+ Vector<bool> feature_required_list;
+ Vector<int> feature_versions;
+
+ if (xr_mode_index == 1 /* XRMode.OVR */) {
+ // Check for degrees of freedom
+ int dof_index = p_preset->get("xr_features/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof
+
+ if (dof_index > 0) {
+ feature_names.push_back("android.hardware.vr.headtracking");
+ feature_required_list.push_back(dof_index == 2);
+ feature_versions.push_back(1);
+ }
+
+ // Check for hand tracking
+ int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
+ if (hand_tracking_index > 0) {
+ feature_names.push_back("oculus.software.handtracking");
+ feature_required_list.push_back(hand_tracking_index == 2);
+ feature_versions.push_back(-1); // no version attribute should be added.
- if (tname == "uses-feature" && dof_index > 0) {
- if (xr_mode_index == 0) {
- WARN_PRINT("VR DOF feature setting is only valid for oculus HMDs with an XR mode set to VR");
+ if (perms.find("oculus.permission.handtracking") == -1) {
+ perms.push_back("oculus.permission.handtracking");
+ }
+ }
}
- ofs += 24; // skip over end tag
- // save manifest ending so we can restore it
- Vector<uint8_t> manifest_end;
- uint32_t manifest_cur_size = p_manifest.size();
+ if (feature_names.size() > 0) {
+ ofs += 24; // skip over end tag
- manifest_end.resize(p_manifest.size() - ofs);
- memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size());
+ // save manifest ending so we can restore it
+ Vector<uint8_t> manifest_end;
+ uint32_t manifest_cur_size = p_manifest.size();
- int32_t attr_name_string = string_table.find("name");
- ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute.");
+ manifest_end.resize(p_manifest.size() - ofs);
+ memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size());
- int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android");
- if (ns_android_string == -1) {
- string_table.push_back("http://schemas.android.com/apk/res/android");
- ns_android_string = string_table.size() - 1;
- }
+ int32_t attr_name_string = string_table.find("name");
+ ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute.");
- int32_t attr_uses_permission_string = string_table.find("uses-feature");
- if (attr_uses_permission_string == -1) {
- string_table.push_back("uses-feature");
- attr_uses_permission_string = string_table.size() - 1;
- }
+ int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android");
+ if (ns_android_string == -1) {
+ string_table.push_back("http://schemas.android.com/apk/res/android");
+ ns_android_string = string_table.size() - 1;
+ }
- int32_t attr_required_string = string_table.find("required");
- if (attr_required_string == -1) {
- string_table.push_back("required");
- attr_required_string = string_table.size() - 1;
- }
+ int32_t attr_uses_feature_string = string_table.find("uses-feature");
+ if (attr_uses_feature_string == -1) {
+ string_table.push_back("uses-feature");
+ attr_uses_feature_string = string_table.size() - 1;
+ }
- int32_t attr_version_string = string_table.find("version");
- if (attr_version_string == -1) {
- string_table.push_back("version");
- attr_version_string = string_table.size() - 1;
- }
+ int32_t attr_required_string = string_table.find("required");
+ if (attr_required_string == -1) {
+ string_table.push_back("required");
+ attr_required_string = string_table.size() - 1;
+ }
- String required_value_string;
- if (dof_index == 1) {
- required_value_string = "false";
- } else if (dof_index == 2) {
- required_value_string = "true";
- } else {
- ERR_FAIL_MSG("Unknown DoF index: " + itos(dof_index) + ".");
- }
- int32_t required_value = string_table.find(required_value_string);
- if (required_value == -1) {
- string_table.push_back(required_value_string);
- required_value = string_table.size() - 1;
- }
+ for (int i = 0; i < feature_names.size(); i++) {
+ String feature_name = feature_names[i];
+ bool feature_required = feature_required_list[i];
+ int feature_version = feature_versions[i];
+ bool has_version_attribute = feature_version != -1;
- int32_t version_value = string_table.find("1");
- if (version_value == -1) {
- string_table.push_back("1");
- version_value = string_table.size() - 1;
- }
+ print_line("Adding feature " + feature_name);
- int32_t feature_string = string_table.find("android.hardware.vr.headtracking");
- if (feature_string == -1) {
- string_table.push_back("android.hardware.vr.headtracking");
- feature_string = string_table.size() - 1;
- }
+ int32_t feature_string = string_table.find(feature_name);
+ if (feature_string == -1) {
+ string_table.push_back(feature_name);
+ feature_string = string_table.size() - 1;
+ }
- {
- manifest_cur_size += 96 + 20; // node and three attrs + end node
- p_manifest.resize(manifest_cur_size);
+ String required_value_string = feature_required ? "true" : "false";
+ int32_t required_value = string_table.find(required_value_string);
+ if (required_value == -1) {
+ string_table.push_back(required_value_string);
+ required_value = string_table.size() - 1;
+ }
- // start tag
- encode_uint16(0x102, &p_manifest.write[ofs]); // type
- encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
- encode_uint32(96, &p_manifest.write[ofs + 4]); // size
- encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
- encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
- encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
- encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name
- encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start
- encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size
- encode_uint16(3, &p_manifest.write[ofs + 28]); // num_attrs
- encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index
- encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index
- encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index
+ int32_t attr_version_string = -1;
+ int32_t version_value = -1;
+ int tag_size;
+ int attr_count;
+ if (has_version_attribute) {
+ attr_version_string = string_table.find("version");
+ if (attr_version_string == -1) {
+ string_table.push_back("version");
+ attr_version_string = string_table.size() - 1;
+ }
- // android:name attribute
- encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns
- encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name'
- encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value
- encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size
- p_manifest.write[ofs + 50] = 0; // typedvalue_always0
- p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string)
- encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference
-
- // android:required attribute
- encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns
- encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name'
- encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value
- encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size
- p_manifest.write[ofs + 70] = 0; // typedvalue_always0
- p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string)
- encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference
-
- // android:version attribute
- encode_uint32(ns_android_string, &p_manifest.write[ofs + 76]); // ns
- encode_uint32(attr_version_string, &p_manifest.write[ofs + 80]); // 'name'
- encode_uint32(version_value, &p_manifest.write[ofs + 84]); // raw_value
- encode_uint16(8, &p_manifest.write[ofs + 88]); // typedvalue_size
- p_manifest.write[ofs + 90] = 0; // typedvalue_always0
- p_manifest.write[ofs + 91] = 0x03; // typedvalue_type (string)
- encode_uint32(version_value, &p_manifest.write[ofs + 92]); // typedvalue reference
-
- ofs += 96;
+ version_value = string_table.find(itos(feature_version));
+ if (version_value == -1) {
+ string_table.push_back(itos(feature_version));
+ version_value = string_table.size() - 1;
+ }
- // end tag
- encode_uint16(0x103, &p_manifest.write[ofs]); // type
- encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
- encode_uint32(24, &p_manifest.write[ofs + 4]); // size
- encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
- encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
- encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
- encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name
+ tag_size = 96; // node and three attrs + end node
+ attr_count = 3;
+ } else {
+ tag_size = 76; // node and two attrs + end node
+ attr_count = 2;
+ }
+ manifest_cur_size += tag_size + 24;
+ p_manifest.resize(manifest_cur_size);
+
+ // start tag
+ encode_uint16(0x102, &p_manifest.write[ofs]); // type
+ encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
+ encode_uint32(tag_size, &p_manifest.write[ofs + 4]); // size
+ encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
+ encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
+ encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
+ encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name
+ encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start
+ encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size
+ encode_uint16(attr_count, &p_manifest.write[ofs + 28]); // num_attrs
+ encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index
+ encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index
+ encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index
+
+ // android:name attribute
+ encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns
+ encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name'
+ encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value
+ encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size
+ p_manifest.write[ofs + 50] = 0; // typedvalue_always0
+ p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string)
+ encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference
+
+ // android:required attribute
+ encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns
+ encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name'
+ encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value
+ encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size
+ p_manifest.write[ofs + 70] = 0; // typedvalue_always0
+ p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string)
+ encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference
+
+ ofs += 76;
+
+ if (has_version_attribute) {
+ // android:version attribute
+ encode_uint32(ns_android_string, &p_manifest.write[ofs]); // ns
+ encode_uint32(attr_version_string, &p_manifest.write[ofs + 4]); // 'name'
+ encode_uint32(version_value, &p_manifest.write[ofs + 8]); // raw_value
+ encode_uint16(8, &p_manifest.write[ofs + 12]); // typedvalue_size
+ p_manifest.write[ofs + 14] = 0; // typedvalue_always0
+ p_manifest.write[ofs + 15] = 0x03; // typedvalue_type (string)
+ encode_uint32(version_value, &p_manifest.write[ofs + 16]); // typedvalue reference
+
+ ofs += 20;
+ }
- ofs += 24;
+ // end tag
+ encode_uint16(0x103, &p_manifest.write[ofs]); // type
+ encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize
+ encode_uint32(24, &p_manifest.write[ofs + 4]); // size
+ encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno
+ encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment
+ encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns
+ encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name
+
+ ofs += 24;
+ }
+ memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size());
+ ofs -= 24; // go back over back end
}
- memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size());
- ofs -= 24; // go back over back end
}
if (tname == "manifest") {
@@ -1259,6 +1324,27 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
//printf("end\n");
}
+ void _process_launcher_icons(const String &p_processing_file_name, const Ref<Image> &p_source_image, const LauncherIcon p_icon, Vector<uint8_t> &p_data) {
+ if (p_processing_file_name == p_icon.export_path) {
+ Ref<Image> working_image = p_source_image;
+
+ if (p_source_image->get_width() != p_icon.dimensions || p_source_image->get_height() != p_icon.dimensions) {
+ working_image = p_source_image->duplicate();
+ working_image->resize(p_icon.dimensions, p_icon.dimensions, Image::Interpolation::INTERPOLATE_LANCZOS);
+ }
+
+ PoolVector<uint8_t> png_buffer;
+ Error err = PNGDriverCommon::image_to_png(working_image, png_buffer);
+ if (err == OK) {
+ p_data.resize(png_buffer.size());
+ memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size());
+ } else {
+ String err_str = String("Failed to convert resized icon (") + p_processing_file_name + ") to png.";
+ WARN_PRINT(err_str.utf8().get_data());
+ }
+ }
+ }
+
static Vector<String> get_enabled_abis(const Ref<EditorExportPreset> &p_preset) {
Vector<String> abis = get_abis();
Vector<String> enabled_abis;
@@ -1295,13 +1381,14 @@ public:
virtual void get_export_options(List<ExportOption> *r_options) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/32_bits_framebuffer"), true));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_package/use_custom_build"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
@@ -1315,11 +1402,9 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/opengl_debug"), false));
-
- for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icons[i].option_id, PROPERTY_HINT_FILE, "*.png"), ""));
- }
-
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), ""));
@@ -1577,29 +1662,34 @@ public:
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
+ bool valid = false;
- if (!bool(p_preset->get("custom_package/use_custom_build"))) {
+ // Look for export templates (first official, and if defined custom templates).
- r_missing_templates = find_export_template("android_debug.apk") == String() || find_export_template("android_release.apk") == String();
+ if (!bool(p_preset->get("custom_template/use_custom_build"))) {
+ bool dvalid = exists_export_template("android_debug.apk", &err);
+ bool rvalid = exists_export_template("android_release.apk", &err);
- if (p_preset->get("custom_package/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/debug"))) {
- r_missing_templates = false;
- } else {
+ if (p_preset->get("custom_template/debug") != "") {
+ dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
+ if (!dvalid) {
err += TTR("Custom debug template not found.") + "\n";
}
}
-
- if (p_preset->get("custom_package/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/release"))) {
- r_missing_templates = false;
- } else {
+ if (p_preset->get("custom_template/release") != "") {
+ rvalid = FileAccess::exists(p_preset->get("custom_template/release"));
+ if (!rvalid) {
err += TTR("Custom release template not found.") + "\n";
}
}
+
+ valid = dvalid || rvalid;
+ } else {
+ valid = exists_export_template("android_source.zip", &err);
}
+ r_missing_templates = !valid;
- bool valid = !r_missing_templates;
+ // Validate the rest of the configuration.
String adb = EditorSettings::get_singleton()->get("export/android/adb");
@@ -1628,7 +1718,7 @@ public:
}
}
- if (bool(p_preset->get("custom_package/use_custom_build"))) {
+ if (bool(p_preset->get("custom_template/use_custom_build"))) {
String sdk_path = EditorSettings::get_singleton()->get("export/android/custom_build_sdk_path");
if (sdk_path == "") {
err += TTR("Custom build requires a valid Android SDK path in Editor Settings.") + "\n";
@@ -1912,7 +2002,7 @@ public:
}
} else if (l.strip_edges().begins_with("<application")) {
- String last_tag = "android:icon=\"@drawable/icon\"";
+ String last_tag = "android:icon=\"@mipmap/icon\"";
int last_tag_pos = l.find(last_tag);
if (last_tag_pos == -1) {
ERR_PRINTS("Not adding application attributes as the expected tag was not found in '<application': " + last_tag);
@@ -1949,7 +2039,7 @@ public:
EditorProgress ep("export", "Exporting for Android", 105, true);
- if (bool(p_preset->get("custom_package/use_custom_build"))) { //custom build
+ if (bool(p_preset->get("custom_template/use_custom_build"))) { //custom build
//re-generate build.gradle and AndroidManifest.xml
{ //test that installed build version is alright
@@ -2017,9 +2107,9 @@ public:
} else {
if (p_debug)
- src_apk = p_preset->get("custom_package/debug");
+ src_apk = p_preset->get("custom_template/debug");
else
- src_apk = p_preset->get("custom_package/release");
+ src_apk = p_preset->get("custom_template/release");
src_apk = src_apk.strip_edges();
if (src_apk == "") {
@@ -2091,6 +2181,35 @@ public:
Vector<String> enabled_abis = get_enabled_abis(p_preset);
+ String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon");
+
+ // Prepare images to be resized for the icons. If some image ends up being uninitialized, the default image from the export template will be used.
+ Ref<Image> launcher_icon_image;
+ Ref<Image> launcher_adaptive_icon_foreground_image;
+ Ref<Image> launcher_adaptive_icon_background_image;
+
+ launcher_icon_image.instance();
+ launcher_adaptive_icon_foreground_image.instance();
+ launcher_adaptive_icon_background_image.instance();
+
+ // Regular icon: user selection -> project icon -> default.
+ String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges();
+ if (path.empty() || ImageLoader::load_image(path, launcher_icon_image) != OK) {
+ ImageLoader::load_image(project_icon_path, launcher_icon_image);
+ }
+
+ // Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default).
+ path = static_cast<String>(p_preset->get(launcher_adaptive_icon_foreground_option)).strip_edges();
+ if (path.empty() || ImageLoader::load_image(path, launcher_adaptive_icon_foreground_image) != OK) {
+ launcher_adaptive_icon_foreground_image = launcher_icon_image;
+ }
+
+ // Adaptive background: user selection -> default.
+ path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges();
+ if (!path.empty()) {
+ ImageLoader::load_image(path, launcher_adaptive_icon_background_image);
+ }
+
while (ret == UNZ_OK) {
//get filename
@@ -2113,41 +2232,22 @@ public:
//write
if (file == "AndroidManifest.xml") {
-
_fix_manifest(p_preset, data, p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG));
}
if (file == "resources.arsc") {
-
_fix_resources(p_preset, data);
}
- if (file == "res/drawable-nodpi-v4/icon.png") {
- bool found = false;
- for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
- String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges();
- if (icon_path != "" && icon_path.ends_with(".png")) {
- FileAccess *f = FileAccess::open(icon_path, FileAccess::READ);
- if (f) {
- data.resize(f->get_len());
- f->get_buffer(data.ptrw(), data.size());
- memdelete(f);
- found = true;
- break;
- }
- }
+ for (int i = 0; i < icon_densities_count; ++i) {
+ if (launcher_icon_image.is_valid() && !launcher_icon_image->empty()) {
+ _process_launcher_icons(file, launcher_icon_image, launcher_icons[i], data);
}
- if (!found) {
-
- String appicon = ProjectSettings::get_singleton()->get("application/config/icon");
- if (appicon != "" && appicon.ends_with(".png")) {
- FileAccess *f = FileAccess::open(appicon, FileAccess::READ);
- if (f) {
- data.resize(f->get_len());
- f->get_buffer(data.ptrw(), data.size());
- memdelete(f);
- }
- }
+ if (launcher_adaptive_icon_foreground_image.is_valid() && !launcher_adaptive_icon_foreground_image->empty()) {
+ _process_launcher_icons(file, launcher_adaptive_icon_foreground_image, launcher_adaptive_icon_foregrounds[i], data);
+ }
+ if (launcher_adaptive_icon_background_image.is_valid() && !launcher_adaptive_icon_background_image->empty()) {
+ _process_launcher_icons(file, launcher_adaptive_icon_background_image, launcher_adaptive_icon_backgrounds[i], data);
}
}
@@ -2246,20 +2346,7 @@ public:
}
}
- if (!err) {
- APKExportData ed;
- ed.ep = &ep;
- ed.apk = unaligned_apk;
- for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) {
- String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges();
- if (icon_path != "" && icon_path.ends_with(".png") && FileAccess::exists(icon_path)) {
- Vector<uint8_t> data = FileAccess::get_file_as_array(icon_path);
- store_in_apk(&ed, launcher_icons[i].export_path, data);
- }
- }
- }
-
- int xr_mode_index = p_preset->get("graphics/xr_mode");
+ int xr_mode_index = p_preset->get("xr_features/xr_mode");
if (xr_mode_index == 1 /* XRMode.OVR */) {
cl.push_back("--xr_mode_ovr");
} else {
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index ba01ec313b..7e9ce70d80 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -27,7 +27,7 @@
<!-- Any tag in this line after android:icon will be erased when doing custom builds. -->
<!-- If you want to add tags manually, do before it. -->
<!-- WARNING: This should stay on a single line until the parsing code is improved. See GH-32414. -->
- <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@drawable/icon" >
+ <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@mipmap/icon" >
<!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->
<!-- Do these changes in the export preset. Adding new ones is fine. -->
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index 517fc403b2..b133585f99 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -11,7 +11,7 @@
</application>
<instrumentation
- android:icon="@drawable/icon"
+ android:icon="@mipmap/icon"
android:label="@string/godot_project_name_string"
android:name=".GodotInstrumentation"
android:targetPackage="org.godotengine.godot" />
diff --git a/platform/android/java/lib/res/drawable-nodpi/icon.png b/platform/android/java/lib/res/drawable-nodpi/icon.png
deleted file mode 100644
index 6ad9b43117..0000000000
--- a/platform/android/java/lib/res/drawable-nodpi/icon.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
new file mode 100644
index 0000000000..1ed4037035
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@mipmap/icon_background"/>
+ <foreground android:drawable="@mipmap/icon_foreground"/>
+</adaptive-icon> \ No newline at end of file
diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon.png b/platform/android/java/lib/res/mipmap-hdpi/icon.png
new file mode 100644
index 0000000000..cc6e113e89
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-hdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon_background.png b/platform/android/java/lib/res/mipmap-hdpi/icon_background.png
new file mode 100644
index 0000000000..78445c0181
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-hdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png
new file mode 100644
index 0000000000..75e409ff74
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon.png b/platform/android/java/lib/res/mipmap-mdpi/icon.png
new file mode 100644
index 0000000000..e1968fe142
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-mdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon_background.png b/platform/android/java/lib/res/mipmap-mdpi/icon_background.png
new file mode 100644
index 0000000000..5813f751ed
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-mdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png
new file mode 100644
index 0000000000..982b69be1e
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon.png b/platform/android/java/lib/res/mipmap-xhdpi/icon.png
new file mode 100644
index 0000000000..9281d8da48
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xhdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png
new file mode 100644
index 0000000000..4269c822a7
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png
new file mode 100644
index 0000000000..726b267ad6
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon.png
new file mode 100644
index 0000000000..7a6b67d273
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png
new file mode 100644
index 0000000000..5e8b518d17
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png
new file mode 100644
index 0000000000..b0c727f74c
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png
new file mode 100644
index 0000000000..0881245802
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png
new file mode 100644
index 0000000000..004b6fd508
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png
new file mode 100644
index 0000000000..72e6f92b6e
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap/icon.png b/platform/android/java/lib/res/mipmap/icon.png
new file mode 100644
index 0000000000..0881245802
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap/icon.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap/icon_background.png b/platform/android/java/lib/res/mipmap/icon_background.png
new file mode 100644
index 0000000000..5813f751ed
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap/icon_background.png
Binary files differ
diff --git a/platform/android/java/lib/res/mipmap/icon_foreground.png b/platform/android/java/lib/res/mipmap/icon_foreground.png
new file mode 100644
index 0000000000..982b69be1e
--- /dev/null
+++ b/platform/android/java/lib/res/mipmap/icon_foreground.png
Binary files differ
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
index 8447af10e4..e0b46673ba 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java
@@ -100,6 +100,16 @@ public class GodotLib {
public static native void hover(int type, int x, int y);
/**
+ * Forward double_tap events from the main thread to the GL thread.
+ */
+ public static native void doubletap(int x, int y);
+
+ /**
+ * Forward scroll events from the main thread to the GL thread.
+ */
+ public static native void scroll(int x, int y);
+
+ /**
* Forward accelerometer sensor events from the main thread to the GL thread.
* @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
*/
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
index 78f3763d84..f938583082 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java
@@ -32,8 +32,10 @@ package org.godotengine.godot;
import android.annotation.SuppressLint;
import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView;
+import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import org.godotengine.godot.input.GodotGestureHandler;
import org.godotengine.godot.input.GodotInputHandler;
import org.godotengine.godot.utils.GLUtils;
import org.godotengine.godot.xr.XRMode;
@@ -68,6 +70,7 @@ public class GodotView extends GLSurfaceView {
private final Godot activity;
private final GodotInputHandler inputHandler;
+ private final GestureDetector detector;
private final GodotRenderer godotRenderer;
public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) {
@@ -78,6 +81,7 @@ public class GodotView extends GLSurfaceView {
this.activity = activity;
this.inputHandler = new GodotInputHandler(this);
+ this.detector = new GestureDetector(activity, new GodotGestureHandler(this));
this.godotRenderer = new GodotRenderer();
init(xrMode, false, 16, 0);
}
@@ -90,6 +94,7 @@ public class GodotView extends GLSurfaceView {
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
+ this.detector.onTouchEvent(event);
return activity.gotTouchEvent(event);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
new file mode 100644
index 0000000000..1a38a9c3d2
--- /dev/null
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java
@@ -0,0 +1,106 @@
+/*************************************************************************/
+/* GodotGestureHandler.java */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+package org.godotengine.godot.input;
+
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import org.godotengine.godot.GodotLib;
+import org.godotengine.godot.GodotView;
+
+/**
+ * Handles gesture input related events for the {@link GodotView} view.
+ * https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener
+ */
+public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener {
+
+ private final GodotView godotView;
+
+ public GodotGestureHandler(GodotView godotView) {
+ this.godotView = godotView;
+ }
+
+ private void queueEvent(Runnable task) {
+ godotView.queueEvent(task);
+ }
+
+ @Override
+ public boolean onDown(MotionEvent event) {
+ super.onDown(event);
+ //Log.i("GodotGesture", "onDown");
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent event) {
+ super.onSingleTapConfirmed(event);
+ return true;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent event) {
+ //Log.i("GodotGesture", "onLongPress");
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent event) {
+ //Log.i("GodotGesture", "onDoubleTap");
+ final int x = Math.round(event.getX());
+ final int y = Math.round(event.getY());
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.doubletap(x, y);
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ //Log.i("GodotGesture", "onScroll");
+ final int x = Math.round(distanceX);
+ final int y = Math.round(distanceY);
+ queueEvent(new Runnable() {
+ @Override
+ public void run() {
+ GodotLib.scroll(x, y);
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
+ //Log.i("GodotGesture", "onFling");
+ return true;
+ }
+}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 0a32f4423b..858ff89cbc 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -835,6 +835,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jo
os_android->process_hover(p_type, Point2(p_x, p_y));
}
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y) {
+ if (step == 0)
+ return;
+
+ os_android->process_double_tap(Point2(p_x, p_y));
+}
+
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y) {
+ if (step == 0)
+ return;
+
+ os_android->process_scroll(Point2(p_x, p_y));
+}
+
/*
* Android Key codes.
*/
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index 8c18c52d2b..71d4547f65 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -46,6 +46,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 4c560273e8..bbea5e3699 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -502,6 +502,26 @@ void OS_Android::process_hover(int p_type, Point2 p_pos) {
}
}
+void OS_Android::process_double_tap(Point2 p_pos) {
+ Ref<InputEventMouseButton> ev;
+ ev.instance();
+ ev->set_position(p_pos);
+ ev->set_global_position(p_pos);
+ ev->set_pressed(true);
+ ev->set_doubleclick(true);
+ ev->set_button_index(1);
+ input->parse_input_event(ev);
+}
+
+void OS_Android::process_scroll(Point2 p_pos) {
+ Ref<InputEventPanGesture> ev;
+ ev.instance();
+ ev->set_position(p_pos);
+ ev->set_delta(p_pos - scroll_prev_pos);
+ input->parse_input_event(ev);
+ scroll_prev_pos = p_pos;
+}
+
void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {
input->set_accelerometer(p_accelerometer);
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 5ac50ddef2..1cf64a2e84 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -70,6 +70,7 @@ public:
private:
Vector<TouchPos> touch;
Point2 hover_prev_pos; // needed to calculate the relative position on hover events
+ Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events
bool use_gl2;
bool use_apk_expansion;
@@ -187,6 +188,8 @@ public:
void process_gyroscope(const Vector3 &p_gyroscope);
void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);
void process_hover(int p_type, Point2 p_pos);
+ void process_double_tap(Point2 p_pos);
+ void process_scroll(Point2 p_pos);
void process_joy_event(JoypadEvent p_event);
void process_event(Ref<InputEvent> p_event);
void init_video_mode(int p_video_width, int p_video_height);