From 370ae3512deda40b2659a1192f302298e269305f Mon Sep 17 00:00:00 2001 From: Jamil Halabi Date: Fri, 15 Jul 2016 15:31:34 +0800 Subject: [PATCH] Added gyroscope support to Godot and Android --- core/os/input.cpp | 1 + core/os/input.h | 1 + doc/base/classes.xml | 7 ++++++ main/input_default.cpp | 14 ++++++++++++ main/input_default.h | 3 +++ platform/android/godot_android.cpp | 22 ++++++++++++++++++- .../java/src/org/godotengine/godot/Godot.java | 7 ++++++ .../src/org/godotengine/godot/GodotLib.java | 1 + platform/android/java_glue.cpp | 11 ++++++++++ platform/android/java_glue.h | 1 + platform/android/os_android.cpp | 5 +++++ platform/android/os_android.h | 1 + 12 files changed, 73 insertions(+), 1 deletion(-) diff --git a/core/os/input.cpp b/core/os/input.cpp index efbae579506..531db738386 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -66,6 +66,7 @@ void Input::_bind_methods() { ObjectTypeDB::bind_method(_MD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer); ObjectTypeDB::bind_method(_MD("get_magnetometer"),&Input::get_magnetometer); + ObjectTypeDB::bind_method(_MD("get_gyroscope"),&Input::get_gyroscope); //ObjectTypeDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos); - this is not the function you want ObjectTypeDB::bind_method(_MD("get_mouse_speed"),&Input::get_mouse_speed); ObjectTypeDB::bind_method(_MD("get_mouse_button_mask"),&Input::get_mouse_button_mask); diff --git a/core/os/input.h b/core/os/input.h index d11703470bd..16bcc0ff9a3 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -82,6 +82,7 @@ public: virtual Vector3 get_accelerometer()=0; virtual Vector3 get_magnetometer()=0; + virtual Vector3 get_gyroscope()=0; virtual void action_press(const StringName& p_action)=0; virtual void action_release(const StringName& p_action)=0; diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 50d550f6b2c..890b617aa28 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -15797,6 +15797,13 @@ Returns an [Array] containing the device IDs of all currently connected joysticks. + + + + + If the device has a gyroscope, this will return the rate of rotation in rad/s around a device's x, y, and z axis. + + diff --git a/main/input_default.cpp b/main/input_default.cpp index 945898f1f3f..5e66a8b5851 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -259,6 +259,12 @@ Vector3 InputDefault::get_magnetometer() { return magnetometer; } +Vector3 InputDefault::get_gyroscope() { + + _THREAD_SAFE_METHOD_ + return gyroscope; +} + void InputDefault::parse_input_event(const InputEvent& p_event) { _THREAD_SAFE_METHOD_ @@ -386,6 +392,14 @@ void InputDefault::set_magnetometer(const Vector3& p_magnetometer) { } +void InputDefault::set_gyroscope(const Vector3& p_gyroscope) { + + _THREAD_SAFE_METHOD_ + + gyroscope=p_gyroscope; + +} + void InputDefault::set_main_loop(MainLoop *p_main_loop) { main_loop=p_main_loop; diff --git a/main/input_default.h b/main/input_default.h index 644af15e3b8..cb71312e22f 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -44,6 +44,7 @@ class InputDefault : public Input { Map custom_action_press; Vector3 accelerometer; Vector3 magnetometer; + Vector3 gyroscope; Vector2 mouse_pos; MainLoop *main_loop; @@ -179,6 +180,7 @@ public: virtual Vector3 get_accelerometer(); virtual Vector3 get_magnetometer(); + virtual Vector3 get_gyroscope(); virtual Point2 get_mouse_pos() const; virtual Point2 get_mouse_speed() const; @@ -190,6 +192,7 @@ public: void parse_input_event(const InputEvent& p_event); void set_accelerometer(const Vector3& p_accel); void set_magnetometer(const Vector3& p_magnetometer); + void set_gyroscope(const Vector3& p_gyroscope); void set_joy_axis(int p_device,int p_axis,float p_value); virtual void start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration=0); diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp index 9f909d70412..2371274d9d6 100644 --- a/platform/android/godot_android.cpp +++ b/platform/android/godot_android.cpp @@ -314,6 +314,7 @@ struct engine { ASensorManager* sensorManager; const ASensor* accelerometerSensor; const ASensor* magnetometerSensor; + const ASensor* gyroscopeSensor; ASensorEventQueue* sensorEventQueue; bool display_active; @@ -745,6 +746,15 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) { ASensorEventQueue_setEventRate(engine->sensorEventQueue, engine->magnetometerSensor, (1000L/60)*1000); + } + // And the gyroscope. + if (engine->gyroscopeSensor != NULL) { + ASensorEventQueue_enableSensor(engine->sensorEventQueue, + engine->gyroscopeSensor); + // We'd like to get 60 events per second (in us). + ASensorEventQueue_setEventRate(engine->sensorEventQueue, + engine->gyroscopeSensor, (1000L/60)*1000); + } engine->animating = 1; break; @@ -759,6 +769,10 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) { ASensorEventQueue_disableSensor(engine->sensorEventQueue, engine->magnetometerSensor); } + if (engine->gyroscopeSensor != NULL) { + ASensorEventQueue_disableSensor(engine->sensorEventQueue, + engine->gyroscopeSensor); + } // Also stop animating. engine->animating = 0; engine_draw_frame(engine); @@ -788,6 +802,8 @@ void android_main(struct android_app* state) { ASENSOR_TYPE_ACCELEROMETER); engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, ASENSOR_TYPE_MAGNETIC_FIELD); + engine.gyroscopeSensor = ASensorManager_getDefaultSensor(engine.sensorManager, + ASENSOR_TYPE_GYROSCOPE); engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL); @@ -828,7 +844,7 @@ void android_main(struct android_app* state) { // If a sensor has data, process it now. // LOGI("events\n"); if (ident == LOOPER_ID_USER) { - if (engine.accelerometerSensor != NULL || engine.magnetometerSensor != NULL) { + if (engine.accelerometerSensor != NULL || engine.magnetometerSensor != NULL || engine.gyroscopeSensor != NULL) { ASensorEvent event; while (ASensorEventQueue_getEvents(engine.sensorEventQueue, &event, 1) > 0) { @@ -843,6 +859,10 @@ void android_main(struct android_app* state) { engine.os->process_magnetometer(Vector3(event.magnetic.x, event.magnetic.y, event.magnetic.z)); } + if (event.vector != NULL) { + engine.os->process_gyroscope(Vector3(event.vector.x, event.vector.y, + event.vector.z)); + } } } diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index 4c0f4878f52..4b80db7e33f 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -217,6 +217,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC private SensorManager mSensorManager; private Sensor mAccelerometer; private Sensor mMagnetometer; + private Sensor mGyroscope; public FrameLayout layout; public RelativeLayout adLayout; @@ -387,6 +388,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); + mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); + mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); result_callback = null; @@ -604,6 +607,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mView.onResume(); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); + mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); GodotLib.focusin(); if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+ Window window = getWindow(); @@ -670,6 +674,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC if (typeOfSensor == event.sensor.TYPE_MAGNETIC_FIELD) { GodotLib.magnetometer(x,y,z); } + if (typeOfSensor == event.sensor.TYPE_GYROSCOPE) { + GodotLib.gyroscope(x,y,z); + } } @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java index df181ae1bb5..9a2ea7df105 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java @@ -52,6 +52,7 @@ public class GodotLib { public static native void touch(int what,int pointer,int howmany, int[] arr); public static native void accelerometer(float x, float y, float z); public static native void magnetometer(float x, float y, float z); + public static native void gyroscope(float x, float y, float z); public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed); public static native void joybutton(int p_device, int p_but, boolean p_pressed); public static native void joyaxis(int p_device, int p_axis, float p_value); diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 45d02876bab..b9d178280c7 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -653,6 +653,7 @@ static bool quit_request=false; static Size2 new_size; static Vector3 accelerometer; static Vector3 magnetometer; +static Vector3 gyroscope; static HashMap jni_singletons; static jobject godot_io; @@ -1093,6 +1094,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv * env, jo os_android->process_magnetometer(magnetometer); + os_android->process_gyroscope(gyroscope); + if (os_android->main_loop_iterate()==true) { jclass cls = env->FindClass("org/godotengine/godot/Godot"); @@ -1501,6 +1504,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv * } +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z) { + + input_mutex->lock(); + gyroscope=Vector3(x,y,z); + input_mutex->unlock(); + +} + JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj){ if (!suspend_mutex) diff --git a/platform/android/java_glue.h b/platform/android/java_glue.h index f7916efe2c5..ae7ced45ee3 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -50,6 +50,7 @@ extern "C" { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv * env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z); + JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_gyroscope(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv * env, jobject obj); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 13cdf2a020a..3c2b4c22e71 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -614,6 +614,11 @@ void OS_Android::process_magnetometer(const Vector3& p_magnetometer) { input->set_magnetometer(p_magnetometer); } +void OS_Android::process_gyroscope(const Vector3& p_gyroscope) { + + input->set_gyroscope(p_gyroscope); +} + bool OS_Android::has_touchscreen_ui_hint() const { return true; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index e82e08ea491..7f39784a749 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -242,6 +242,7 @@ public: void process_accelerometer(const Vector3& p_accelerometer); 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& p_points); void process_joy_event(JoystickEvent p_event); void process_event(InputEvent p_event);