Browse Source

Merge pull request #4845 from vnen/pr-magnetometer

Add magnetometer sensor support for Android
Rémi Verschelde 9 years ago
parent
commit
96bdab6edf

+ 1 - 0
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_name","device"),&Input::get_joy_name);
 	ObjectTypeDB::bind_method(_MD("get_joy_guid","device"),&Input::get_joy_guid);
 	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_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_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_speed"),&Input::get_mouse_speed);
 	ObjectTypeDB::bind_method(_MD("get_mouse_button_mask"),&Input::get_mouse_button_mask);
 	ObjectTypeDB::bind_method(_MD("get_mouse_button_mask"),&Input::get_mouse_button_mask);

+ 1 - 0
core/os/input.h

@@ -75,6 +75,7 @@ public:
 	virtual void warp_mouse_pos(const Vector2& p_to)=0;
 	virtual void warp_mouse_pos(const Vector2& p_to)=0;
 
 
 	virtual Vector3 get_accelerometer()=0;
 	virtual Vector3 get_accelerometer()=0;
+	virtual Vector3 get_magnetometer()=0;
 
 
 	virtual void action_press(const StringName& p_action)=0;
 	virtual void action_press(const StringName& p_action)=0;
 	virtual void action_release(const StringName& p_action)=0;
 	virtual void action_release(const StringName& p_action)=0;

+ 7 - 0
doc/base/classes.xml

@@ -15387,6 +15387,13 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
 			If the device has an accelerometer, this will return the movement.
 			If the device has an accelerometer, this will return the movement.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_magnetometer">
+			<return type="Vector3">
+			</return>
+			<description>
+			If the device has a magnetometer, this will return the magnetic field strength in micro-Tesla for all axes.
+			</description>
+		</method>
 		<method name="get_mouse_speed" qualifiers="const">
 		<method name="get_mouse_speed" qualifiers="const">
 			<return type="Vector2">
 			<return type="Vector2">
 			</return>
 			</return>

+ 14 - 0
main/input_default.cpp

@@ -200,6 +200,12 @@ Vector3 InputDefault::get_accelerometer() {
 	return accelerometer;
 	return accelerometer;
 }
 }
 
 
