diff options
Diffstat (limited to 'platform/android')
9 files changed, 177 insertions, 58 deletions
diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h index fb442f4c54..857bef02d1 100644 --- a/platform/android/android_keys_utils.h +++ b/platform/android/android_keys_utils.h @@ -148,6 +148,8 @@ enum { AKEYCODE_BUTTON_START = 108, AKEYCODE_BUTTON_SELECT = 109, AKEYCODE_BUTTON_MODE = 110, + AKEYCODE_CONTROL_LEFT = 113, + AKEYCODE_CONTROL_RIGHT = 114, // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. @@ -246,6 +248,8 @@ static _WinTranslatePair _ak_to_keycode[] = { { KEY_BACKSLASH, AKEYCODE_BACKSLASH }, { KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET }, { KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET }, + { KEY_CONTROL, AKEYCODE_CONTROL_LEFT }, + { KEY_CONTROL, AKEYCODE_CONTROL_RIGHT }, { KEY_UNKNOWN, 0 } }; /* diff --git a/platform/android/detect.py b/platform/android/detect.py index 6da1e5f3d6..a4ac87f723 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -164,7 +164,7 @@ def configure(env): elif env["target"] == "debug": env.Append(LINKFLAGS=["-O0"]) env.Append(CCFLAGS=["-O0", "-g", "-fno-limit-debug-info"]) - env.Append(CPPDEFINES=["_DEBUG", "DEBUG_ENABLED", "DEBUG_MEMORY_ENABLED"]) + env.Append(CPPDEFINES=["_DEBUG", "DEBUG_ENABLED"]) env.Append(CPPFLAGS=["-UNDEBUG"]) # Compiler configuration diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 3bc9e6d876..7193519a52 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -486,17 +486,40 @@ void DisplayServerAndroid::process_joy_event(DisplayServerAndroid::JoypadEvent p } } +void DisplayServerAndroid::_set_key_modifier_state(Ref<InputEventWithModifiers> ev) { + ev->set_shift(shift_mem); + ev->set_alt(alt_mem); + ev->set_metakey(meta_mem); + ev->set_control(control_mem); +} + void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) { Ref<InputEventKey> ev; ev.instance(); int val = p_unicode_char; int keycode = android_get_keysym(p_keycode); int phy_keycode = android_get_keysym(p_scancode); + + if (keycode == KEY_SHIFT) { + shift_mem = p_pressed; + } + if (keycode == KEY_ALT) { + alt_mem = p_pressed; + } + if (keycode == KEY_CONTROL) { + control_mem = p_pressed; + } + if (keycode == KEY_META) { + meta_mem = p_pressed; + } + ev->set_keycode(keycode); ev->set_physical_keycode(phy_keycode); ev->set_unicode(val); ev->set_pressed(p_pressed); + _set_key_modifier_state(ev); + if (val == '\n') { ev->set_keycode(KEY_ENTER); } else if (val == 61448) { @@ -629,6 +652,7 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) { case 10: { // hover exit Ref<InputEventMouseMotion> ev; ev.instance(); + _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); ev->set_relative(p_pos - hover_prev_pos); @@ -641,6 +665,7 @@ void DisplayServerAndroid::process_hover(int p_type, Point2 p_pos) { void DisplayServerAndroid::process_double_tap(Point2 p_pos) { Ref<InputEventMouseButton> ev; ev.instance(); + _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_global_position(p_pos); ev->set_pressed(false); @@ -651,6 +676,7 @@ void DisplayServerAndroid::process_double_tap(Point2 p_pos) { void DisplayServerAndroid::process_scroll(Point2 p_pos) { Ref<InputEventPanGesture> ev; ev.instance(); + _set_key_modifier_state(ev); ev->set_position(p_pos); ev->set_delta(p_pos - scroll_prev_pos); Input::get_singleton()->parse_input_event(ev); diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index d64542df58..4cae52fa76 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -63,6 +63,11 @@ public: private: String rendering_driver; + bool alt_mem = false; + bool shift_mem = false; + bool control_mem = false; + bool meta_mem = false; + bool keep_screen_on; Vector<TouchPos> touch; @@ -84,6 +89,8 @@ private: static void _dispatch_input_events(const Ref<InputEvent> &p_event); + void _set_key_modifier_state(Ref<InputEventWithModifiers> ev); + public: static DisplayServerAndroid *get_singleton(); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index ed85256695..0213094c60 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "export.h" +#include "gradle_export_util.h" #include "core/io/image_loader.h" #include "core/io/marshalls.h" @@ -1408,23 +1409,81 @@ 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; + void _process_launcher_icons(const String &p_file_name, const Ref<Image> &p_source_image, int dimension, Vector<uint8_t> &p_data) { + 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); + if (p_source_image->get_width() != dimension || p_source_image->get_height() != dimension) { + working_image = p_source_image->duplicate(); + working_image->resize(dimension, dimension, Image::Interpolation::INTERPOLATE_LANCZOS); + } + + Vector<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.ptr(), p_data.size()); + } else { + String err_str = String("Failed to convert resized icon (") + p_file_name + ") to png."; + WARN_PRINT(err_str.utf8().get_data()); + } + } + + void load_icon_refs(const Ref<EditorExportPreset> &p_preset, Ref<Image> &icon, Ref<Image> &foreground, Ref<Image> &background) { + String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); + + icon.instance(); + foreground.instance(); + background.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, icon) != OK) { + ImageLoader::load_image(project_icon_path, icon); + } + + // 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, foreground) != OK) { + foreground = icon; + } + + // 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, background); + } + } + + void store_image(const LauncherIcon launcher_icon, const Vector<uint8_t> &data) { + String img_path = launcher_icon.export_path; + img_path = img_path.insert(0, "res://android/build/"); + store_file_at_path(img_path, data); + } + + void _copy_icons_to_gradle_project(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &main_image, + const Ref<Image> &foreground, const Ref<Image> &background) { + // 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. + + for (int i = 0; i < icon_densities_count; ++i) { + if (main_image.is_valid() && !main_image->empty()) { + Vector<uint8_t> data; + _process_launcher_icons(launcher_icons[i].export_path, main_image, launcher_icons[i].dimensions, data); + store_image(launcher_icons[i], data); } - Vector<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.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()); + if (foreground.is_valid() && !foreground->empty()) { + Vector<uint8_t> data; + _process_launcher_icons(launcher_adaptive_icon_foregrounds[i].export_path, foreground, + launcher_adaptive_icon_foregrounds[i].dimensions, data); + store_image(launcher_adaptive_icon_foregrounds[i], data); + } + + if (background.is_valid() && !background->empty()) { + Vector<uint8_t> data; + _process_launcher_icons(launcher_adaptive_icon_backgrounds[i].export_path, background, + launcher_adaptive_icon_backgrounds[i].dimensions, data); + store_image(launcher_adaptive_icon_backgrounds[i], data); } } } @@ -2006,6 +2065,12 @@ public: bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build")); + Ref<Image> main_image; + Ref<Image> foreground; + Ref<Image> background; + + load_icon_refs(p_preset, main_image, foreground, background); + if (use_custom_build) { //re-generate build.gradle and AndroidManifest.xml { //test that installed build version is alright @@ -2028,6 +2093,9 @@ public: if (err != OK) { EditorNode::add_io_error("Unable to overwrite res://android/build/res/*.xml files with project name"); } + // Copies the project icon files into the appropriate Gradle project directory + _copy_icons_to_gradle_project(p_preset, main_image, foreground, background); + //build project if custom build is enabled String sdk_path = EDITOR_GET("export/android/custom_build_sdk_path"); @@ -2157,34 +2225,7 @@ 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); - } Vector<String> invalid_abis(enabled_abis); while (ret == UNZ_OK) { @@ -2211,21 +2252,27 @@ public: _fix_manifest(p_preset, data, p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG)); } - if (file == "resources.arsc") { - if (!use_custom_build) { + if (!use_custom_build) { + if (file == "resources.arsc") { _fix_resources(p_preset, data); } - } - 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 (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); + for (int i = 0; i < icon_densities_count; ++i) { + if (main_image.is_valid() && !main_image->empty()) { + if (file == launcher_icons[i].export_path) { + _process_launcher_icons(file, main_image, launcher_icons[i].dimensions, data); + } + } + if (foreground.is_valid() && !foreground->empty()) { + if (file == launcher_adaptive_icon_foregrounds[i].export_path) { + _process_launcher_icons(file, foreground, launcher_adaptive_icon_foregrounds[i].dimensions, data); + } + } + if (background.is_valid() && !background->empty()) { + if (file == launcher_adaptive_icon_backgrounds[i].export_path) { + _process_launcher_icons(file, background, launcher_adaptive_icon_backgrounds[i].dimensions, data); + } + } } } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 4da2f31250..d169f46599 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -117,6 +117,11 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView godot.onBackPressed(); } + @Override + public GodotInputHandler getInputHandler() { + return inputHandler; + } + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java index 27e63f3a66..68b8a16641 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java @@ -30,6 +30,8 @@ package org.godotengine.godot; +import org.godotengine.godot.input.GodotInputHandler; + import android.view.SurfaceView; public interface GodotRenderView { @@ -43,4 +45,6 @@ public interface GodotRenderView { abstract public void onActivityResumed(); abstract public void onBackPressed(); + + abstract public GodotInputHandler getInputHandler(); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index aace593bae..65708389c3 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -90,6 +90,11 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV godot.onBackPressed(); } + @Override + public GodotInputHandler getInputHandler() { + return mInputHandler; + } + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java index 7f596575a8..c0defd008e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java @@ -155,14 +155,35 @@ public class GodotEditText extends EditText { // =========================================================== @Override public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) { - super.onKeyDown(keyCode, keyEvent); - - /* Let GlSurfaceView get focus if back key is input. */ + /* Let SurfaceView get focus if back key is input. */ if (keyCode == KeyEvent.KEYCODE_BACK) { mRenderView.getView().requestFocus(); } - return true; + // pass event to godot in special cases + if (needHandlingInGodot(keyCode, keyEvent) && mRenderView.getInputHandler().onKeyDown(keyCode, keyEvent)) { + return true; + } else { + return super.onKeyDown(keyCode, keyEvent); + } + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent keyEvent) { + if (needHandlingInGodot(keyCode, keyEvent) && mRenderView.getInputHandler().onKeyUp(keyCode, keyEvent)) { + return true; + } else { + return super.onKeyUp(keyCode, keyEvent); + } + } + + private boolean needHandlingInGodot(int keyCode, KeyEvent keyEvent) { + boolean isArrowKey = keyCode == KeyEvent.KEYCODE_DPAD_UP || keyCode == KeyEvent.KEYCODE_DPAD_DOWN || + keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT; + boolean isModifiedKey = keyEvent.isAltPressed() || keyEvent.isCtrlPressed() || keyEvent.isSymPressed() || + keyEvent.isFunctionPressed() || keyEvent.isMetaPressed(); + return isArrowKey || keyCode == KeyEvent.KEYCODE_TAB || KeyEvent.isModifierKey(keyCode) || + isModifiedKey; } // =========================================================== |