Merge pull request #42360 from thebestnom/android-click-support-3.2

[3.2] Support mouse events on Android
This commit is contained in:
Rémi Verschelde 2020-10-30 15:38:33 +01:00 committed by GitHub
commit 61ad669892
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 280 additions and 235 deletions

View file

@ -31,128 +31,9 @@
#ifndef ANDROID_KEYS_UTILS_H
#define ANDROID_KEYS_UTILS_H
#include <android/input.h>
#include <core/os/keyboard.h>
/*
* Android Key codes.
*/
enum {
AKEYCODE_UNKNOWN = 0,
AKEYCODE_SOFT_LEFT = 1,
AKEYCODE_SOFT_RIGHT = 2,
AKEYCODE_HOME = 3,
AKEYCODE_BACK = 4,
AKEYCODE_CALL = 5,
AKEYCODE_ENDCALL = 6,
AKEYCODE_0 = 7,
AKEYCODE_1 = 8,
AKEYCODE_2 = 9,
AKEYCODE_3 = 10,
AKEYCODE_4 = 11,
AKEYCODE_5 = 12,
AKEYCODE_6 = 13,
AKEYCODE_7 = 14,
AKEYCODE_8 = 15,
AKEYCODE_9 = 16,
AKEYCODE_STAR = 17,
AKEYCODE_POUND = 18,
AKEYCODE_DPAD_UP = 19,
AKEYCODE_DPAD_DOWN = 20,
AKEYCODE_DPAD_LEFT = 21,
AKEYCODE_DPAD_RIGHT = 22,
AKEYCODE_DPAD_CENTER = 23,
AKEYCODE_VOLUME_UP = 24,
AKEYCODE_VOLUME_DOWN = 25,
AKEYCODE_POWER = 26,
AKEYCODE_CAMERA = 27,
AKEYCODE_CLEAR = 28,
AKEYCODE_A = 29,
AKEYCODE_B = 30,
AKEYCODE_C = 31,
AKEYCODE_D = 32,
AKEYCODE_E = 33,
AKEYCODE_F = 34,
AKEYCODE_G = 35,
AKEYCODE_H = 36,
AKEYCODE_I = 37,
AKEYCODE_J = 38,
AKEYCODE_K = 39,
AKEYCODE_L = 40,
AKEYCODE_M = 41,
AKEYCODE_N = 42,
AKEYCODE_O = 43,
AKEYCODE_P = 44,
AKEYCODE_Q = 45,
AKEYCODE_R = 46,
AKEYCODE_S = 47,
AKEYCODE_T = 48,
AKEYCODE_U = 49,
AKEYCODE_V = 50,
AKEYCODE_W = 51,
AKEYCODE_X = 52,
AKEYCODE_Y = 53,
AKEYCODE_Z = 54,
AKEYCODE_COMMA = 55,
AKEYCODE_PERIOD = 56,
AKEYCODE_ALT_LEFT = 57,
AKEYCODE_ALT_RIGHT = 58,
AKEYCODE_SHIFT_LEFT = 59,
AKEYCODE_SHIFT_RIGHT = 60,
AKEYCODE_TAB = 61,
AKEYCODE_SPACE = 62,
AKEYCODE_SYM = 63,
AKEYCODE_EXPLORER = 64,
AKEYCODE_ENVELOPE = 65,
AKEYCODE_ENTER = 66,
AKEYCODE_DEL = 67,
AKEYCODE_GRAVE = 68,
AKEYCODE_MINUS = 69,
AKEYCODE_EQUALS = 70,
AKEYCODE_LEFT_BRACKET = 71,
AKEYCODE_RIGHT_BRACKET = 72,
AKEYCODE_BACKSLASH = 73,
AKEYCODE_SEMICOLON = 74,
AKEYCODE_APOSTROPHE = 75,
AKEYCODE_SLASH = 76,
AKEYCODE_AT = 77,
AKEYCODE_NUM = 78,
AKEYCODE_HEADSETHOOK = 79,
AKEYCODE_FOCUS = 80, // *Camera* focus
AKEYCODE_PLUS = 81,
AKEYCODE_MENU = 82,
AKEYCODE_NOTIFICATION = 83,
AKEYCODE_SEARCH = 84,
AKEYCODE_MEDIA_PLAY_PAUSE = 85,
AKEYCODE_MEDIA_STOP = 86,
AKEYCODE_MEDIA_NEXT = 87,
AKEYCODE_MEDIA_PREVIOUS = 88,
AKEYCODE_MEDIA_REWIND = 89,
AKEYCODE_MEDIA_FAST_FORWARD = 90,
AKEYCODE_MUTE = 91,
AKEYCODE_PAGE_UP = 92,
AKEYCODE_PAGE_DOWN = 93,
AKEYCODE_PICTSYMBOLS = 94,
AKEYCODE_SWITCH_CHARSET = 95,
AKEYCODE_BUTTON_A = 96,
AKEYCODE_BUTTON_B = 97,
AKEYCODE_BUTTON_C = 98,
AKEYCODE_BUTTON_X = 99,
AKEYCODE_BUTTON_Y = 100,
AKEYCODE_BUTTON_Z = 101,
AKEYCODE_BUTTON_L1 = 102,
AKEYCODE_BUTTON_R1 = 103,
AKEYCODE_BUTTON_L2 = 104,
AKEYCODE_BUTTON_R2 = 105,
AKEYCODE_BUTTON_THUMBL = 106,
AKEYCODE_BUTTON_THUMBR = 107,
AKEYCODE_BUTTON_START = 108,
AKEYCODE_BUTTON_SELECT = 109,
AKEYCODE_BUTTON_MODE = 110,
// 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.
};
struct _WinTranslatePair {
unsigned int keysym;
@ -247,6 +128,8 @@ static _WinTranslatePair _ak_to_keycode[] = {
{ KEY_BACKSLASH, AKEYCODE_BACKSLASH },
{ KEY_BRACKETLEFT, AKEYCODE_LEFT_BRACKET },
{ KEY_BRACKETRIGHT, AKEYCODE_RIGHT_BRACKET },
{ KEY_CONTROL, AKEYCODE_CTRL_LEFT },
{ KEY_CONTROL, AKEYCODE_CTRL_RIGHT },
{ KEY_UNKNOWN, 0 }
};
/*

View file

@ -72,6 +72,7 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings.Secure;
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@ -989,65 +990,6 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
}
}
public boolean gotTouchEvent(final MotionEvent event) {
final int evcount = event.getPointerCount();
if (evcount == 0)
return true;
if (mView != null) {
final int[] arr = new int[event.getPointerCount() * 3];
for (int i = 0; i < event.getPointerCount(); i++) {
arr[i * 3 + 0] = (int)event.getPointerId(i);
arr[i * 3 + 1] = (int)event.getX(i);
arr[i * 3 + 2] = (int)event.getY(i);
}
final int pointer_idx = event.getPointerId(event.getActionIndex());
//System.out.printf("gaction: %d\n",event.getAction());
final int action = event.getAction() & MotionEvent.ACTION_MASK;
mView.queueEvent(new Runnable() {
@Override
public void run() {
switch (action) {
case MotionEvent.ACTION_DOWN: {
GodotLib.touch(0, 0, evcount, arr);
//System.out.printf("action down at: %f,%f\n", event.getX(),event.getY());
} break;
case MotionEvent.ACTION_MOVE: {
GodotLib.touch(1, 0, evcount, arr);
/*
for(int i=0;i<event.getPointerCount();i++) {
System.out.printf("%d - moved to: %f,%f\n",i, event.getX(i),event.getY(i));
}
*/
} break;
case MotionEvent.ACTION_POINTER_UP: {
GodotLib.touch(4, pointer_idx, evcount, arr);
//System.out.printf("%d - s.up at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_POINTER_DOWN: {
GodotLib.touch(3, pointer_idx, evcount, arr);
//System.out.printf("%d - s.down at: %f,%f\n",pointer_idx, event.getX(pointer_idx),event.getY(pointer_idx));
} break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
GodotLib.touch(2, 0, evcount, arr);
/*
for(int i=0;i<event.getPointerCount();i++) {
System.out.printf("%d - up! %f,%f\n",i, event.getX(i),event.getY(i));
}
*/
} break;
}
}
});
}
return true;
}
public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) {
String s = event.getCharacters();
if (s == null || s.length() == 0)

View file

@ -93,17 +93,19 @@ public class GodotLib {
/**
* Forward touch events from the main thread to the GL thread.
*/
public static native void touch(int what, int pointer, int howmany, int[] arr);
public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions);
public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions, int buttonsMask);
public static native void touch(int inputDevice, int event, int pointer, int pointerCount, float[] positions, int buttonsMask, float verticalFactor, float horizontalFactor);
/**
* Forward hover events from the main thread to the GL thread.
*/
public static native void hover(int type, int x, int y);
public static native void hover(int type, float x, float y);
/**
* Forward double_tap events from the main thread to the GL thread.
*/
public static native void doubletap(int x, int y);
public static native void doubleTap(int buttonMask, int x, int y);
/**
* Forward scroll events from the main thread to the GL thread.

View file

@ -99,7 +99,7 @@ public class GodotView extends GLSurfaceView {
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
this.detector.onTouchEvent(event);
return godot.gotTouchEvent(event);
return inputHandler.onTouchEvent(event);
}
@Override

View file

@ -33,7 +33,6 @@ package org.godotengine.godot.input;
import org.godotengine.godot.GodotLib;
import org.godotengine.godot.GodotView;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
@ -76,10 +75,11 @@ public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener
//Log.i("GodotGesture", "onDoubleTap");
final int x = Math.round(event.getX());
final int y = Math.round(event.getY());
final int buttonMask = event.getButtonState();
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.doubletap(x, y);
GodotLib.doubleTap(buttonMask, x, y);
}
});
return true;

View file

@ -36,6 +36,7 @@ import org.godotengine.godot.GodotLib;
import org.godotengine.godot.GodotView;
import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
import android.os.Build;
import android.util.Log;
import android.view.InputDevice;
import android.view.InputDevice.MotionRange;
@ -157,6 +158,53 @@ public class GodotInputHandler implements InputDeviceListener {
return true;
}
public boolean onTouchEvent(final MotionEvent event) {
// Mouse drag (mouse pressed and move) doesn't fire onGenericMotionEvent so this is needed
if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (event.getAction() != MotionEvent.ACTION_MOVE) {
// we return true because every time a mouse event is fired, the event is already handled
// in onGenericMotionEvent, so by touch event we can say that the event is also handled
return true;
}
return handleMouseEvent(event);
}
final int evcount = event.getPointerCount();
if (evcount == 0)
return true;
if (godotView != null) {
final float[] arr = new float[event.getPointerCount() * 3]; // pointerId1, x1, y1, pointerId2, etc...
for (int i = 0; i < event.getPointerCount(); i++) {
arr[i * 3 + 0] = event.getPointerId(i);
arr[i * 3 + 1] = event.getX(i);
arr[i * 3 + 2] = event.getY(i);
}
final int action = event.getActionMasked();
godotView.queueEvent(new Runnable() {
@Override
public void run() {
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_MOVE: {
GodotLib.touch(event.getSource(), action, 0, evcount, arr);
} break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN: {
int pointer_idx = event.getPointerId(event.getActionIndex());
GodotLib.touch(event.getSource(), action, pointer_idx, evcount, arr);
} break;
}
}
});
}
return true;
}
public boolean onGenericMotionEvent(MotionEvent event) {
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) {
@ -191,8 +239,8 @@ public class GodotInputHandler implements InputDeviceListener {
return true;
}
} else if ((event.getSource() & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) {
final int x = Math.round(event.getX());
final int y = Math.round(event.getY());
final float x = event.getX();
final float y = event.getY();
final int type = event.getAction();
queueEvent(new Runnable() {
@Override
@ -201,6 +249,10 @@ public class GodotInputHandler implements InputDeviceListener {
}
});
return true;
} else if ((event.getSource() & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return handleMouseEvent(event);
}
}
return false;
@ -368,4 +420,53 @@ public class GodotInputHandler implements InputDeviceListener {
return -1;
}
private boolean handleMouseEvent(final MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE:
case MotionEvent.ACTION_HOVER_EXIT: {
final float x = event.getX();
final float y = event.getY();
final int type = event.getAction();
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.hover(type, x, y);
}
});
return true;
}
case MotionEvent.ACTION_BUTTON_PRESS:
case MotionEvent.ACTION_BUTTON_RELEASE:
case MotionEvent.ACTION_MOVE: {
final float x = event.getX();
final float y = event.getY();
final int buttonsMask = event.getButtonState();
final int action = event.getAction();
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask);
}
});
return true;
}
case MotionEvent.ACTION_SCROLL: {
final float x = event.getX();
final float y = event.getY();
final int buttonsMask = event.getButtonState();
final int action = event.getAction();
final float verticalFactor = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
final float horizontalFactor = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
queueEvent(new Runnable() {
@Override
public void run() {
GodotLib.touch(event.getSource(), action, 0, 1, new float[] { 0, x, y }, buttonsMask, verticalFactor, horizontalFactor);
}
});
}
}
return false;
}
}

View file

@ -49,6 +49,8 @@
#include "os_android.h"
#include "string_android.h"
#include "thread_jandroid.h"
#include <android/input.h>
#include <unistd.h>
static JavaClassWrapper *java_class_wrapper = NULL;
@ -272,42 +274,51 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl
}
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint count, jintArray positions) {
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)
return;
Vector<OS_Android::TouchPos> points;
for (int i = 0; i < count; i++) {
jint p[3];
env->GetIntArrayRegion(positions, i * 3, 3, p);
for (int i = 0; i < pointer_count; i++) {
jfloat p[3];
env->GetFloatArrayRegion(positions, i * 3, 3, p);
OS_Android::TouchPos tp;
tp.pos = Point2(p[1], p[2]);
tp.id = p[0];
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);
} else {
os_android->process_touch(ev, pointer, points);
/*
if (os_android)
os_android->process_touch(ev,pointer,points);
*/
}
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jint p_x, jint p_y) {
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);
}
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);
}
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);
}
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)
return;
os_android->process_hover(p_type, Point2(p_x, p_y));
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jclass clazz, jint p_x, jint p_y) {
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)
return;
os_android->process_double_tap(Point2(p_x, p_y));
os_android->process_double_tap(p_button_mask, Point2(p_x, p_y));
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y) {

View file

@ -44,9 +44,12 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, j
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jboolean p_32_bits);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jclass clazz);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jclass clazz, jint ev, jint pointer, jint count, jintArray positions);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jint p_x, jint p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jclass clazz, jint p_x, jint p_y);
void touch_preprocessing(JNIEnv *env, jclass clazz, jint input_device, jint ev, jint pointer, jint pointer_count, jfloatArray positions, jint buttons_mask = 0, jfloat vertical_factor = 0, jfloat horizontal_factor = 0);
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 positions);
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 positions, jint buttons_mask);
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 positions, jint buttons_mask, jfloat vertical_factor, jfloat horizontal_factor);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jclass clazz, jint p_type, jfloat p_x, jfloat p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubleTap(JNIEnv *env, jclass clazz, jint p_button_mask, jint p_x, jint p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jclass clazz, jint p_x, jint p_y);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jclass clazz, jint p_scancode, jint p_unicode_char, jboolean p_pressed);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jclass clazz, jint p_device, jint p_button, jboolean p_pressed);

