mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2025-07-01 23:35:59 +00:00
Implement controller motion sensor support
Axis values probably still need to be swapped around to match other platforms
This commit is contained in:
parent
d48690b320
commit
ef5c3d36d3
@ -35,6 +35,11 @@
|
||||
@property (nonatomic) HapticContext* _Nullable leftTriggerMotor;
|
||||
@property (nonatomic) HapticContext* _Nullable rightTriggerMotor;
|
||||
|
||||
@property (nonatomic) NSTimer* _Nullable accelTimer;
|
||||
@property (nonatomic) GCAcceleration lastAccelSample;
|
||||
@property (nonatomic) NSTimer* _Nullable gyroTimer;
|
||||
@property (nonatomic) GCRotationRate lastGyroSample;
|
||||
|
||||
@property (nonatomic) BOOL reportedArrival;
|
||||
|
||||
@end
|
||||
|
@ -89,7 +89,90 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
|
||||
- (void) setMotionEventState:(uint16_t)controllerNumber motionType:(uint8_t)motionType reportRateHz:(uint16_t)reportRateHz
|
||||
{
|
||||
|
||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
|
||||
if (controller == nil) {
|
||||
// No connected controller for this player
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller.gamepad.motion == nil) {
|
||||
// No motion supported for this controller
|
||||
return;
|
||||
}
|
||||
|
||||
switch (motionType) {
|
||||
case LI_MOTION_TYPE_ACCEL:
|
||||
[controller.accelTimer invalidate];
|
||||
controller.accelTimer = nil;
|
||||
|
||||
if (reportRateHz && controller.gamepad.motion.hasGravityAndUserAcceleration) {
|
||||
// Reset the last motion sample
|
||||
GCAcceleration emptyAccelSample = {};
|
||||
controller.lastAccelSample = emptyAccelSample;
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
controller.accelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / reportRateHz repeats:YES block:^(NSTimer *timer) {
|
||||
// Don't send duplicate samples
|
||||
GCAcceleration lastAccelSample = controller.lastAccelSample;
|
||||
GCAcceleration accelSample = controller.gamepad.motion.acceleration;
|
||||
if (memcmp(&accelSample, &lastAccelSample, sizeof(accelSample)) == 0) {
|
||||
return;
|
||||
}
|
||||
controller.lastAccelSample = accelSample;
|
||||
|
||||
// Convert g to m/s^2
|
||||
LiSendControllerMotionEvent((uint8_t)controllerNumber,
|
||||
LI_MOTION_TYPE_ACCEL,
|
||||
accelSample.x * 9.80665f,
|
||||
accelSample.y * 9.80665f,
|
||||
accelSample.z * 9.80665f);
|
||||
}];
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case LI_MOTION_TYPE_GYRO:
|
||||
[controller.gyroTimer invalidate];
|
||||
controller.gyroTimer = nil;
|
||||
|
||||
if (reportRateHz && controller.gamepad.motion.hasRotationRate) {
|
||||
// Reset the last motion sample
|
||||
GCRotationRate emptyGyroSample = {};
|
||||
controller.lastGyroSample = emptyGyroSample;
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
controller.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / reportRateHz repeats:YES block:^(NSTimer *timer) {
|
||||
// Don't send duplicate samples
|
||||
GCRotationRate lastGyroSample = controller.lastGyroSample;
|
||||
GCRotationRate gyroSample = controller.gamepad.motion.rotationRate;
|
||||
if (memcmp(&gyroSample, &lastGyroSample, sizeof(gyroSample)) == 0) {
|
||||
return;
|
||||
}
|
||||
controller.lastGyroSample = gyroSample;
|
||||
|
||||
// Convert rad/s to deg/s
|
||||
LiSendControllerMotionEvent((uint8_t)controllerNumber,
|
||||
LI_MOTION_TYPE_GYRO,
|
||||
gyroSample.x * 57.2957795f,
|
||||
gyroSample.y * 57.2957795f,
|
||||
gyroSample.z * 57.2957795f);
|
||||
}];
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the motion sensor state if they require manual activation
|
||||
if (controller.gamepad.motion.sensorsRequireManualActivation) {
|
||||
if (controller.gyroTimer || controller.accelTimer) {
|
||||
controller.gamepad.motion.sensorsActive = YES;
|
||||
}
|
||||
else {
|
||||
controller.gamepad.motion.sensorsActive = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y
|
||||
@ -305,6 +388,20 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
[controller.rightTriggerMotor cleanup];
|
||||
}
|
||||
|
||||
-(void) cleanupControllerMotion:(Controller*) controller
|
||||
{
|
||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||
// Stop sensor sampling timers
|
||||
[controller.gyroTimer invalidate];
|
||||
[controller.accelTimer invalidate];
|
||||
|
||||
// Disable motion sensors if they require manual activation
|
||||
if (controller.gamepad && controller.gamepad.motion && controller.gamepad.motion.sensorsRequireManualActivation) {
|
||||
controller.gamepad.motion.sensorsActive = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) reportControllerArrival:(GCController*) controller
|
||||
{
|
||||
if (controller == nil || controller.extendedGamepad == nil) {
|
||||
@ -418,6 +515,16 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect supported motion sensors
|
||||
if (controller.motion) {
|
||||
if (controller.motion.hasGravityAndUserAcceleration) {
|
||||
capabilities |= LI_CCAP_ACCEL;
|
||||
}
|
||||
if (controller.motion.hasRotationRate) {
|
||||
capabilities |= LI_CCAP_GYRO;
|
||||
}
|
||||
}
|
||||
|
||||
LiSendControllerArrivalEvent(controller.playerIndex, [self getActiveGamepadMask], type, supportedButtonFlags, capabilities);
|
||||
}
|
||||
}
|
||||
@ -987,6 +1094,9 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
// Stop haptics on this controller
|
||||
[self cleanupControllerHaptics:limeController];
|
||||
|
||||
// Stop motion reports on this controller
|
||||
[self cleanupControllerMotion:limeController];
|
||||
|
||||
limeController.gamepad = nil;
|
||||
|
||||
// Inform the server of the updated active gamepads before removing this controller
|
||||
@ -1066,6 +1176,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
|
||||
for (Controller* controller in [_controllers allValues]) {
|
||||
[self cleanupControllerHaptics:controller];
|
||||
[self cleanupControllerMotion:controller];
|
||||
}
|
||||
[_controllers removeAllObjects];
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user