iOS: Implement accelerometer support

This commit is contained in:
Henrik Rydgård 2024-06-04 11:51:09 +02:00
parent 328acdcd0a
commit 7b3f0aeab2
5 changed files with 71 additions and 2 deletions

View File

@ -1325,7 +1325,7 @@ elseif(IOS AND NOT LIBRETRO)
Common/Battery/AppleBatteryClient.m
)
set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreText -framework CoreVideo -framework CoreMedia -framework CoreServices -framework Metal -framework IOSurface" )
set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework CoreMotion -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreText -framework CoreVideo -framework CoreMedia -framework CoreServices -framework Metal -framework IOSurface" )
if(EXISTS "${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks/GameController.framework")
set(nativeExtraLibs ${nativeExtraLibs} "-weak_framework GameController")
endif()

View File

@ -3,6 +3,8 @@
#include <map>
#import <GameController/GameController.h>
#import <CoreMotion/CoreMotion.h>
#include "iCade/iCadeState.h"
#include "Common/Input/InputState.h"
@ -38,3 +40,5 @@ private:
double lastSelectPress = 0.0f;
double lastStartPress = 0.0f;
};
void ProcessAccelerometerData(CMAccelerometerData *accData);

View File

@ -358,3 +358,11 @@ void ICadeTracker::ButtonUp(iCadeState button) {
NativeKey(key);
}
}
void ProcessAccelerometerData(CMAccelerometerData *accData) {
CMAcceleration acc = accData.acceleration;
// INFO_LOG(SYSTEM, "%f %f %f", acc.x, acc.y, acc.z);
// Might need to change these for portrait or inverse landscape
NativeAccelerometer(-acc.x, -acc.y, -acc.z);
}

View File

@ -109,6 +109,8 @@ id<PPSSPPViewController> sharedViewController;
//@property (nonatomic) iCadeReaderView* iCadeView;
@property (nonatomic) GCController *gameController __attribute__((weak_import));
@property (strong, nonatomic) CMMotionManager *motionManager;
@property (strong, nonatomic) NSOperationQueue *accelerometerQueue;
@end
@ -124,6 +126,9 @@ id<PPSSPPViewController> sharedViewController;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidConnect:) name:GCControllerDidConnectNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidDisconnect:) name:GCControllerDidDisconnectNotification object:nil];
}
self.accelerometerQueue = [[NSOperationQueue alloc] init];
self.accelerometerQueue.name = @"AccelerometerQueue";
self.accelerometerQueue.maxConcurrentOperationCount = 1;
return self;
}
@ -269,7 +274,9 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) {
[mBackGestureRecognizer setEdges:UIRectEdgeLeft];
[[self view] addGestureRecognizer:mBackGestureRecognizer];
INFO_LOG(G3D, "Done with viewDidLoad. Next up, OpenGL");
// Initialize the motion manager for accelerometer control.
self.motionManager = [[CMMotionManager alloc] init];
INFO_LOG(G3D, "Done with viewDidLoad.");
}
- (void)handleSwipeFrom:(UIScreenEdgePanGestureRecognizer *)recognizer
@ -291,6 +298,21 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) {
- (void)didBecomeActive {
INFO_LOG(SYSTEM, "didBecomeActive begin");
if (self.motionManager.accelerometerAvailable) {
self.motionManager.accelerometerUpdateInterval = 1.0 / 60.0;
INFO_LOG(G3D, "Starting accelerometer updates.");
[self.motionManager startAccelerometerUpdatesToQueue:self.accelerometerQueue
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
if (error) {
NSLog(@"Accelerometer error: %@", error);
return;
}
ProcessAccelerometerData(accelerometerData);
}];
} else {
INFO_LOG(G3D, "No accelerometer available, not starting updates.");
}
[self runGLRenderLoop];
INFO_LOG(SYSTEM, "didBecomeActive end");
}
@ -298,6 +320,12 @@ void GLRenderLoop(IOSGLESContext *graphicsContext) {
- (void)willResignActive {
INFO_LOG(SYSTEM, "willResignActive begin");
[self requestExitGLRenderLoop];
// Stop accelerometer updates
if (self.motionManager.accelerometerActive) {
INFO_LOG(G3D, "Stopping accelerometer updates");
[self.motionManager stopAccelerometerUpdates];
}
INFO_LOG(SYSTEM, "willResignActive end");
}

View File

@ -213,6 +213,8 @@ static std::thread g_renderLoopThread;
}
@property (nonatomic) GCController *gameController __attribute__((weak_import));
@property (strong, nonatomic) CMMotionManager *motionManager;
@property (strong, nonatomic) NSOperationQueue *accelerometerQueue;
@end // @interface
@ -228,6 +230,9 @@ static std::thread g_renderLoopThread;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidConnect:) name:GCControllerDidConnectNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidDisconnect:) name:GCControllerDidDisconnectNotification object:nil];
}
self.accelerometerQueue = [[NSOperationQueue alloc] init];
self.accelerometerQueue.name = @"AccelerometerQueue";
self.accelerometerQueue.maxConcurrentOperationCount = 1;
return self;
}
@ -338,7 +343,21 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
// These two are forwarded from the appDelegate
- (void)didBecomeActive {
INFO_LOG(G3D, "didBecomeActive GL");
if (self.motionManager.accelerometerAvailable) {
self.motionManager.accelerometerUpdateInterval = 1.0 / 60.0;
INFO_LOG(G3D, "Starting accelerometer updates.");
[self.motionManager startAccelerometerUpdatesToQueue:self.accelerometerQueue
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
if (error) {
NSLog(@"Accelerometer error: %@", error);
return;
}
ProcessAccelerometerData(accelerometerData);
}];
} else {
INFO_LOG(G3D, "No accelerometer available, not starting updates.");
}
// Spin up the emu thread. It will in turn spin up the Vulkan render thread
// on its own.
[self runVulkanRenderLoop];
@ -347,6 +366,12 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
- (void)willResignActive {
INFO_LOG(G3D, "willResignActive GL");
[self requestExitVulkanRenderLoop];
// Stop accelerometer updates
if (self.motionManager.accelerometerActive) {
INFO_LOG(G3D, "Stopping accelerometer updates");
[self.motionManager stopAccelerometerUpdates];
}
}
- (void)shutdown
@ -419,6 +444,9 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
UIScreenEdgePanGestureRecognizer *mBackGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:) ];
[mBackGestureRecognizer setEdges:UIRectEdgeLeft];
[[self view] addGestureRecognizer:mBackGestureRecognizer];
// Initialize the motion manager for accelerometer control.
self.motionManager = [[CMMotionManager alloc] init];
}
// Allow device rotation to resize the swapchain
@ -444,6 +472,7 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear: animated];
INFO_LOG(G3D, "viewWillDisappear");
}
- (void)viewDidAppear:(BOOL)animated {