+Vector3 InputDefault::get_magnetometer() {
+
+	_THREAD_SAFE_METHOD_
+	return magnetometer;
+}
+
 void InputDefault::parse_input_event(const InputEvent& p_event) {
 void InputDefault::parse_input_event(const InputEvent& p_event) {
 
 
 	_THREAD_SAFE_METHOD_
 	_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) {
 void InputDefault::set_main_loop(MainLoop *p_main_loop) {
 	main_loop=p_main_loop;
 	main_loop=p_main_loop;
 
 

+ 3 - 0
main/input_default.h

@@ -14,6 +14,7 @@ class InputDefault : public Input {
 	Map<int,float> _joy_axis;
 	Map<int,float> _joy_axis;
 	Map<StringName,int> custom_action_press;
 	Map<StringName,int> custom_action_press;
 	Vector3 accelerometer;
 	Vector3 accelerometer;
+	Vector3 magnetometer;
 	Vector2 mouse_pos;
 	Vector2 mouse_pos;
 	MainLoop *main_loop;
 	MainLoop *main_loop;
 
 
@@ -132,6 +133,7 @@ public:
 	void parse_joystick_mapping(String p_mapping, bool p_update_existing);
 	void parse_joystick_mapping(String p_mapping, bool p_update_existing);
 
 
 	virtual Vector3 get_accelerometer();
 	virtual Vector3 get_accelerometer();
+	virtual Vector3 get_magnetometer();
 
 
 	virtual Point2 get_mouse_pos() const;
 	virtual Point2 get_mouse_pos() const;
 	virtual Point2 get_mouse_speed() const;
 	virtual Point2 get_mouse_speed() const;
@@ -142,6 +144,7 @@ public:
 
 
 	void parse_input_event(const InputEvent& p_event);
 	void parse_input_event(const InputEvent& p_event);
 	void set_accelerometer(const Vector3& p_accel);
 	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_joy_axis(int p_device,int p_axis,float p_value);
 
 
 	void set_main_loop(MainLoop *main_loop);
 	void set_main_loop(MainLoop *main_loop);

+ 26 - 5
platform/android/godot_android.cpp

@@ -313,6 +313,7 @@ struct engine {
 
 
     ASensorManager* sensorManager;
     ASensorManager* sensorManager;
     const ASensor* accelerometerSensor;
     const ASensor* accelerometerSensor;
+    const ASensor* magnetometerSensor;
     ASensorEventQueue* sensorEventQueue;
     ASensorEventQueue* sensorEventQueue;
 
 
     bool display_active;
     bool display_active;
@@ -735,16 +736,29 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
 		ASensorEventQueue_setEventRate(engine->sensorEventQueue,
 		ASensorEventQueue_setEventRate(engine->sensorEventQueue,
 			engine->accelerometerSensor, (1000L/60)*1000);
 			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;
 	    engine->animating = 1;
 	    break;
 	    break;
 	case APP_CMD_LOST_FOCUS:
 	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.
 	    // This is to avoid consuming battery while not being used.
 	    if (engine->accelerometerSensor != NULL) {
 	    if (engine->accelerometerSensor != NULL) {
 		ASensorEventQueue_disableSensor(engine->sensorEventQueue,
 		ASensorEventQueue_disableSensor(engine->sensorEventQueue,
 			engine->accelerometerSensor);
 			engine->accelerometerSensor);
 	    }
 	    }
+	    if (engine->magnetometerSensor != NULL) {
+		ASensorEventQueue_disableSensor(engine->sensorEventQueue,
+			engine->magnetometerSensor);
+	    }
 	    // Also stop animating.
 	    // Also stop animating.
 	    engine->animating = 0;
 	    engine->animating = 0;
 	    engine_draw_frame(engine);
 	    engine_draw_frame(engine);
@@ -768,10 +782,12 @@ void android_main(struct android_app* state) {
 
 
      FileAccessAndroid::asset_manager=state->activity->assetManager;
      FileAccessAndroid::asset_manager=state->activity->assetManager;
 
 
-     // Prepare to monitor accelerometer
+     // Prepare to monitor sensors
      engine.sensorManager = ASensorManager_getInstance();
      engine.sensorManager = ASensorManager_getInstance();
      engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
      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,
      engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
 	     state->looper, LOOPER_ID_USER, NULL, NULL);
 	     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.
 	     // If a sensor has data, process it now.
 	    // LOGI("events\n");
 	    // LOGI("events\n");
 	     if (ident == LOOPER_ID_USER) {
 	     if (ident == LOOPER_ID_USER) {
-		 if (engine.accelerometerSensor != NULL) {
+		 if (engine.accelerometerSensor != NULL || engine.magnetometerSensor != NULL) {
 		     ASensorEvent event;
 		     ASensorEvent event;
 		     while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
 		     while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
 			     &event, 1) > 0) {
 			     &event, 1) > 0) {
 
 
 
 
 			     if (engine.os) {
 			     if (engine.os) {
+				  if (event.acceleration != NULL) {
 				     engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
 				     engine.os->process_accelerometer(Vector3(event.acceleration.x, event.acceleration.y,
 									      event.acceleration.z));
 									      event.acceleration.z));
-
+				  }
+				  if (event.magnetic != NULL) {
+				     engine.os->process_magnetometer(Vector3(event.magnetic.x, event.magnetic.y,
+									      event.magnetic.z));
+				  }
 			     }
 			     }
 
 
 		     }
 		     }

+ 12 - 1
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 SensorManager mSensorManager;
 	private Sensor mAccelerometer;
 	private Sensor mAccelerometer;
+	private Sensor mMagnetometer;
 
 
 	public FrameLayout layout;
 	public FrameLayout layout;
 	public RelativeLayout adLayout;
 	public RelativeLayout adLayout;
@@ -374,6 +375,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
 		mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
 		mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
 		mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
 		mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
 		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
 		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;
 		result_callback = null;
 
 
@@ -588,6 +591,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
 
 
 		mView.onResume();
 		mView.onResume();
 		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
 		mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
+		mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
 		GodotLib.focusin();
 		GodotLib.focusin();
 		if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
 		if(use_immersive && Build.VERSION.SDK_INT >= 19.0){ // check if the application runs on an android 4.4+
 			Window window = getWindow();
 			Window window = getWindow();
@@ -646,7 +650,14 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
 		float x = adjustedValues[0];
 		float x = adjustedValues[0];
 		float y = adjustedValues[1];
 		float y = adjustedValues[1];
 		float z = adjustedValues[2];
 		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) {
 	@Override public final void onAccuracyChanged(Sensor sensor, int accuracy) {

+ 1 - 0
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 step();
      public static native void touch(int what,int pointer,int howmany, int[] arr);
      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 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 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 joybutton(int p_device, int p_but, boolean p_pressed);
 	 public static native void joyaxis(int p_device, int p_axis, float p_value);
 	 public static native void joyaxis(int p_device, int p_axis, float p_value);

+ 11 - 0
platform/android/java_glue.cpp

@@ -650,6 +650,7 @@ static bool resized_reload=false;
 static bool quit_request=false;
 static bool quit_request=false;
 static Size2 new_size;
 static Size2 new_size;
 static Vector3 accelerometer;
 static Vector3 accelerometer;
+static Vector3 magnetometer;
 static HashMap<String,JNISingleton*> jni_singletons;
 static HashMap<String,JNISingleton*> jni_singletons;
 static jobject godot_io;
 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_accelerometer(accelerometer);
 
 
+	os_android->process_magnetometer(magnetometer);
+
 	if (os_android->main_loop_iterate()==true) {
 	if (os_android->main_loop_iterate()==true) {
 
 
 		jclass cls = env->FindClass("org/godotengine/godot/Godot");
 		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){
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusin(JNIEnv * env, jobject obj){
 
 
 	if (!suspend_mutex)
 	if (!suspend_mutex)

+ 1 - 0
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_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_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_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_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_focusout(JNIEnv * env, jobject obj);
     JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);
     JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_singleton(JNIEnv * env, jobject obj, jstring name,jobject p_object);

+ 5 - 0
platform/android/os_android.cpp

@@ -609,6 +609,11 @@ void OS_Android::process_accelerometer(const Vector3& p_accelerometer) {
 	input->set_accelerometer(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 {
 bool OS_Android::has_touchscreen_ui_hint() const {
 
 
 	return true;
 	return true;

+ 1 - 0
platform/android/os_android.h

@@ -239,6 +239,7 @@ public:
 
 
 
 
 	void process_accelerometer(const Vector3& p_accelerometer);
 	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<TouchPos>& p_points);
 	void process_touch(int p_what,int p_pointer, const Vector<TouchPos>& p_points);
 	void process_joy_event(JoystickEvent p_event);
 	void process_joy_event(JoystickEvent p_event);
 	void process_event(InputEvent p_event);
 	void process_event(InputEvent p_event);