Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Clean-up and refactor of the Android input implementation #65398

Merged
merged 2 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions editor/progress_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,9 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int
OS::get_singleton()->force_process_input();
}

#ifndef ANDROID_ENABLED
Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor
#endif
return cancelled;
}

Expand Down
200 changes: 112 additions & 88 deletions platform/android/android_input_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> e
ev->set_control(control_mem);
}

void AndroidInputHandler::process_event(Ref<InputEvent> &p_event) {
input->parse_input_event(p_event);
}

void AndroidInputHandler::process_key_event(int p_scancode, int p_physical_scancode, int p_unicode, bool p_pressed) {
Ref<InputEventKey> ev;
ev.instance();
Expand Down Expand Up @@ -104,20 +100,31 @@ void AndroidInputHandler::process_key_event(int p_scancode, int p_physical_scanc
input->parse_input_event(ev);
}

void AndroidInputHandler::process_touch(int p_event, int p_pointer, const Vector<TouchPos> &p_points) {
void AndroidInputHandler::_parse_all_touch(bool p_pressed) {
if (touch.size()) {
//end all if exist
for (int i = 0; i < touch.size(); i++) {
Ref<InputEventScreenTouch> ev;
ev.instance();
ev->set_index(touch[i].id);
ev->set_pressed(p_pressed);
ev->set_position(touch[i].pos);
input->parse_input_event(ev);
}
}
}

void AndroidInputHandler::_release_all_touch() {
_parse_all_touch(false);
touch.clear();
}

void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const Vector<TouchPos> &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<InputEventScreenTouch> ev;
ev.instance();
ev->set_index(touch[i].id);
ev->set_pressed(false);
ev->set_position(touch[i].pos);
input->parse_input_event(ev);
}
}
// Release any remaining touches or mouse event
_release_mouse_event_info();
_release_all_touch();

