From 4877b714b3f8b0f0af2bce7a32691fc2202c8acc Mon Sep 17 00:00:00 2001 From: fluffrabbit Date: Fri, 27 May 2016 14:29:37 -0300 Subject: [PATCH] Add magnetometer sensor support for Android --- core/os/input.cpp | 1 + core/os/input.h | 1 + main/input_default.cpp | 14 +++++++++ main/input_default.h | 3 ++ platform/android/godot_android.cpp | 31 ++++++++++++++++--- .../java/src/org/godotengine/godot/Godot.java | 13 +++++++- .../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 + 11 files changed, 76 insertions(+), 6 deletions(-) diff --git a/core/os/input.cpp b/core/os/input.cpp index 6e1e618d9a8..a766ef87fc6 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -60,6 +60,7 @@ void Input::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_joy_name","device"),&Input::get_joy_name); ObjectTypeDB::bind_method(_MD("get_joy_guid","device"),&Input::get_joy_guid); ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer); + ObjectTypeDB::bind_method(_MD("get_magnetometer"),&Input::get_magnetometer); //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 535776f39c0..46edb30aa15 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -75,6 +75,7 @@ public: virtual void warp_mouse_pos(const Vector2& p_to)=0; virtual Vector3 get_accelerometer()=0; + virtual Vector3 get_magnetometer()=0; virtual void action_press(const StringName& p_action)=0; virtual void action_release(const StringName& p_action)=0; diff --git a/main/input_default.cpp b/main/input_default.cpp index c8b8062eee2..5b4ae7f2cb4 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -200,6 +200,12 @@ Vector3 InputDefault::get_accelerometer() { return accelerometer; } +Vector3 InputDefault::get_magnetometer() { + + _THREAD_SAFE_METHOD_ + return magnetometer; +} + void InputDefault::parse_input_event(const InputEvent& p_event) { _THREAD_SAFE_METHOD_ @@ -296,6 +302,14 @@ void InputDefault::set_accelerometer(const Vector3& p_accel) { } +void InputDefault::set_magnetometer(const Vector3& p_magnetometer) { + + _THREAD_SAFE_METHOD_ + + magnetometer=p_magnetometer; + +} + 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 471ae9e692b..8f6a4304367 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -14,6 +14,7 @@ class InputDefault : public Input { Map _joy_axis; Map custom_action_press; Vector3 accelerometer; + Vector3 magnetometer; Vector2 mouse_pos; MainLoop *main_loop; @@ -132,6 +133,7 @@ public: void parse_joystick_mapping(String p_mapping, bool p_update_existing); virtual Vector3 get_accelerometer(); + virtual Vector3 get_magnetometer(); virtual Point2 get_mouse_pos() const; virtual Point2 get_mouse_speed() const; @@ -142,6 +144,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_joy_axis(int p_device,int p_axis,float p_value); void set_main_loop(MainLoop *main_loop); diff --git a/platform/android/godot_android.cpp b/platform/android/godot_android.cpp index f9feb3481f4..edb051575f5 100644 --- a/platform/android/godot_android.cpp +++ b/platform/android/godot_android.cpp @@ -313,6 +313,7 @@ struct engine { ASensorManager* sensorManager; const ASensor* accelerometerSensor; + const ASensor* magnetometerSensor; ASensorEventQueue* sensorEventQueue; bool display_active; @@ -735,16 +736,29 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) { ASensorEventQueue_setEventRate(engine->sensorEventQueue, engine->accelerometerSensor, (1000L/60)*1000); + } + // Also start monitoring the magnetometer. + if (engine->magnetometerSensor != NULL) { + ASensorEventQueue_enableSensor(engine->sensorEventQueue, + engine->magnetometerSensor); + // We'd like to get 60 events per second (in us). + ASensorEventQueue_setEventRate(engine->sensorEventQueue, + engine->magnetometerSensor, (1000L/60)*1000); + } engine->animating = 1; break; case APP_CMD_LOST_FOCUS: - // When our app loses focus, we stop monitoring the accelerometer. + // When our app loses focus, we stop monitoring the sensors. // This is to avoid consuming battery while not being used. if (engine->accelerometerSensor != NULL) { ASensorEventQueue_disableSensor(engine->sensorEventQueue, engine->accelerometerSensor); } + if (engine->magnetometerSensor != NULL) { + ASensorEventQueue_disableSensor(engine->sensorEventQueue, + engine->magnetometerSensor); + } // Also stop animating. engine->animating = 0; engine_draw_frame(engine); @@ -768,10 +782,12 @@ void android_main(struct android_app* state) { FileAccessAndroid::asset_manager=state->activity->assetManager; - // Prepare to monitor accelerometer + // Prepare to monitor sensors engine.sensorManager = ASensorManager_getInstance(); engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, - ASENSOR_TYPE_ACCELEROMETER); + ASENSOR_TYPE_ACCELEROMETER); + engine.magnetometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, + ASENSOR_TYPE_MAGNETIC_FIELD); engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL); @@ -812,16 +828,21 @@ 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) { + if (engine.accelerometerSensor != NULL || engine.magnetometerSensor != NULL) { ASensorEvent event; while (ASensorEventQueue_getEvents(engine.sensorEventQueue, &event, 1) > 0) { if (engine.os) { + if (event.acceleration != NULL) { engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y, event.acceleration.z)); - + } + if (event.magnetic != NULL) { + engine.os->process_magnetometer(Vector3(event.magnetic.x, event.magnetic.y, + event.magnetic.z)); + } } } diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index 1f208f8fb65..c4ba2da7517 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -206,6 +206,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC private SensorManager mSensorManager; private Sensor mAccelerometer; + private Sensor mMagnetometer; public FrameLayout layout; public RelativeLayout adLayout; @@ -374,6 +375,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); + mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); + mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); result_callback = null; @@ -588,6 +591,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC mView.onResume(); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL); GodotLib.focusin(); if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+ Window window = getWindow(); @@ -646,7 +650,14 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC float x = adjustedValues[0]; float y = adjustedValues[1]; float z = adjustedValues[2]; - GodotLib.accelerometer(x,y,z); + + int typeOfSensor = event.sensor.getType(); + if (typeOfSensor == event.sensor.TYPE_ACCELEROMETER) { + GodotLib.accelerometer(x,y,z); + } + if (typeOfSensor == event.sensor.TYPE_MAGNETIC_FIELD) { + GodotLib.magnetometer(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 7c5ac33c858..df181ae1bb5 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java @@ -51,6 +51,7 @@ public class GodotLib { public static native void step(); 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 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 b5beb8fa2c0..1ea7cd7ebba 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -650,6 +650,7 @@ static bool resized_reload=false; static bool quit_request=false; static Size2 new_size; static Vector3 accelerometer; +static Vector3 magnetometer; static HashMap jni_singletons; static jobject godot_io; @@ -1088,6 +1089,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv * env, jo os_android->process_accelerometer(accelerometer); + os_android->process_magnetometer(magnetometer); + if (os_android->main_loop_iterate()==true) { jclass cls = env->FindClass("org/godotengine/godot/Godot"); @@ -1488,6 +1491,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_accelerometer(JNIEnv } +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_magnetometer(JNIEnv * env, jobject obj, jfloat x, jfloat y, jfloat z) { + + input_mutex->lock(); + magnetometer=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 1d65d21251f..f7916efe2c5 100644 --- a/platform/android/java_glue.h +++ b/platform/android/java_glue.h @@ -49,6 +49,7 @@ extern "C" { JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyconnectionchanged(JNIEnv * env, jobject obj, jint p_device, jboolean p_connected, jstring p_name); 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_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 2ef28333bed..4e6dfb2db21 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -609,6 +609,11 @@ void OS_Android::process_accelerometer(const Vector3& p_accelerometer) { input->set_accelerometer(p_accelerometer); } +void OS_Android::process_magnetometer(const Vector3& p_magnetometer) { + + input->set_magnetometer(p_magnetometer); +} + 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 ec1f4119b49..843b3c47886 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -239,6 +239,7 @@ public: void process_accelerometer(const Vector3& p_accelerometer); + void process_magnetometer(const Vector3& p_magnetometer); 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);