Explorar o código

Replacing deprecated UIAccelerometer with Core Motion

BastiaanOlij %!s(int64=8) %!d(string=hai) anos
pai
achega
5c13bae8df

+ 8 - 3
platform/iphone/app_delegate.h

@@ -30,11 +30,16 @@
 #import "gl_view.h"
 #import "view_controller.h"
 
-@interface AppDelegate : NSObject <UIApplicationDelegate, UIAccelerometerDelegate, GLViewDelegate> {
+// Old accelerometer approach deprecated since IOS 7.0
+// Include coremotion for accelerometer, gyroscope and magnetometer access, available since IOS 4.0 but some functionality won't work for anything before IOS 5.0
+#import <CoreMotion/CoreMotion.h>
+
+//@interface AppDelegate : NSObject <UIApplicationDelegate, UIAccelerometerDelegate, GLViewDelegate> {
+@interface AppDelegate : NSObject <UIApplicationDelegate, GLViewDelegate> {
 	//@property (strong, nonatomic) UIWindow *window;
 	ViewController* view_controller;
-	UIAccelerationValue accel[3];
-	UIAccelerationValue last_accel[3];
+//	UIAccelerationValue accel[3];
+//	UIAccelerationValue last_accel[3];
 };
 
 @property (strong, nonatomic) UIWindow *window;

+ 46 - 1
platform/iphone/app_delegate.mm

@@ -84,6 +84,9 @@ extern char** gargv;
 extern int iphone_main(int, int, int, char**);
 extern void iphone_finish();
 
+CMMotionManager *motionManager;
+bool motionInitialised; 
+
 static ViewController* mainViewController = nil;
 + (ViewController*) getViewController
 {
@@ -195,7 +198,22 @@ static int frame_count = 0;
 	default: {
 
 		if (OSIPhone::get_singleton()) {
-			OSIPhone::get_singleton()->update_accelerometer(accel[0], accel[1], accel[2]);
+//			OSIPhone::get_singleton()->update_accelerometer(accel[0], accel[1], accel[2]);
+			if (motionInitialised) {
+				// Just using polling approach for now, we can set this up so it sends data to us in intervals, might be better.
+				// See Apple reference pages for more details:
+				// https://developer.apple.com/reference/coremotion/cmmotionmanager?language=objc
+				CMAcceleration acceleration = motionManager.deviceMotion.userAcceleration;
+				OSIPhone::get_singleton()->update_accelerometer(acceleration.x, acceleration.y, acceleration.z);
+
+				CMMagneticField magnetic = motionManager.deviceMotion.magneticField.field;
+				OSIPhone::get_singleton()->update_magnetometer(magnetic.x, magnetic.y, magnetic.z);
+
+				///@TODO we can access rotationRate as a CMRotationRate variable (processed date) or CMGyroData (raw data), have to see what works best
+				CMRotationRate rotation = motionManager.deviceMotion.rotationRate;
+				OSIPhone::get_singleton()->update_gyroscope(rotation.x, rotation.y, rotation.z);
+			}
+
 			bool quit_request = OSIPhone::get_singleton()->iterate();
 		};
 
@@ -253,11 +271,24 @@ static int frame_count = 0;
 	[window makeKeyAndVisible];
 
 	//Configure and start accelerometer
+/*
+  Old accelerometer approach deprecated since IOS 7.0
+
 	last_accel[0] = 0;
 	last_accel[1] = 0;
 	last_accel[2] = 0;
 	[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
 	[[UIAccelerometer sharedAccelerometer] setDelegate:self];
+*/
+
+	if (!motionInitialised) {
+		motionManager = [[CMMotionManager alloc] init];
+		if (motionManager.deviceMotionAvailable) {
+      motionManager.deviceMotionUpdateInterval = 1.0/70.0;
+      [motionManager startDeviceMotionUpdates];			
+			motionInitialised = YES;
+		};
+	};
 
 	//OSIPhone::screen_width = rect.size.width - rect.origin.x;
 	//OSIPhone::screen_height = rect.size.height - rect.origin.y;
@@ -297,12 +328,23 @@ static int frame_count = 0;
 - (void)applicationWillTerminate:(UIApplication*)application {
 
 	printf("********************* will terminate\n");
+
+	if (motionInitialised) {
+		///@TODO is this the right place to clean this up?
+    [motionManager stopDeviceMotionUpdates];
+    // no free ?
+    motionManager = nil;
+    motionInitialised = NO;	
+	};
+
 	iphone_finish();
 };
 
 - (void)applicationDidEnterBackground:(UIApplication *)application
 {
 	printf("********************* did enter background\n");
+	///@TODO maybe add pause motionManager? and where would we unpause it?
+
 	if (OS::get_singleton()->get_main_loop())
 		OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
 	[view_controller.view stopAnimation];
@@ -340,12 +382,15 @@ static int frame_count = 0;
 	};
 }
 
+/*
+  Depricated since IOS 7.0
 - (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration {
 	//Use a basic low-pass filter to only keep the gravity in the accelerometer values
 	accel[0] = acceleration.x; // * kFilteringFactor + accel[0] * (1.0 - kFilteringFactor);
 	accel[1] = acceleration.y; // * kFilteringFactor + accel[1] * (1.0 - kFilteringFactor);
 	accel[2] = acceleration.z; // * kFilteringFactor + accel[2] * (1.0 - kFilteringFactor);
 }
+*/
 
 - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
 #ifdef MODULE_FACEBOOKSCORER_IOS_ENABLED

+ 3 - 0
platform/iphone/detect.py

@@ -83,6 +83,7 @@ def configure(env):
                               '-framework', 'CoreAudio',
                               '-framework', 'CoreGraphics',
                               '-framework', 'CoreMedia',
+                              '-framework', 'CoreMotion',
                               '-framework', 'Foundation',
                               '-framework', 'Security',
                               '-framework', 'UIKit',
@@ -109,6 +110,7 @@ def configure(env):
                                                 '-framework', 'MediaPlayer',
                                                 '-framework', 'AVFoundation',
                                                 '-framework', 'CoreMedia',
+                                                '-framework', 'CoreMotion',
                               ])
     else:
         env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1',
@@ -126,6 +128,7 @@ def configure(env):
                                                 '-framework', 'MediaPlayer',
                                                 '-framework', 'AVFoundation',
                                                 '-framework', 'CoreMedia',
+                                                '-framework', 'CoreMotion',
                               ])
 
     if env['game_center'] == 'yes':

+ 6 - 0
platform/iphone/os_iphone.cpp

@@ -364,7 +364,13 @@ void OSIPhone::update_accelerometer(float p_x, float p_y, float p_z) {
 	*/
 };
 
+void OSIPhone::update_magnetometer(float p_x, float p_y, float p_z) {
+	input->set_magnetometer(Vector3(p_x, p_y, p_z));
+};
 
+void OSIPhone::update_gyroscope(float p_x, float p_y, float p_z) {
+	input->set_gyroscope(Vector3(p_x, p_y, p_z));
+};
 
 void OSIPhone::delete_main_loop() {
 

+ 2 - 0
platform/iphone/os_iphone.h

@@ -153,6 +153,8 @@ public:
 	int set_base_framebuffer(int p_fb);
 
 	void update_accelerometer(float p_x, float p_y, float p_z);
+	void update_magnetometer(float p_x, float p_y, float p_z);
+	void update_gyroscope(float p_x, float p_y, float p_z);
 
 	static OSIPhone* get_singleton();