diff --git a/platform/android/SCsub b/platform/android/SCsub index 5a1425396bd4..1a3e2b458a9f 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -4,6 +4,7 @@ Import("env") android_files = [ "os_android.cpp", + "android_input_handler.cpp", "file_access_android.cpp", "audio_driver_opensl.cpp", "dir_access_jandroid.cpp", diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp new file mode 100644 index 000000000000..d085286a6168 --- /dev/null +++ b/platform/android/android_input_handler.cpp @@ -0,0 +1,372 @@ +/*************************************************************************/ +/* android_input_handler.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#include "android_input_handler.h" + +#include "android_keys_utils.h" + +#include "core/os/os.h" + +void AndroidInputHandler::process_joy_event(const JoypadEvent &p_event) { + switch (p_event.type) { + case JOY_EVENT_BUTTON: + input->joy_button(p_event.device, p_event.index, p_event.pressed); + break; + case JOY_EVENT_AXIS: + InputDefault::JoyAxis value; + value.min = -1; + value.value = p_event.value; + input->joy_axis(p_event.device, p_event.index, value); + break; + case JOY_EVENT_HAT: + input->joy_hat(p_event.device, p_event.hat); + break; + default: + return; + } +} + +void AndroidInputHandler::_set_key_modifier_state(Ref ev) const { + ev->set_shift(shift_mem); + ev->set_alt(alt_mem); + ev->set_metakey(meta_mem); + ev->set_control(control_mem); +} + +void AndroidInputHandler::process_event(Ref &p_event) { + input->parse_input_event(p_event); +} + +void AndroidInputHandler::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) { + Ref ev; + ev.instance(); + int val = p_unicode_char; + unsigned int scancode = android_get_keysym(p_keycode); + unsigned int phy_scancode = android_get_keysym(p_scancode); + + switch (scancode) { + case KEY_SHIFT: { + shift_mem = p_pressed; + } break; + case KEY_ALT: { + alt_mem = p_pressed; + } break; + case KEY_CONTROL: { + control_mem = p_pressed; + } break; + case KEY_META: { + meta_mem = p_pressed; + } break; + } + + ev->set_scancode(scancode); + ev->set_physical_scancode(phy_scancode); + + ev->set_unicode(val); + ev->set_pressed(p_pressed); + + _set_key_modifier_state(ev); + + if (val == '\n') { + ev->set_scancode(KEY_ENTER); + } else if (val == 61448) { + ev->set_scancode(KEY_BACKSPACE); + ev->set_unicode(KEY_BACKSPACE); + } else if (val == 61453) { + ev->set_scancode(KEY_ENTER); + ev->set_unicode(KEY_ENTER); + } else if (p_scancode == 4) { + if (MainLoop *main_loop = OS::get_singleton()->get_main_loop()) { + main_loop->call_deferred("notification", MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST); + } + } + + input->parse_input_event(ev); +} + +void AndroidInputHandler::process_touch(int p_event, int p_pointer, const Vector &p_points) { + switch (p_event) { + case AMOTION_EVENT_ACTION_DOWN: { //gesture begin + if (touch.size()) { + //end all if exist + for (int i = 0; i < touch.size(); i++) { + Ref ev; + ev.instance(); + ev->set_index(touch[i].id); + ev->set_pressed(false); + ev->set_position(touch[i].pos); + input->parse_input_event(ev); + } + } + + touch.resize(p_points.size()); + for (int i = 0; i < p_points.size(); i++) { + touch.write[i].id = p_points[i].id; + touch.write[i].pos = p_points[i].pos; + } + + //send touch + for (int i = 0; i < touch.size(); i++) { + Ref ev; + ev.instance(); + ev->set_index(touch[i].id); + ev->set_pressed(true); + ev->set_position(touch[i].pos); + input->parse_input_event(ev); + } + + } break; + case AMOTION_EVENT_ACTION_MOVE: { //motion + ERR_FAIL_COND(touch.size() != p_points.size()); + + for (int i = 0; i < touch.size(); i++) { + int idx = -1; + for (int j = 0; j < p_points.size(); j++) { + if (touch[i].id == p_points[j].id) { + idx = j; + break; + } + } + + ERR_CONTINUE(idx == -1); + + if (touch[i].pos == p_points[idx].pos) + continue; //no move unncesearily + + Ref ev; + ev.instance(); + ev->set_index(touch[i].id); + ev->set_position(p_points[idx].pos); + ev->set_relative(p_points[idx].pos - touch[i].pos); + input->parse_input_event(ev); + touch.write[i].pos = p_points[idx].pos; + } + + } break; + case AMOTION_EVENT_ACTION_CANCEL: + case AMOTION_EVENT_ACTION_UP: { //release + if (touch.size()) { + //end all if exist + for (int i = 0; i < touch.size(); i++) { + Ref ev; + ev.instance(); + ev->set_index(touch[i].id); + ev->set_pressed(false); + ev->set_position(touch[i].pos); + input->parse_input_event(ev); + } + touch.clear(); + } + } break; + case AMOTION_EVENT_ACTION_POINTER_DOWN: { // add touch + for (int i = 0; i < p_points.size(); i++) { + if (p_points[i].id == p_pointer) { + TouchPos tp = p_points[i]; + touch.push_back(tp); + + Ref ev; + ev.instance(); + + ev->set_index(tp.id); + ev->set_pressed(true); + ev->set_position(tp.pos); + input->parse_input_event(ev); + + break; + } + } + } break; + case AMOTION_EVENT_ACTION_POINTER_UP: { // remove touch + for (int i = 0; i < touch.size(); i++) { + if (touch[i].id == p_pointer) { + Ref ev; + ev.instance(); + ev->set_index(touch[i].id); + ev->set_pressed(false); + ev->set_position(touch[i].pos); + input->parse_input_event(ev); + touch.remove(i); + + break; + } + } + } break; + } +} + +void AndroidInputHandler::process_hover(int p_type, Point2 p_pos) { + // https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER + switch (p_type) { + case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move + case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter + case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit + Ref 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); + input->parse_input_event(ev); + hover_prev_pos = p_pos; + } break; + } +} + +void AndroidInputHandler::process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) { + int event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask); + switch (event_action) { + case AMOTION_EVENT_ACTION_BUTTON_PRESS: + case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { + Ref ev; + ev.instance(); + _set_key_modifier_state(ev); + ev->set_position(event_pos); + ev->set_global_position(event_pos); + ev->set_pressed(event_action == AMOTION_EVENT_ACTION_BUTTON_PRESS); + int changed_button_mask = buttons_state ^ event_buttons_mask; + + buttons_state = event_buttons_mask; + + ev->set_button_index(_button_index_from_mask(changed_button_mask)); + ev->set_button_mask(event_buttons_mask); + input->parse_input_event(ev); + } break; + + case AMOTION_EVENT_ACTION_MOVE: { + Ref ev; + ev.instance(); + _set_key_modifier_state(ev); + ev->set_position(event_pos); + ev->set_global_position(event_pos); + ev->set_relative(event_pos - hover_prev_pos); + ev->set_button_mask(event_buttons_mask); + input->parse_input_event(ev); + hover_prev_pos = event_pos; + } break; + case AMOTION_EVENT_ACTION_SCROLL: { + Ref ev; + ev.instance(); + _set_key_modifier_state(ev); + ev->set_position(event_pos); + ev->set_global_position(event_pos); + ev->set_pressed(true); + buttons_state = event_buttons_mask; + if (event_vertical_factor > 0) { + _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, event_vertical_factor); + } else if (event_vertical_factor < 0) { + _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -event_vertical_factor); + } + + if (event_horizontal_factor > 0) { + _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, event_horizontal_factor); + } else if (event_horizontal_factor < 0) { + _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -event_horizontal_factor); + } + } break; + } +} + +void AndroidInputHandler::_wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor) { + Ref evd = ev->duplicate(); + evd->set_button_index(wheel_button); + evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1))); + evd->set_factor(factor); + input->parse_input_event(evd); + Ref evdd = evd->duplicate(); + evdd->set_pressed(false); + evdd->set_button_mask(event_buttons_mask); + input->parse_input_event(evdd); +} + +void AndroidInputHandler::process_double_tap(int event_android_button_mask, Point2 p_pos) { + int event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask); + Ref ev; + ev.instance(); + _set_key_modifier_state(ev); + ev->set_position(p_pos); + ev->set_global_position(p_pos); + ev->set_pressed(event_button_mask != 0); + ev->set_button_index(_button_index_from_mask(event_button_mask)); + ev->set_button_mask(event_button_mask); + ev->set_doubleclick(true); + input->parse_input_event(ev); +} + +void AndroidInputHandler::process_scroll(Point2 p_pos) { + Ref ev; + ev.instance(); + _set_key_modifier_state(ev); + ev->set_position(p_pos); + ev->set_delta(p_pos - scroll_prev_pos); + input->parse_input_event(ev); + scroll_prev_pos = p_pos; +} + +int AndroidInputHandler::_button_index_from_mask(int button_mask) { + switch (button_mask) { + case BUTTON_MASK_LEFT: + return BUTTON_LEFT; + case BUTTON_MASK_RIGHT: + return BUTTON_RIGHT; + case BUTTON_MASK_MIDDLE: + return BUTTON_MIDDLE; + case BUTTON_MASK_XBUTTON1: + return BUTTON_XBUTTON1; + case BUTTON_MASK_XBUTTON2: + return BUTTON_XBUTTON2; + default: + return 0; + } +} + +int AndroidInputHandler::_android_button_mask_to_godot_button_mask(int android_button_mask) { + int godot_button_mask = 0; + if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { + godot_button_mask |= BUTTON_MASK_LEFT; + } + if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { + godot_button_mask |= BUTTON_MASK_RIGHT; + } + if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) { + godot_button_mask |= BUTTON_MASK_MIDDLE; + } + if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) { + godot_button_mask |= BUTTON_MASK_XBUTTON1; + } + if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { + godot_button_mask |= BUTTON_MASK_XBUTTON2; + } + + return godot_button_mask; +} + +void AndroidInputHandler::joy_connection_changed(int p_device, bool p_connected, String p_name) { + input->joy_connection_changed(p_device, p_connected, p_name, ""); +} diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h new file mode 100644 index 000000000000..b2de075a0eeb --- /dev/null +++ b/platform/android/android_input_handler.h @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* android_input_handler.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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. */ +/*************************************************************************/ + +#ifndef ANDROID_INPUT_HANDLER_H +#define ANDROID_INPUT_HANDLER_H + +#include "main/input_default.h" + +// This class encapsulates all the handling of input events that come from the Android UI thread. +// Remarks: +// - It's not thread-safe by itself, so its functions must only be called on a single thread, which is the Android UI thread. +// - Its functions must only call thread-safe methods. +class AndroidInputHandler { +public: + struct TouchPos { + int id; + Point2 pos; + }; + + enum { + JOY_EVENT_BUTTON = 0, + JOY_EVENT_AXIS = 1, + JOY_EVENT_HAT = 2 + }; + + struct JoypadEvent { + int device; + int type; + int index; + bool pressed; + float value; + int hat; + }; + +private: + Vector 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 alt_mem = false; + bool shift_mem = false; + bool control_mem = false; + bool meta_mem = false; + + int buttons_state = 0; + + InputDefault *input = static_cast(InputDefault::get_singleton()); + + void _set_key_modifier_state(Ref ev) const; + + static int _button_index_from_mask(int button_mask); + + static int _android_button_mask_to_godot_button_mask(int android_button_mask); + + void _wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor); + +public: + void process_event(Ref &p_event); + void process_joy_event(const JoypadEvent &p_event); + void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed); + void process_touch(int p_event, int p_pointer, const Vector &p_points); + void process_hover(int p_type, Point2 p_pos); + void process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor); + void process_double_tap(int event_android_button_mask, Point2 p_pos); + void process_scroll(Point2 p_pos); + void joy_connection_changed(int p_device, bool p_connected, String p_name); +}; + +#endif 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 index b29afe67deae..1dfd79069b89 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java @@ -75,7 +75,7 @@ public boolean onDoubleTap(MotionEvent event) { final int x = Math.round(event.getX()); final int y = Math.round(event.getY()); final int buttonMask = event.getButtonState(); - queueEvent(() -> GodotLib.doubleTap(buttonMask, x, y)); + GodotLib.doubleTap(buttonMask, x, y); return true; } @@ -84,7 +84,7 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float d //Log.i("GodotGesture", "onScroll"); final int x = Math.round(distanceX); final int y = Math.round(distanceY); - queueEvent(() -> GodotLib.scroll(x, y)); + GodotLib.scroll(x, y); return true; } diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java index e9ea0676cea5..d13f4b1a92cb 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java @@ -68,10 +68,6 @@ public GodotInputHandler(GodotView godotView) { this.inputManager.registerInputDeviceListener(this, null); } - private void queueEvent(Runnable task) { - godotView.queueEvent(task); - } - private boolean isKeyEvent_GameDevice(int source) { // Note that keyboards are often (SOURCE_KEYBOARD | SOURCE_DPAD) if (source == (InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD)) @@ -96,13 +92,12 @@ public boolean onKeyUp(final int keyCode, KeyEvent event) { if (mJoystickIds.indexOfKey(deviceId) >= 0) { final int button = getGodotButton(keyCode); final int godotJoyId = mJoystickIds.get(deviceId); - - queueEvent(() -> GodotLib.joybutton(godotJoyId, button, false)); + GodotLib.joybutton(godotJoyId, button, false); } } else { final int scanCode = event.getScanCode(); final int chr = event.getUnicodeChar(0); - queueEvent(() -> GodotLib.key(keyCode, scanCode, chr, false)); + GodotLib.key(keyCode, scanCode, chr, false); }; return true; @@ -132,13 +127,12 @@ public boolean onKeyDown(final int keyCode, KeyEvent event) { if (mJoystickIds.indexOfKey(deviceId) >= 0) { final int button = getGodotButton(keyCode); final int godotJoyId = mJoystickIds.get(deviceId); - - queueEvent(() -> GodotLib.joybutton(godotJoyId, button, true)); + GodotLib.joybutton(godotJoyId, button, true); } } else { final int scanCode = event.getScanCode(); final int chr = event.getUnicodeChar(0); - queueEvent(() -> GodotLib.key(keyCode, scanCode, chr, true)); + GodotLib.key(keyCode, scanCode, chr, true); } return true; @@ -170,18 +164,16 @@ public boolean onTouchEvent(final MotionEvent event) { final int action = event.getActionMasked(); final int pointer_idx = event.getPointerId(event.getActionIndex()); - godotView.queueEvent(() -> { - switch (action) { - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_MOVE: - case MotionEvent.ACTION_POINTER_UP: - case MotionEvent.ACTION_POINTER_DOWN: { - GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr); - } break; - } - }); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_POINTER_DOWN: { + GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr); + } break; + } } return true; } @@ -205,7 +197,7 @@ public boolean onGenericMotionEvent(MotionEvent event) { // save value to prevent repeats joystick.axesValues.put(axis, value); final int godotAxisIdx = i; - queueEvent(() -> GodotLib.joyaxis(godotJoyId, godotAxisIdx, value)); + GodotLib.joyaxis(godotJoyId, godotAxisIdx, value); } } @@ -215,7 +207,7 @@ public boolean onGenericMotionEvent(MotionEvent event) { if (joystick.hatX != hatX || joystick.hatY != hatY) { joystick.hatX = hatX; joystick.hatY = hatY; - queueEvent(() -> GodotLib.joyhat(godotJoyId, hatX, hatY)); + GodotLib.joyhat(godotJoyId, hatX, hatY); } } return true; @@ -224,7 +216,7 @@ public boolean onGenericMotionEvent(MotionEvent event) { final float x = event.getX(); final float y = event.getY(); final int type = event.getAction(); - queueEvent(() -> GodotLib.hover(type, x, y)); + GodotLib.hover(type, x, y); return true; } else if ((event.isFromSource(InputDevice.SOURCE_MOUSE))) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -315,7 +307,7 @@ public void onInputDeviceAdded(int deviceId) { } mJoysticksDevices.put(deviceId, joystick); - queueEvent(() -> GodotLib.joyconnectionchanged(id, true, joystick.name)); + GodotLib.joyconnectionchanged(id, true, joystick.name); } @Override @@ -327,8 +319,7 @@ public void onInputDeviceRemoved(int deviceId) { final int godotJoyId = mJoystickIds.get(deviceId); mJoystickIds.delete(deviceId); mJoysticksDevices.delete(deviceId); - - queueEvent(() -> GodotLib.joyconnectionchanged(godotJoyId, false, "")); + GodotLib.joyconnectionchanged(godotJoyId, false, ""); } @Override @@ -417,7 +408,7 @@ private boolean handleMouseEvent(final MotionEvent event) { final float x = event.getX(); final float y = event.getY(); final int type = event.getAction(); - queueEvent(() -> GodotLib.hover(type, x, y)); + GodotLib.hover(type, x, y); return true; } case MotionEvent.ACTION_BUTTON_PRESS: @@ -427,7 +418,7 @@ private boolean handleMouseEvent(final MotionEvent event) { final float y = event.getY(); final int buttonsMask = event.getButtonState(); final int action = event.getAction(); - queueEvent(() -> GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask)); + GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask); return true; } case MotionEvent.ACTION_SCROLL: { @@ -437,7 +428,7 @@ private boolean handleMouseEvent(final MotionEvent event) { final int action = event.getAction(); final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL); final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL); - queueEvent(() -> GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor)); + GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor); } } return false; diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java index 0a252fb78c91..eec17f18348d 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java @@ -94,17 +94,15 @@ public void afterTextChanged(final Editable s) { public void beforeTextChanged(final CharSequence pCharSequence, final int start, final int count, final int after) { //Log.d(TAG, "beforeTextChanged(" + pCharSequence + ")start: " + start + ",count: " + count + ",after: " + after); - mView.queueEvent(() -> { - for (int i = 0; i < count; ++i) { - GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true); - GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false); - - if (mHasSelection) { - mHasSelection = false; - break; - } + for (int i = 0; i < count; ++i) { + GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true); + GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false); + + if (mHasSelection) { + mHasSelection = false; + break; } - }); + } } @Override @@ -115,17 +113,15 @@ public void onTextChanged(final CharSequence pCharSequence, final int start, fin for (int i = start; i < start + count; ++i) { newChars[i - start] = pCharSequence.charAt(i); } - mView.queueEvent(() -> { - for (int i = 0; i < count; ++i) { - int key = newChars[i]; - if ((key == '\n') && !mEdit.isMultiline()) { - // Return keys are handled through action events - continue; - } - GodotLib.key(0, 0, key, true); - GodotLib.key(0, 0, key, false); + for (int i = 0; i < count; ++i) { + int key = newChars[i]; + if ((key == '\n') && !mEdit.isMultiline()) { + // Return keys are handled through action events + continue; } - }); + GodotLib.key(0, 0, key, true); + GodotLib.key(0, 0, key, false); + } } @Override @@ -133,13 +129,11 @@ public boolean onEditorAction(final TextView pTextView, final int pActionID, fin if (this.mEdit == pTextView && this.isFullScreenEdit()) { final String characters = pKeyEvent.getCharacters(); - mView.queueEvent(() -> { - for (int i = 0; i < characters.length(); i++) { - final int ch = characters.codePointAt(i); - GodotLib.key(0, 0, ch, true); - GodotLib.key(0, 0, ch, false); - } - }); + for (int i = 0; i < characters.length(); i++) { + final int ch = characters.codePointAt(i); + GodotLib.key(0, 0, ch, true); + GodotLib.key(0, 0, ch, false); + } } if (pActionID == EditorInfo.IME_ACTION_DONE) { diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 682020de8e2a..c03d52ee1195 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -33,7 +33,7 @@ #include "java_godot_wrapper.h" #include "android/asset_manager_jni.h" -#include "android_keys_utils.h" +#include "android_input_handler.h" #include "api/java_class_wrapper.h" #include "api/jni_singleton.h" #include "core/engine.h" @@ -50,14 +50,16 @@ #include #include +#include static JavaClassWrapper *java_class_wrapper = NULL; static OS_Android *os_android = NULL; +static AndroidInputHandler *input_handler = NULL; static GodotJavaWrapper *godot_java = NULL; static GodotIOJavaWrapper *godot_io_java = NULL; static bool initialized = false; -static int step = 0; +static std::atomic step; // Shared between UI and render threads static Size2 new_size; static Vector3 accelerometer; @@ -153,6 +155,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env if (godot_java) { delete godot_java; } + if (input_handler) { + delete input_handler; + } if (os_android) { delete os_android; } @@ -215,9 +220,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *en os_android->set_context_is_16_bits(!p_32_bits); } else { // GL context recreated because it was lost; restart app to let it reload everything + step = -1; // Ensure no further steps are attempted and no further events are sent os_android->main_loop_end(); godot_java->restart(env); - step = -1; // Ensure no further steps are attempted } } } @@ -226,7 +231,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jcl if (step == 0) return; - os_android->main_loop_request_go_back(); + if (os_android->get_main_loop()) { + os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST); + } } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz) { @@ -237,6 +244,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl // Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id, // but for Godot purposes, the main thread is the one running the game loop Main::setup2(Thread::get_caller_id()); + input_handler = new AndroidInputHandler(); ++step; return; } @@ -263,92 +271,101 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl } void touch_preprocessing(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor) { - if (step == 0) + if (step <= 0) return; - Vector points; + Vector points; for (int i = 0; i < pointer_count; i++) { jfloat p[3]; env->GetFloatArrayRegion(positions, i * 3, 3, p); - OS_Android::TouchPos tp; + AndroidInputHandler::TouchPos tp; tp.pos = Point2(p[1], p[2]); tp.id = (int)p[0]; points.push_back(tp); } if ((input_device & AINPUT_SOURCE_MOUSE) == AINPUT_SOURCE_MOUSE) { - os_android->process_mouse_event(ev, buttons_mask, points[0].pos, vertical_factor, horizontal_factor); + input_handler->process_mouse_event(ev, buttons_mask, points[0].pos, vertical_factor, horizontal_factor); } else { - os_android->process_touch(ev, pointer, points); + input_handler->process_touch(ev, pointer, points); } } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3F(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray position) { touch_preprocessing(env, clazz, input_device, ev, pointer, pointer_count, position); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FI(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray position, jint buttons_mask) { touch_preprocessing(env, clazz, input_device, ev, pointer, pointer_count, position, buttons_mask); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch__IIII_3FIFF(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray position, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor) { touch_preprocessing(env, clazz, input_device, ev, pointer, pointer_count, position, buttons_mask, vertical_factor, horizontal_factor); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jfloat p_x, jfloat p_y) { - if (step == 0) + if (step <= 0) return; - os_android->process_hover(p_type, Point2(p_x, p_y)); + input_handler->process_hover(p_type, Point2(p_x, p_y)); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env, jclass clazz, jint p_button_mask, jint p_x, jint p_y) { - if (step == 0) + if (step <= 0) return; - os_android->process_double_tap(p_button_mask, Point2(p_x, p_y)); + input_handler->process_double_tap(p_button_mask, Point2(p_x, p_y)); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y) { - if (step == 0) + if (step <= 0) return; - os_android->process_scroll(Point2(p_x, p_y)); + input_handler->process_scroll(Point2(p_x, p_y)); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed) { - if (step == 0) + if (step <= 0) return; - OS_Android::JoypadEvent jevent; + AndroidInputHandler::JoypadEvent jevent; jevent.device = p_device; - jevent.type = OS_Android::JOY_EVENT_BUTTON; + jevent.type = AndroidInputHandler::JOY_EVENT_BUTTON; jevent.index = p_button; jevent.pressed = p_pressed; - os_android->process_joy_event(jevent); + input_handler->process_joy_event(jevent); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jclass clazz, jint p_device, jint p_axis, jfloat p_value) { - if (step == 0) + if (step <= 0) return; - OS_Android::JoypadEvent jevent; + AndroidInputHandler::JoypadEvent jevent; jevent.device = p_device; - jevent.type = OS_Android::JOY_EVENT_AXIS; + jevent.type = AndroidInputHandler::JOY_EVENT_AXIS; jevent.index = p_axis; jevent.value = p_value; - os_android->process_joy_event(jevent); + input_handler->process_joy_event(jevent); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, jclass clazz, jint p_device, jint p_hat_x, jint p_hat_y) { - if (step == 0) + if (step <= 0) return; - OS_Android::JoypadEvent jevent; + AndroidInputHandler::JoypadEvent jevent; jevent.device = p_device; - jevent.type = OS_Android::JOY_EVENT_HAT; + jevent.type = AndroidInputHandler::JOY_EVENT_HAT; int hat = 0; if (p_hat_x != 0) { if (p_hat_x < 0) @@ -364,21 +381,24 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyhat(JNIEnv *env, j } jevent.hat = hat; - os_android->process_joy_event(jevent); + input_handler->process_joy_event(jevent); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv *env, jclass clazz, jint p_device, jboolean p_connected, jstring p_name) { - if (os_android) { - String name = jstring_to_string(p_name, env); - os_android->joy_connection_changed(p_device, p_connected, name); - } + if (step <= 0) + return; + + String name = jstring_to_string(p_name, env); + input_handler->joy_connection_changed(p_device, p_connected, name); } +// Called on the UI thread JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_keycode, jint p_scancode, jint p_unicode_char, jboolean p_pressed) { - if (step == 0) + if (step <= 0) return; - os_android->process_key_event(p_keycode, p_scancode, p_unicode_char, p_pressed); + input_handler->process_key_event(p_keycode, p_scancode, p_unicode_char, p_pressed); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv *env, jclass clazz, jfloat x, jfloat y, jfloat z) { @@ -398,14 +418,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv *env } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv *env, jclass clazz) { - if (step == 0) + if (step <= 0) return; os_android->main_loop_focusin(); } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env, jclass clazz) { - if (step == 0) + if (step <= 0) return; os_android->main_loop_focusout(); @@ -483,7 +503,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResu } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz) { - if (step == 0) + if (step <= 0) return; if (os_android->get_main_loop()) { @@ -492,7 +512,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNI } JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz) { - if (step == 0) + if (step <= 0) return; if (os_android->get_main_loop()) { diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 8686934b3a54..36a2c7cd6abd 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -47,7 +47,6 @@ #include #include -#include "android_keys_utils.h" #include "java_godot_io_wrapper.h" #include "java_godot_wrapper.h" @@ -181,6 +180,7 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int AudioDriverManager::initialize(p_audio_driver); input = memnew(InputDefault); + input->set_use_input_buffering(true); // Needed because events will come directly from the UI thread input->set_fallback_mapping(godot_java->get_input_fallback_mapping()); //power_manager = memnew(PowerAndroid); @@ -246,11 +246,11 @@ bool OS_Android::is_mouse_grab_enabled() const { } Point2 OS_Android::get_mouse_position() const { - return hover_prev_pos; + return input->get_mouse_position(); } int OS_Android::get_mouse_button_state() const { - return buttons_state; + return input->get_mouse_button_mask(); } void OS_Android::set_window_title(const String &p_title) { @@ -327,337 +327,6 @@ void OS_Android::main_loop_focusin() { audio_driver_android.set_pause(false); } -void OS_Android::process_joy_event(OS_Android::JoypadEvent p_event) { - switch (p_event.type) { - case JOY_EVENT_BUTTON: - input->joy_button(p_event.device, p_event.index, p_event.pressed); - break; - case JOY_EVENT_AXIS: - InputDefault::JoyAxis value; - value.min = -1; - value.value = p_event.value; - input->joy_axis(p_event.device, p_event.index, value); - break; - case JOY_EVENT_HAT: - input->joy_hat(p_event.device, p_event.hat); - break; - default: - return; - } -} - -void OS_Android::_set_key_modifier_state(Ref ev) const { - ev->set_shift(shift_mem); - ev->set_alt(alt_mem); - ev->set_metakey(meta_mem); - ev->set_control(control_mem); -} - -void OS_Android::process_event(Ref p_event) { - input->parse_input_event(p_event); -} - -void OS_Android::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) { - Ref ev; - ev.instance(); - int val = p_unicode_char; - unsigned int scancode = android_get_keysym(p_keycode); - unsigned int phy_scancode = android_get_keysym(p_scancode); - - switch (scancode) { - case KEY_SHIFT: { - shift_mem = p_pressed; - } break; - case KEY_ALT: { - alt_mem = p_pressed; - } break; - case KEY_CONTROL: { - control_mem = p_pressed; - } break; - case KEY_META: { - meta_mem = p_pressed; - } break; - } - - ev->set_scancode(scancode); - ev->set_physical_scancode(phy_scancode); - - ev->set_unicode(val); - ev->set_pressed(p_pressed); - - _set_key_modifier_state(ev); - - if (val == '\n') { - ev->set_scancode(KEY_ENTER); - } else if (val == 61448) { - ev->set_scancode(KEY_BACKSPACE); - ev->set_unicode(KEY_BACKSPACE); - } else if (val == 61453) { - ev->set_scancode(KEY_ENTER); - ev->set_unicode(KEY_ENTER); - } else if (p_scancode == 4) { - main_loop_request_go_back(); - } - - input->parse_input_event(ev); -} - -void OS_Android::process_touch(int p_event, int p_pointer, const Vector &p_points) { - switch (p_event) { - case AMOTION_EVENT_ACTION_DOWN: { //gesture begin - if (touch.size()) { - //end all if exist - for (int i = 0; i < touch.size(); i++) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(false); - ev->set_position(touch[i].pos); - input->parse_input_event(ev); - } - } - - touch.resize(p_points.size()); - for (int i = 0; i < p_points.size(); i++) { - touch.write[i].id = p_points[i].id; - touch.write[i].pos = p_points[i].pos; - } - - //send touch - for (int i = 0; i < touch.size(); i++) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(true); - ev->set_position(touch[i].pos); - input->parse_input_event(ev); - } - - } break; - case AMOTION_EVENT_ACTION_MOVE: { //motion - ERR_FAIL_COND(touch.size() != p_points.size()); - - for (int i = 0; i < touch.size(); i++) { - int idx = -1; - for (int j = 0; j < p_points.size(); j++) { - if (touch[i].id == p_points[j].id) { - idx = j; - break; - } - } - - ERR_CONTINUE(idx == -1); - - if (touch[i].pos == p_points[idx].pos) - continue; //no move unncesearily - - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_position(p_points[idx].pos); - ev->set_relative(p_points[idx].pos - touch[i].pos); - input->parse_input_event(ev); - touch.write[i].pos = p_points[idx].pos; - } - - } break; - case AMOTION_EVENT_ACTION_CANCEL: - case AMOTION_EVENT_ACTION_UP: { //release - if (touch.size()) { - //end all if exist - for (int i = 0; i < touch.size(); i++) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(false); - ev->set_position(touch[i].pos); - input->parse_input_event(ev); - } - touch.clear(); - } - } break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: { // add touch - for (int i = 0; i < p_points.size(); i++) { - if (p_points[i].id == p_pointer) { - TouchPos tp = p_points[i]; - touch.push_back(tp); - - Ref ev; - ev.instance(); - - ev->set_index(tp.id); - ev->set_pressed(true); - ev->set_position(tp.pos); - input->parse_input_event(ev); - - break; - } - } - } break; - case AMOTION_EVENT_ACTION_POINTER_UP: { // remove touch - for (int i = 0; i < touch.size(); i++) { - if (touch[i].id == p_pointer) { - Ref ev; - ev.instance(); - ev->set_index(touch[i].id); - ev->set_pressed(false); - ev->set_position(touch[i].pos); - input->parse_input_event(ev); - touch.remove(i); - - break; - } - } - } break; - } -} - -void OS_Android::process_hover(int p_type, Point2 p_pos) { - // https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER - switch (p_type) { - case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move - case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter - case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit - Ref 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); - input->parse_input_event(ev); - hover_prev_pos = p_pos; - } break; - } -} - -void OS_Android::process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor, float event_horizontal_factor) { - int event_buttons_mask = _android_button_mask_to_godot_button_mask(event_android_buttons_mask); - switch (event_action) { - case AMOTION_EVENT_ACTION_BUTTON_PRESS: - case AMOTION_EVENT_ACTION_BUTTON_RELEASE: { - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(event_pos); - ev->set_global_position(event_pos); - ev->set_pressed(event_action == AMOTION_EVENT_ACTION_BUTTON_PRESS); - int changed_button_mask = buttons_state ^ event_buttons_mask; - - buttons_state = event_buttons_mask; - - ev->set_button_index(_button_index_from_mask(changed_button_mask)); - ev->set_button_mask(event_buttons_mask); - input->parse_input_event(ev); - } break; - - case AMOTION_EVENT_ACTION_MOVE: { - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(event_pos); - ev->set_global_position(event_pos); - ev->set_relative(event_pos - hover_prev_pos); - ev->set_button_mask(event_buttons_mask); - input->parse_input_event(ev); - hover_prev_pos = event_pos; - } break; - case AMOTION_EVENT_ACTION_SCROLL: { - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(event_pos); - ev->set_global_position(event_pos); - ev->set_pressed(true); - buttons_state = event_buttons_mask; - if (event_vertical_factor > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, event_vertical_factor); - } else if (event_vertical_factor < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -event_vertical_factor); - } - - if (event_horizontal_factor > 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, event_horizontal_factor); - } else if (event_horizontal_factor < 0) { - _wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -event_horizontal_factor); - } - } break; - } -} - -void OS_Android::_wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor) { - Ref evd = ev->duplicate(); - evd->set_button_index(wheel_button); - evd->set_button_mask(event_buttons_mask ^ (1 << (wheel_button - 1))); - evd->set_factor(factor); - input->parse_input_event(evd); - Ref evdd = evd->duplicate(); - evdd->set_pressed(false); - evdd->set_button_mask(event_buttons_mask); - input->parse_input_event(evdd); -} - -void OS_Android::process_double_tap(int event_android_button_mask, Point2 p_pos) { - int event_button_mask = _android_button_mask_to_godot_button_mask(event_android_button_mask); - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(p_pos); - ev->set_global_position(p_pos); - ev->set_pressed(event_button_mask != 0); - ev->set_button_index(_button_index_from_mask(event_button_mask)); - ev->set_button_mask(event_button_mask); - ev->set_doubleclick(true); - input->parse_input_event(ev); -} - -void OS_Android::process_scroll(Point2 p_pos) { - Ref ev; - ev.instance(); - _set_key_modifier_state(ev); - ev->set_position(p_pos); - ev->set_delta(p_pos - scroll_prev_pos); - input->parse_input_event(ev); - scroll_prev_pos = p_pos; -} - -int OS_Android::_button_index_from_mask(int button_mask) { - switch (button_mask) { - case BUTTON_MASK_LEFT: - return BUTTON_LEFT; - case BUTTON_MASK_RIGHT: - return BUTTON_RIGHT; - case BUTTON_MASK_MIDDLE: - return BUTTON_MIDDLE; - case BUTTON_MASK_XBUTTON1: - return BUTTON_XBUTTON1; - case BUTTON_MASK_XBUTTON2: - return BUTTON_XBUTTON2; - default: - return 0; - } -} - -int OS_Android::_android_button_mask_to_godot_button_mask(int android_button_mask) { - int godot_button_mask = 0; - if (android_button_mask & AMOTION_EVENT_BUTTON_PRIMARY) { - godot_button_mask |= BUTTON_MASK_LEFT; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - godot_button_mask |= BUTTON_MASK_RIGHT; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_TERTIARY) { - godot_button_mask |= BUTTON_MASK_MIDDLE; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_BACK) { - godot_button_mask |= BUTTON_MASK_XBUTTON1; - } - if (android_button_mask & AMOTION_EVENT_BUTTON_SECONDARY) { - godot_button_mask |= BUTTON_MASK_XBUTTON2; - } - - return godot_button_mask; -} - void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) { input->set_accelerometer(p_accelerometer); } @@ -712,11 +381,6 @@ void OS_Android::init_video_mode(int p_video_width, int p_video_height) { default_videomode.resizable = false; } -void OS_Android::main_loop_request_go_back() { - if (main_loop) - main_loop->notification(MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST); -} - void OS_Android::set_display_size(Size2 p_size) { default_videomode.width = p_size.x; default_videomode.height = p_size.y; @@ -817,10 +481,6 @@ void OS_Android::set_context_is_16_bits(bool p_is_16) { // rasterizer->set_force_16_bits_fbo(p_is_16); } -void OS_Android::joy_connection_changed(int p_device, bool p_connected, String p_name) { - return input->joy_connection_changed(p_device, p_connected, p_name, ""); -} - bool OS_Android::is_joy_known(int p_device) { return input->is_joy_mapped(p_device); } @@ -860,7 +520,6 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god default_videomode.height = 600; default_videomode.fullscreen = true; default_videomode.resizable = false; - buttons_state = 0; main_loop = NULL; gl_extensions = NULL; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 0e979d19a837..1c659fd0dd3f 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -32,7 +32,6 @@ #define OS_ANDROID_H #include "audio_driver_opensl.h" -#include "core/os/input.h" #include "core/os/main_loop.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" @@ -43,32 +42,6 @@ class GodotJavaWrapper; class GodotIOJavaWrapper; class OS_Android : public OS_Unix { -public: - struct TouchPos { - int id; - Point2 pos; - }; - - enum { - JOY_EVENT_BUTTON = 0, - JOY_EVENT_AXIS = 1, - JOY_EVENT_HAT = 2 - }; - - struct JoypadEvent { - int device; - int type; - int index; - bool pressed; - float value; - int hat; - }; - -private: - Vector 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; @@ -93,21 +66,6 @@ class OS_Android : public OS_Unix { int video_driver_index; - bool alt_mem = false; - bool shift_mem = false; - bool control_mem = false; - bool meta_mem = false; - - int buttons_state; - - void _set_key_modifier_state(Ref ev) const; - - static int _button_index_from_mask(int button_mask); - - static int _android_button_mask_to_godot_button_mask(int android_button_mask); - - void _wheel_button_click(int event_buttons_mask, const Ref &ev, int wheel_button, float factor); - public: // functions used by main to initialize/deinitialize the OS virtual int get_video_driver_count() const; @@ -162,7 +120,6 @@ class OS_Android : public OS_Unix { void main_loop_begin(); bool main_loop_iterate(); - void main_loop_request_go_back(); void main_loop_end(); void main_loop_focusout(); void main_loop_focusin(); @@ -200,19 +157,10 @@ class OS_Android : public OS_Unix { void process_gravity(const Vector3 &p_gravity); void process_magnetometer(const Vector3 &p_magnetometer); void process_gyroscope(const Vector3 &p_gyroscope); - void process_touch(int p_event, int p_pointer, const Vector &p_points); - void process_hover(int p_type, Point2 p_pos); - void process_mouse_event(int event_action, int event_android_buttons_mask, Point2 event_pos, float event_vertical_factor = 0, float event_horizontal_factor = 0); - void process_double_tap(int event_android_button_mask, Point2 p_pos); - void process_scroll(Point2 p_pos); - void process_joy_event(JoypadEvent p_event); - void process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed); - void process_event(Ref p_event); void init_video_mode(int p_video_width, int p_video_height); virtual bool is_joy_known(int p_device); virtual String get_joy_guid(int p_device) const; - void joy_connection_changed(int p_device, bool p_connected, String p_name); void vibrate_handheld(int p_duration_ms); virtual bool _check_internal_feature_support(const String &p_feature);