touch.resize(p_points.size());
for (int i = 0; i < p_points.size(); i++) {
Expand All @@ -126,18 +133,13 @@ void AndroidInputHandler::process_touch(int p_event, int p_pointer, const Vector
}

//send touch
for (int i = 0; i < touch.size(); i++) {
Ref<InputEventScreenTouch> ev;
ev.instance();
ev->set_index(touch[i].id);
ev->set_pressed(true);
ev->set_position(touch[i].pos);
input->parse_input_event(ev);
}
_parse_all_touch(true);

} break;
case AMOTION_EVENT_ACTION_MOVE: { //motion
ERR_FAIL_COND(touch.size() != p_points.size());
if (touch.size() != p_points.size()) {
return;
}

for (int i = 0; i < touch.size(); i++) {
int idx = -1;
Expand Down Expand Up @@ -166,18 +168,7 @@ void AndroidInputHandler::process_touch(int p_event, int p_pointer, const Vector
} 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<InputEventScreenTouch> 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();
}
_release_all_touch();
} break;
case AMOTION_EVENT_ACTION_POINTER_DOWN: { // add touch
for (int i = 0; i < p_points.size(); i++) {
Expand Down Expand Up @@ -215,73 +206,102 @@ void AndroidInputHandler::process_touch(int p_event, int p_pointer, const Vector
}
}

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) {
void AndroidInputHandler::_parse_mouse_event_info(int buttons_mask, bool p_pressed, bool p_double_click) {
if (!mouse_event_info.valid) {
return;
}

Ref<InputEventMouseButton> ev;
ev.instance();
_set_key_modifier_state(ev);
ev->set_position(mouse_event_info.pos);
ev->set_global_position(mouse_event_info.pos);
ev->set_pressed(p_pressed);
int changed_button_mask = buttons_state ^ buttons_mask;

buttons_state = buttons_mask;

ev->set_button_index(_button_index_from_mask(changed_button_mask));
ev->set_button_mask(buttons_mask);
ev->set_doubleclick(p_double_click);
input->parse_input_event(ev);
hover_prev_pos = mouse_event_info.pos;
}

void AndroidInputHandler::_release_mouse_event_info() {
_parse_mouse_event_info(0, false, false);
mouse_event_info.valid = false;
}

void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click) {
int event_buttons_mask = _android_button_mask_to_godot_button_mask(p_event_android_buttons_mask);
switch (p_event_action) {
case AMOTION_EVENT_ACTION_HOVER_MOVE: // hover move
case AMOTION_EVENT_ACTION_HOVER_ENTER: // hover enter
case AMOTION_EVENT_ACTION_HOVER_EXIT: { // hover exit
// https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER
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);
ev->set_position(p_event_pos);
ev->set_global_position(p_event_pos);
ev->set_relative(p_event_pos - hover_prev_pos);
input->parse_input_event(ev);
hover_prev_pos = p_pos;
hover_prev_pos = p_event_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<InputEventMouseButton> 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;
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_BUTTON_PRESS: {
// Release any remaining touches or mouse event
_release_mouse_event_info();
_release_all_touch();

buttons_state = event_buttons_mask;
mouse_event_info.valid = true;
mouse_event_info.pos = p_event_pos;
_parse_mouse_event_info(event_buttons_mask, true, p_double_click);
} break;

ev->set_button_index(_button_index_from_mask(changed_button_mask));
ev->set_button_mask(event_buttons_mask);
input->parse_input_event(ev);
case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_CANCEL:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
_release_mouse_event_info();
} break;

case AMOTION_EVENT_ACTION_MOVE: {
if (!mouse_event_info.valid) {
return;
}

Ref<InputEventMouseMotion> 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_position(p_event_pos);
ev->set_global_position(p_event_pos);
ev->set_relative(p_event_pos - hover_prev_pos);
ev->set_button_mask(event_buttons_mask);
input->parse_input_event(ev);
hover_prev_pos = event_pos;
mouse_event_info.pos = p_event_pos;
hover_prev_pos = p_event_pos;
} break;

case AMOTION_EVENT_ACTION_SCROLL: {
Ref<InputEventMouseButton> ev;
ev.instance();
_set_key_modifier_state(ev);
ev->set_position(event_pos);
ev->set_global_position(event_pos);
ev->set_position(p_event_pos);
ev->set_global_position(p_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 (p_delta.y > 0) {
_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_UP, p_delta.y);
} else if (p_delta.y < 0) {
_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_DOWN, -p_delta.y);
}

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);
if (p_delta.x > 0) {
_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_RIGHT, p_delta.x);
} else if (p_delta.x < 0) {
_wheel_button_click(event_buttons_mask, ev, BUTTON_WHEEL_LEFT, -p_delta.x);
}
} break;
}
Expand All @@ -299,18 +319,22 @@ void AndroidInputHandler::_wheel_button_click(int event_buttons_mask, const Ref<
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<InputEventMouseButton> 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_magnify(Point2 p_pos, float p_factor) {
Ref<InputEventMagnifyGesture> magnify_event;
magnify_event.instance();
_set_key_modifier_state(magnify_event);
magnify_event->set_position(p_pos);
magnify_event->set_factor(p_factor);
input->parse_input_event(magnify_event);
}

void AndroidInputHandler::process_pan(Point2 p_pos, Vector2 p_delta) {
Ref<InputEventPanGesture> pan_event;
pan_event.instance();
_set_key_modifier_state(pan_event);
pan_event->set_position(p_pos);
pan_event->set_delta(p_delta);
input->parse_input_event(pan_event);
}

int AndroidInputHandler::_button_index_from_mask(int button_mask) {
Expand Down
23 changes: 18 additions & 5 deletions platform/android/android_input_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ class AndroidInputHandler {
Point2 pos;
};

struct MouseEventInfo {
bool valid = false;
Point2 pos;
};

enum {
JOY_EVENT_BUTTON = 0,
JOY_EVENT_AXIS = 1,
Expand All @@ -61,6 +66,7 @@ class AndroidInputHandler {

private:
Vector<TouchPos> touch;
MouseEventInfo mouse_event_info;
Point2 hover_prev_pos; // needed to calculate the relative position on hover events

bool alt_mem = false;
Expand All @@ -80,14 +86,21 @@ class AndroidInputHandler {

void _wheel_button_click(int event_buttons_mask, const Ref<InputEventMouseButton> &ev, int wheel_button, float factor);

void _parse_mouse_event_info(int buttons_mask, bool p_pressed, bool p_double_click);

void _release_mouse_event_info();

void _parse_all_touch(bool p_pressed);

void _release_all_touch();

public:
void process_event(Ref<InputEvent> &p_event);
void process_joy_event(const JoypadEvent &p_event);
void process_key_event(int p_scancode, int p_physical_scancode, int p_unicode, bool p_pressed);
void process_touch(int p_event, int p_pointer, const Vector<TouchPos> &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_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click);
void process_touch_event(int p_event, int p_pointer, const Vector<TouchPos> &p_points);
void process_magnify(Point2 p_pos, float p_factor);
void process_pan(Point2 p_pos, Vector2 p_delta);
void joy_connection_changed(int p_device, bool p_connected, String p_name);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ open class GodotEditor : FullScreenGodotApp() {
}

super.onCreate(savedInstanceState)

// Enable long press, panning and scaling gestures
godotFragment?.mView?.inputHandler?.apply {
enableLongPress(enableLongPressGestures())
enablePanningAndScalingGestures(enablePanAndScaleGestures())
}
}

private fun updateCommandLineParams(args: Array<String>?) {
Expand Down Expand Up @@ -148,6 +154,16 @@ open class GodotEditor : FullScreenGodotApp() {
*/
protected open fun overrideOrientationRequest() = true

/**
* Enable long press gestures for the Godot Android editor.
*/
protected open fun enableLongPressGestures() = true

/**
* Enable pan and scale gestures for the Godot Android editor.
*/
protected open fun enablePanAndScaleGestures() = true

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Check if we got the MANAGE_EXTERNAL_STORAGE permission
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@ package org.godotengine.editor
*/
class GodotGame : GodotEditor() {
override fun overrideOrientationRequest() = false

override fun enableLongPressGestures() = false

override fun enablePanAndScaleGestures() = false
}
Loading