View file

@ -45,6 +45,7 @@
#include "file_access_jandroid.h"
#include "net_socket_android.h"
#include <android/input.h>
#include <dlfcn.h>
#include "java_godot_io_wrapper.h"
@ -251,13 +252,11 @@ bool OS_Android::is_mouse_grab_enabled() const {
}
Point2 OS_Android::get_mouse_position() const {
return Point2();
return hover_prev_pos;
}
int OS_Android::get_mouse_button_state() const {
return 0;
return buttons_state;
}
void OS_Android::set_window_title(const String &p_title) {
@ -370,15 +369,13 @@ void OS_Android::process_event(Ref<InputEvent> p_event) {
input->parse_input_event(p_event);
}
void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points) {
switch (p_what) {
case 0: { //gesture begin
void OS_Android::process_touch(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);
@ -396,7 +393,6 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
//send touch
for (int i = 0; i < touch.size(); i++) {
Ref<InputEventScreenTouch> ev;
ev.instance();
ev->set_index(touch[i].id);
@ -406,15 +402,12 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
}
} break;
case 1: { //motion
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;
@ -436,12 +429,11 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
}
} break;
case 2: { //release
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);
@ -452,8 +444,7 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
touch.clear();
}
} break;
case 3: { // add touch
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];
@ -471,11 +462,9 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
}
}
} break;
case 4: { // remove touch
case AMOTION_EVENT_ACTION_POINTER_UP: { // remove touch
for (int i = 0; i < touch.size(); i++) {
if (touch[i].id == p_pointer) {
Ref<InputEventScreenTouch> ev;
ev.instance();
ev->set_index(touch[i].id);
@ -494,9 +483,9 @@ void OS_Android::process_touch(int p_what, int p_pointer, const Vector<TouchPos>
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 7: // hover move
case 9: // hover enter
case 10: { // hover exit
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<InputEventMouseMotion> ev;
ev.instance();
ev->set_position(p_pos);
@ -508,12 +497,78 @@ void OS_Android::process_hover(int p_type, Point2 p_pos) {
}
}
void OS_Android::process_double_tap(Point2 p_pos) {
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<InputEventMouseButton> ev;
ev.instance();
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<InputEventMouseMotion> ev;
ev.instance();
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<InputEventMouseButton> ev;
ev.instance();
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<InputEventMouseButton> &ev, int wheel_button, float factor) {
Ref<InputEventMouseButton> 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<InputEventMouseButton> 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<InputEventMouseButton> ev;
ev.instance();
ev->set_position(p_pos);
ev->set_global_position(p_pos);
ev->set_pressed(false);
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);
}
@ -527,6 +582,44 @@ void OS_Android::process_scroll(Point2 p_pos) {
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);
@ -782,6 +875,7 @@ 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;

View file

@ -97,6 +97,14 @@ private:
int video_driver_index;
int buttons_state;
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<InputEventMouseButton> &ev, int wheel_button, float factor);
public:
// functions used by main to initialize/deinitialize the OS
virtual int get_video_driver_count() const;
@ -187,9 +195,10 @@ public:
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_what, int p_pointer, const Vector<TouchPos> &p_points);
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_double_tap(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_event(Ref<InputEvent> p_event);