switch between built-in & controller gyros

This commit is contained in:
TrueZhuanjia
2025-07-06 21:12:57 +08:00
parent 3cbdba78d6
commit 578ad81b8a
7 changed files with 460 additions and 249 deletions
+7 -7
View File
@@ -49,7 +49,7 @@
988FCD41293B091B003050E2 /* KeyboardInputField.m in Sources */ = {isa = PBXBuildFile; fileRef = 988FCD40293B091B003050E2 /* KeyboardInputField.m */; };
9890CF6B203B7EE1006C4B06 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9890CF6A203B7EE1006C4B06 /* libxml2.tbd */; };
9896219723D15C7000211983 /* X1Kit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9896219623D15C7000211983 /* X1Kit.swift */; };
9897B6A1221260EF00966419 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 9897B6A0221260EF00966419 /* Controller.m */; };
9897B6A1221260EF00966419 /* VoidController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9897B6A0221260EF00966419 /* VoidController.m */; };
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98AB2E841CAD46840089BB98 /* libmoonlight-common.a */; };
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; };
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */; };
@@ -208,8 +208,8 @@
988FCD40293B091B003050E2 /* KeyboardInputField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeyboardInputField.m; sourceTree = "<group>"; };
9890CF6A203B7EE1006C4B06 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
9896219623D15C7000211983 /* X1Kit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = X1Kit.swift; path = X1Kit/Sources/X1Kit/X1Kit.swift; sourceTree = "<group>"; };
9897B6A0221260EF00966419 /* Controller.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
9897B6A32212610800966419 /* Controller.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
9897B6A0221260EF00966419 /* VoidController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VoidController.m; sourceTree = "<group>"; };
9897B6A32212610800966419 /* VoidController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VoidController.h; sourceTree = "<group>"; };
98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "moonlight-common/moonlight-common.xcodeproj"; sourceTree = "<group>"; };
98B9CE6C27B2144B00B473C4 /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS15.2.sdk/System/Library/Frameworks/AVKit.framework; sourceTree = DEVELOPER_DIR; };
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryHost.h; path = Database/TemporaryHost.h; sourceTree = "<group>"; };
@@ -559,8 +559,8 @@
FB4678EC1A50C40900377732 /* OnScreenControls.m */,
FB1A674B2131E65900507771 /* KeyboardSupport.h */,
FB1A674C2131E65900507771 /* KeyboardSupport.m */,
9897B6A0221260EF00966419 /* Controller.m */,
9897B6A32212610800966419 /* Controller.h */,
9897B6A0221260EF00966419 /* VoidController.m */,
9897B6A32212610800966419 /* VoidController.h */,
9827E7A22514366900F25707 /* HapticContext.m */,
9827E7A7251436EA00F25707 /* HapticContext.h */,
840751B12BF49B5A0096B657 /* CustomTapGestureRecognizer.h */,
@@ -874,7 +874,7 @@
847D2FDB2DDA015F00937A62 /* MenuSectionView.m in Sources */,
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
189AD29A2DE7446000E24B88 /* HostCollectionViewController.m in Sources */,
9897B6A1221260EF00966419 /* Controller.m in Sources */,
9897B6A1221260EF00966419 /* VoidController.m in Sources */,
84351B112C29ACCB00A77989 /* OSCProfilesManager.m in Sources */,
FB89462919F646E200339C8A /* mkcert.c in Sources */,
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
@@ -1135,7 +1135,7 @@
"$(PROJECT_DIR)/libs/FFmpeg/lib/iOS-Sim",
);
MARKETING_VERSION = 0.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.voidlink.tf.debug7.iOS;
PRODUCT_BUNDLE_IDENTIFIER = com.voidlink.tf.debug10.iOS;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
+12 -12
View File
@@ -7,7 +7,7 @@
//
#import "StreamConfiguration.h"
#import "Controller.h"
#import "VoidController.h"
@class OnScreenControls;
@@ -16,7 +16,7 @@
- (void)gamepadPresenceChanged;
- (void)mousePresenceChanged;
- (void)streamExitRequested;
- (void)automaticallyStartSendingBuiltinGyroEvents;
- (void)automaticallyStartSendingGyroEvents;
@end
@@ -27,20 +27,20 @@
-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc;
-(void) cleanup;
-(Controller*) getOscController;
-(VoidController*) getOscController;
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y;
-(void) updateRightStick:(Controller*)controller x:(short)x y:(short)y;
-(void) updateLeftStick:(VoidController*)controller x:(short)x y:(short)y;
-(void) updateRightStick:(VoidController*)controller x:(short)x y:(short)y;
-(void) updateLeftTrigger:(Controller*)controller left:(unsigned char)left;
-(void) updateRightTrigger:(Controller*)controller right:(unsigned char)right;
-(void) updateTriggers:(Controller*)controller left:(unsigned char)left right:(unsigned char)right;
-(void) updateLeftTrigger:(VoidController*)controller left:(unsigned char)left;
-(void) updateRightTrigger:(VoidController*)controller right:(unsigned char)right;
-(void) updateTriggers:(VoidController*)controller left:(unsigned char)left right:(unsigned char)right;
-(void) updateButtonFlags:(Controller*)controller flags:(int)flags;
-(void) setButtonFlag:(Controller*)controller flags:(int)flags;
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags;
-(void) updateButtonFlags:(VoidController*)controller flags:(int)flags;
-(void) setButtonFlag:(VoidController*)controller flags:(int)flags;
-(void) clearButtonFlag:(VoidController*)controller flags:(int)flags;
-(void) updateFinished:(Controller*)controller;
-(void) updateFinished:(VoidController*)controller;
-(void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor;
-(void) rumbleTriggers:(uint16_t)controllerNumber leftTrigger:(uint16_t)leftTrigger rightTrigger:(uint16_t)rightTrigger;
+364 -160
View File
@@ -10,7 +10,7 @@
//
#import "ControllerSupport.h"
#import "Controller.h"
#import "VoidController.h"
#import "OnScreenControls.h"
@@ -34,9 +34,9 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
id _keyboardDisconnectObserver;
NSLock *_controllerStreamLock;
NSMutableDictionary *_controllers;
NSMutableDictionary *_voidControllers;
id<ControllerSupportDelegate> _delegate;
StreamConfiguration* streamConfig;
StreamConfiguration* _streamConfig;
float accumulatedDeltaX;
float accumulatedDeltaY;
@@ -44,7 +44,8 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
float accumulatedScrollY;
OnScreenControls *_osc;
Controller *_oscController;
VoidController *_oscController;
NSMutableSet* _activeGCControllers;
#define EMULATING_SELECT 0x1
#define EMULATING_SPECIAL 0x2
@@ -66,7 +67,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
-(void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor
{
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
VoidController* controller = [_voidControllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
if (controller == nil && controllerNumber == 0 && _oscEnabled) {
// TODO: Rumble emulation for OSC
}
@@ -81,7 +82,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
-(void) rumbleTriggers:(uint16_t)controllerNumber leftTrigger:(uint16_t)leftTrigger rightTrigger:(uint16_t)rightTrigger
{
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
VoidController* controller = [_voidControllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
if (controller == nil && controllerNumber == 0 && _oscEnabled) {
// TODO: Trigger rumble emulation for OSC
}
@@ -93,62 +94,68 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
[controller.rightTriggerMotor setMotorAmplitude:rightTrigger];
}
-(void)updateTimerStateForController:(Controller* )controller{
-(void)updateTimerStateForController:(VoidController* )voidController{
if (@available(iOS 14.0, tvOS 14.0, *)) {
NSLog(@"controller obj timer update");
if(_gyroMode == GyroModeOff){
[self stopTimerForController:controller];
[self stopTimerForController:voidController];
return;
}
for(NSNumber* motionTypeObj in controller.motionTypes){
if(voidController.gamepad.motion.hasAttitudeAndRotationRate) [voidController.motionTypes addObject:@(LI_MOTION_TYPE_ACCEL)];
if(voidController.gamepad.motion.hasRotationRate) [voidController.motionTypes addObject:@(LI_MOTION_TYPE_GYRO)];
NSLog(@"voidCon reportHz: %d", voidController.reportRateHz);
for(NSNumber* motionTypeObj in voidController.motionTypes){
uint8_t motionType = motionTypeObj.intValue;
NSLog(@"controller obj controllerNumber %d", voidController.controllerNumber);
if(_gyroMode != AlwaysController && controller.controllerNumber < 2){
#if !TARGET_OS_TV //tvOS has no device motion
if(controller.gamepad.motion == nil || _gyroMode == AlwaysDevice){
//Player has no controller *or* no motion for controller 1 *or* wants to override controller 1 motion with device motion
if(!controller.motionManager) {
controller.motionManager = [[CMMotionManager alloc] init];
}
if(_gyroMode != AlwaysController || voidController == _oscController){
NSLog(@"device gyro mode, motionType: %d", motionType);
#if !TARGET_OS_TV //tvOS has no device motion
if(voidController == _oscController){
//Player has no controller *or* no motion for controller 1 *or* wants to override controller 1 motion with device motion
if(!voidController.motionManager) {
voidController.motionManager = [[CMMotionManager alloc] init];
}
NSLog(@"device gyro mode 666, motionType: %d", motionType);
switch (motionType) {
case LI_MOTION_TYPE_ACCEL:
[controller.accelTimer invalidate];
controller.accelTimer = nil;
[voidController.accelTimer invalidate];
voidController.accelTimer = nil;
// Reset the last motion sample
CMAcceleration emptyDeviceAccelSample = {};
controller.lastDeviceAccelSample = emptyDeviceAccelSample;
voidController.lastDeviceAccelSample = emptyDeviceAccelSample;
{dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"setup device built-in gyro accelTimer");
controller.accelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / controller.reportRateHz repeats:YES block:^(NSTimer *timer) {
voidController.hasAccelerometer = YES;
voidController.accelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / voidController.reportRateHz repeats:YES block:^(NSTimer *timer) {
// Don't send duplicate samples
CMAcceleration lastDeviceAccelSample = controller.lastDeviceAccelSample;
CMAcceleration deviceAccelSample = controller.motionManager.deviceMotion.userAcceleration;
CMAcceleration lastDeviceAccelSample = voidController.lastDeviceAccelSample;
CMAcceleration deviceAccelSample = voidController.motionManager.deviceMotion.userAcceleration;
//userAcceleration does not contain gravity, add gravity to x, y and z values:
deviceAccelSample.x += controller.motionManager.deviceMotion.gravity.x * self->_gyroSensitivity;
deviceAccelSample.y += controller.motionManager.deviceMotion.gravity.y * self->_gyroSensitivity;
deviceAccelSample.z += controller.motionManager.deviceMotion.gravity.z * self->_gyroSensitivity;
deviceAccelSample.x += voidController.motionManager.deviceMotion.gravity.x * self->_gyroSensitivity;
deviceAccelSample.y += voidController.motionManager.deviceMotion.gravity.y * self->_gyroSensitivity;
deviceAccelSample.z += voidController.motionManager.deviceMotion.gravity.z * self->_gyroSensitivity;
if (memcmp(&deviceAccelSample, &lastDeviceAccelSample, sizeof(deviceAccelSample)) == 0) {
return;
}
controller.lastDeviceAccelSample = deviceAccelSample;
voidController.lastDeviceAccelSample = deviceAccelSample;
// Convert g to m/s^2
if(UIApplication.sharedApplication.windows.firstObject.windowScene.interfaceOrientation == 4){ //check for landscape left or landscape right
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
LI_MOTION_TYPE_ACCEL,
deviceAccelSample.y * -9.80665f * self->_gyroSensitivity,
deviceAccelSample.z * -9.80665f * self->_gyroSensitivity,
deviceAccelSample.x * -9.80665f * self->_gyroSensitivity);
}
else{
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
LI_MOTION_TYPE_ACCEL,
deviceAccelSample.y * +9.80665f * self->_gyroSensitivity,
deviceAccelSample.z * -9.80665f * self->_gyroSensitivity,
@@ -158,35 +165,37 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
});}
break;
case LI_MOTION_TYPE_GYRO:
[controller.gyroTimer invalidate];
controller.gyroTimer = nil;
[voidController.gyroTimer invalidate];
voidController.gyroTimer = nil;
// Reset the last motion sample
CMRotationRate emptyDeviceGyroSample = {};
controller.lastDeviceGyroSample = emptyDeviceGyroSample;
[controller.motionManager startDeviceMotionUpdates];
voidController.lastDeviceGyroSample = emptyDeviceGyroSample;
[voidController.motionManager startDeviceMotionUpdates];
NSLog(@"setup device built-in gyro gyroTimer");
controller.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / controller.reportRateHz repeats:YES block:^(NSTimer *timer) {
voidController.hasGyroscope = YES;
voidController.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / voidController.reportRateHz repeats:YES block:^(NSTimer *timer) {
// Don't send duplicate samples
CMRotationRate lastDeviceGyroSample = controller.lastDeviceGyroSample;
CMRotationRate deviceGyroSample = controller.motionManager.deviceMotion.rotationRate;
CMRotationRate lastDeviceGyroSample = voidController.lastDeviceGyroSample;
CMRotationRate deviceGyroSample = voidController.motionManager.deviceMotion.rotationRate;
if (memcmp(&deviceGyroSample, &lastDeviceGyroSample, sizeof(deviceGyroSample)) == 0) {
return;
}
controller.lastDeviceGyroSample = deviceGyroSample;
voidController.lastDeviceGyroSample = deviceGyroSample;
// Convert rad/s to deg/s
NSLog(@"sending built-in gyro data, accelSample data 00: %f, playerIndex: %d",deviceGyroSample.x, voidController.playerIndex);
if(UIApplication.sharedApplication.windows.firstObject.windowScene.interfaceOrientation == 4){//check for landscape left or landscape right
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
LI_MOTION_TYPE_GYRO,
deviceGyroSample.y * 57.2957795f * self->_gyroSensitivity,
deviceGyroSample.z * 57.2957795f * self->_gyroSensitivity,
deviceGyroSample.x * 57.2957795f * self->_gyroSensitivity);
}
else{
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
LI_MOTION_TYPE_GYRO,
deviceGyroSample.y * -57.2957795f * self->_gyroSensitivity,
deviceGyroSample.z * 57.2957795f * self->_gyroSensitivity,
@@ -199,98 +208,140 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
#endif
else{
NSLog(@"controller obj timer update: controller timer ");
switch (motionType) {
case LI_MOTION_TYPE_ACCEL:
[controller.accelTimer invalidate];
controller.accelTimer = nil;
NSLog(@"LI_MOTION_TYPE_ACCEL: setup controller gyro accelTimer");
[voidController.accelTimer invalidate];
voidController.accelTimer = nil;
if (controller.reportRateHz && controller.gamepad.motion.hasGravityAndUserAcceleration) {
if (voidController.reportRateHz && voidController.gamepad.motion.hasGravityAndUserAcceleration) {
// Reset the last motion sample
GCAcceleration emptyAccelSample = {};
controller.lastAccelSample = emptyAccelSample;
voidController.lastAccelSample = emptyAccelSample;
NSLog(@"setup controller gyro accelTimer");
controller.accelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / controller.reportRateHz repeats:YES block:^(NSTimer *timer) {
dispatch_sync(dispatch_get_main_queue(), ^{
voidController.hasAccelerometer = YES;
voidController.accelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / voidController.reportRateHz repeats:YES block:^(NSTimer *timer) {
// Don't send duplicate samples
GCAcceleration lastAccelSample = controller.lastAccelSample;
GCAcceleration accelSample = controller.gamepad.motion.acceleration;
NSLog(@"gyro not returned here, gyro obj:%@", voidController);
GCAcceleration lastAccelSample = voidController.lastAccelSample;
GCAcceleration accelSample = voidController.gamepad.motion.acceleration;
if (memcmp(&accelSample, &lastAccelSample, sizeof(accelSample)) == 0) {
return;
}
controller.lastAccelSample = accelSample;
voidController.lastAccelSample = accelSample;
// Convert g to m/s^2
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
NSLog(@"sending controller gyro data, accelSample data 00: %f, playerIndex: %ld, obj: %@",accelSample.x, (long)voidController.gamepad.playerIndex, voidController);
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
LI_MOTION_TYPE_ACCEL,
accelSample.x * -9.80665f * self->_gyroSensitivity,
accelSample.y * -9.80665f * self->_gyroSensitivity,
accelSample.z * -9.80665f * self->_gyroSensitivity);
}];
});
}
break;
case LI_MOTION_TYPE_GYRO:
[controller.gyroTimer invalidate];
controller.gyroTimer = nil;
[voidController.gyroTimer invalidate];
voidController.gyroTimer = nil;
if (controller.reportRateHz && controller.gamepad.motion.hasRotationRate) {
if (voidController.reportRateHz && voidController.gamepad.motion.hasRotationRate) {
// Reset the last motion sample
GCRotationRate emptyGyroSample = {};
controller.lastGyroSample = emptyGyroSample;
NSLog(@"setup controller gyro gyroTimer");
controller.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / controller.reportRateHz repeats:YES block:^(NSTimer *timer) {
voidController.lastGyroSample = emptyGyroSample;
NSLog(@"setup controller gyro gyroTimer, controller obj: %@, reportRate %d", voidController, voidController.reportRateHz);
NSLog(@"setup controller gyro gyroTimer, controller obj num in dict: %lu", (unsigned long)[[_voidControllers allValues] count]);
//dispatch_sync(dispatch_get_main_queue(), ^{
{dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"controller obj: %@", voidController);
voidController.hasGyroscope = YES;
voidController.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / voidController.reportRateHz repeats:YES block:^(NSTimer *timer) {
// Don't send duplicate samples
GCRotationRate lastGyroSample = controller.lastGyroSample;
GCRotationRate gyroSample = controller.gamepad.motion.rotationRate;
NSLog(@"gyro not returned here, voidcon obj:%@, gcCon obj %@", voidController, voidController.gamepad);
GCRotationRate lastGyroSample = voidController.lastGyroSample;
GCRotationRate gyroSample = voidController.gamepad.motion.rotationRate;
if (memcmp(&gyroSample, &lastGyroSample, sizeof(gyroSample)) == 0) {
NSLog(@"gyro returned here");
return;
}
controller.lastGyroSample = gyroSample;
voidController.lastGyroSample = gyroSample;
// Convert rad/s to deg/s
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
NSLog(@"sending controller gyro data, gyroSample data 00: %f, playerIndex: %ld, obj: %@",gyroSample.x, (long)voidController.gamepad.playerIndex, voidController);
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
LI_MOTION_TYPE_GYRO,
gyroSample.x * 57.2957795f * self->_gyroSensitivity,
gyroSample.z * 57.2957795f * self->_gyroSensitivity,
gyroSample.y * -57.2957795f * self->_gyroSensitivity);
}];
// });
});}
}
break;
}
}
}
NSLog(@"controller obj timer, motionTypes: %lu", (unsigned long)voidController.motionTypes.count);
// Set the motion sensor state if they require manual activation
[self updateSensorSateForController:voidController];
//controller.gamepad.motion.sensorsActive = YES;
NSLog(@"sensor active: %d", voidController.gamepad.motion.sensorsActive);
}
}
- (void)updateSensorSateForController:(VoidController* )voidController{
if (@available(iOS 14.0, *)) {
if (voidController.gamepad.motion.sensorsRequireManualActivation) {
if ((voidController.hasGyroscope || voidController.hasAccelerometer) && _gyroMode != GyroModeOff) {
voidController.gamepad.motion.sensorsActive = YES;
}
else {
voidController.gamepad.motion.sensorsActive = NO;
}
}
}
}
- (void) setMotionEventState:(uint16_t)controllerNumber motionType:(uint8_t)motionType reportRateHz:(uint16_t)reportRateHz {
if (@available(iOS 14.0, tvOS 14.0, *)) {
NSLog(@"gyroMode: %ld", (long)_gyroMode);
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
VoidController* voidController = [_voidControllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
//using device motion
if (controller == nil) {
if (voidController == nil || _gyroMode == AlwaysDevice) {
// No connected controller for this player, use the _oscController instead
controller = _oscController;
voidController = _oscController;
if(!voidController.motionTypes){
voidController.motionTypes = [[NSMutableSet alloc] init];
}
[voidController.motionTypes addObject:@(motionType)];
voidController.hasGyroscope = NO;
voidController.hasAccelerometer = NO;
voidController.reportRateHz = reportRateHz;
}
if(!controller.motionTypes){
controller.motionTypes = [[NSMutableSet alloc] init];
}
[controller.motionTypes addObject:@(motionType)];
controller.reportRateHz = reportRateHz;
controller.controllerNumber = controllerNumber;
NSLog(@"device gyro codes, %@, add motion type: %d, %@", controller.motionTypes, motionType, controller);
if(controller != _oscController) [self updateTimerStateForController:controller];
voidController.controllerNumber = controllerNumber;
NSLog(@"device gyro codes, %@, add motion type: %d, gyro obj: %@, is osc: %d", voidController.motionTypes, motionType, voidController, voidController == _oscController);
if(voidController == _oscController) [self updateTimerStateForController:voidController];
// [self updateTimerStateForController:voidController];
// built-in gyro will be fired somewhere else
}
}
-(void) setControllerLed:(uint16_t)controllerNumber r:(uint8_t)r g:(uint8_t)g b:(uint8_t)b {
if (@available(iOS 14.0, tvOS 14.0, *)) {
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
VoidController* controller = [_voidControllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
if (controller == nil) {
// No connected controller for this player
return;
@@ -305,7 +356,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y
-(void) updateLeftStick:(VoidController*)controller x:(short)x y:(short)y
{
@synchronized(controller) {
controller.lastLeftStickX = x;
@@ -313,7 +364,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) updateRightStick:(Controller*)controller x:(short)x y:(short)y
-(void) updateRightStick:(VoidController*)controller x:(short)x y:(short)y
{
@synchronized(controller) {
controller.lastRightStickX = x;
@@ -321,21 +372,21 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) updateLeftTrigger:(Controller*)controller left:(unsigned char)left
-(void) updateLeftTrigger:(VoidController*)controller left:(unsigned char)left
{
@synchronized(controller) {
controller.lastLeftTrigger = left;
}
}
-(void) updateRightTrigger:(Controller*)controller right:(unsigned char)right
-(void) updateRightTrigger:(VoidController*)controller right:(unsigned char)right
{
@synchronized(controller) {
controller.lastRightTrigger = right;
}
}
-(void) updateTriggers:(Controller*) controller left:(unsigned char)left right:(unsigned char)right
-(void) updateTriggers:(VoidController*) controller left:(unsigned char)left right:(unsigned char)right
{
@synchronized(controller) {
controller.lastLeftTrigger = left;
@@ -343,7 +394,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) handleSpecialCombosReleased:(Controller*)controller releasedButtons:(int)releasedButtons
-(void) handleSpecialCombosReleased:(VoidController*)controller releasedButtons:(int)releasedButtons
{
if ((controller.emulatingButtonFlags & EMULATING_SELECT) && (releasedButtons & (LB_FLAG | PLAY_FLAG))) {
controller.lastButtonFlags &= ~BACK_FLAG;
@@ -367,7 +418,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) handleSpecialCombosPressed:(Controller*)controller pressedButtons:(int)pressedButtons
-(void) handleSpecialCombosPressed:(VoidController*)controller pressedButtons:(int)pressedButtons
{
// Special button combos for select and special
if (controller.lastButtonFlags & PLAY_FLAG) {
@@ -400,7 +451,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) updateButtonFlags:(Controller*)controller flags:(int)flags
-(void) updateButtonFlags:(VoidController*)controller flags:(int)flags
{
@synchronized(controller) {
controller.lastButtonFlags = flags;
@@ -416,7 +467,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) setButtonFlag:(Controller*)controller flags:(int)flags
-(void) setButtonFlag:(VoidController*)controller flags:(int)flags
{
@synchronized(controller) {
controller.lastButtonFlags |= flags;
@@ -424,7 +475,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags
-(void) clearButtonFlag:(VoidController*)controller flags:(int)flags
{
@synchronized(controller) {
controller.lastButtonFlags &= ~flags;
@@ -437,7 +488,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
return (_multiController ? _controllerNumbers : 1) | (_oscEnabled ? 1 : 0);
}
-(void) updateFinished:(Controller*)controller
-(void) updateFinished:(VoidController*)controller
{
BOOL exitRequested = NO;
@@ -533,7 +584,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) initializeControllerHaptics:(Controller*) controller
-(void) initializeControllerHaptics:(VoidController*) controller
{
controller.lowFreqMotor = [HapticContext createContextForLowFreqMotor:controller.gamepad];
controller.highFreqMotor = [HapticContext createContextForHighFreqMotor:controller.gamepad];
@@ -541,7 +592,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
controller.rightTriggerMotor = [HapticContext createContextForRightTrigger:controller.gamepad];
}
-(void) cleanupControllerHaptics:(Controller*) controller
-(void) cleanupControllerHaptics:(VoidController*) controller
{
[controller.lowFreqMotor cleanup];
[controller.highFreqMotor cleanup];
@@ -549,7 +600,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
[controller.rightTriggerMotor cleanup];
}
-(void) cleanupControllerMotion:(Controller*) controller
-(void) cleanupControllerMotion:(VoidController*) controller
{
if (@available(iOS 14.0, tvOS 14.0, *)) {
// Stop sensor sampling timers
@@ -563,7 +614,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) initializeControllerBattery:(Controller*) controller
-(void) initializeControllerBattery:(VoidController*) controller
{
if (@available(iOS 14.0, tvOS 14.0, *)) {
if (controller.gamepad.battery) {
@@ -602,14 +653,14 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
}
-(void) cleanupControllerBattery:(Controller*) controller
-(void) cleanupControllerBattery:(VoidController*) controller
{
if (@available(iOS 14.0, tvOS 14.0, *)) {
[controller.batteryTimer invalidate];
}
}
-(BOOL) reportControllerArrival:(Controller*) limeController
-(BOOL) reportControllerArrival:(VoidController*) limeController
{
// Only report arrival once
if (limeController.reportedArrival) {
@@ -770,7 +821,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
return YES;
}
-(void) handleControllerTouchpad:(Controller*)controller touch:(GCControllerDirectionPad*)touch index:(int)index
-(void) handleControllerTouchpad:(VoidController*)controller touch:(GCControllerDirectionPad*)touch index:(int)index
{
controller_touch_context_t context = index == 0 ? controller.primaryTouch : controller.secondaryTouch;
@@ -828,7 +879,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
if (useLegacyPausedHandler) {
controller.controllerPausedHandler = ^(GCController *controller) {
Controller* limeController = [self->_controllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
VoidController* limeController = [self->_voidControllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
// Get off the main thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
@@ -854,7 +905,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
controller.extendedGamepad.valueChangedHandler = ^(GCExtendedGamepad *gamepad, GCControllerElement *element) {
Controller* limeController = [self->_controllers objectForKey:[NSNumber numberWithInteger:gamepad.controller.playerIndex]];
VoidController* limeController = [self->_voidControllers objectForKey:[NSNumber numberWithInteger:gamepad.controller.playerIndex]];
short leftStickX, leftStickY;
short rightStickX, rightStickY;
unsigned char leftTrigger, rightTrigger;
@@ -1109,26 +1160,46 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
[self updateAutoOnScreenControlMode];
}
-(Controller*) assignController:(GCController*)controller {
for (int i = 0; i < 4; i++) {
if (!(_controllerNumbers & (1 << i))) {
_controllerNumbers |= (1 << i);
controller.playerIndex = i;
-(VoidController* )controllerHasBeenAssignedDeprecated:(GCController*)controller{
if(controller.playerIndex == 0) return nil;
if(controller.playerIndex > 0){
for(VoidController* voidController in _voidControllers){
if(voidController.gamepad == controller) return voidController;
}
}
return nil;
}
Controller* limeController = [[Controller alloc] init];
limeController.playerIndex = i;
limeController.supportedEmulationFlags = EMULATING_SPECIAL | EMULATING_SELECT;
limeController.gamepad = controller;
- (void)updateVoidController:(VoidController* )voidController withGCController:(GCController* )controller{
voidController.playerIndex = controller.playerIndex == -1 ? 0 : (uint8_t) controller.playerIndex;
voidController.motionTypes = [[NSMutableSet alloc] init];
voidController.supportedEmulationFlags = EMULATING_SPECIAL | EMULATING_SELECT;
voidController.gamepad = controller;
voidController.hasAccelerometer = NO;
voidController.hasGyroscope = NO;
if(voidController.gamepad.motion.hasAttitudeAndRotationRate){
[voidController.motionTypes addObject:@(LI_MOTION_TYPE_ACCEL)];
voidController.hasAccelerometer = YES;
voidController.reportRateHz = 120;
}
if (@available(iOS 14.0, *)) {
if(voidController.gamepad.motion.hasRotationRate) [voidController.motionTypes addObject:@(LI_MOTION_TYPE_GYRO)];
voidController.hasGyroscope = YES;
voidController.reportRateHz = 120;
}
// If this is player 0, it shares state with the OSC
limeController.mergedWithController = _oscController;
_oscController.mergedWithController = limeController;
voidController.mergedWithController = _oscController;
_oscController.mergedWithController = voidController;
if (@available(iOS 13.0, tvOS 13.0, *)) {
if (controller.extendedGamepad != nil &&
controller.extendedGamepad.buttonOptions != nil) {
// Disable select button emulation since we have a physical select button
limeController.supportedEmulationFlags &= ~EMULATING_SELECT;
voidController.supportedEmulationFlags &= ~EMULATING_SELECT;
}
}
@@ -1136,24 +1207,59 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
if (controller.extendedGamepad != nil &&
controller.extendedGamepad.buttonHome != nil) {
// Disable special button emulation since we have a physical special button
limeController.supportedEmulationFlags &= ~EMULATING_SPECIAL;
voidController.supportedEmulationFlags &= ~EMULATING_SPECIAL;
}
}
// Prepare controller haptics for use
[self initializeControllerHaptics:limeController];
[self initializeControllerHaptics:voidController];
}
[_controllers setObject:limeController forKey:[NSNumber numberWithInteger:controller.playerIndex]];
-(VoidController* )assignController:(GCController*)controller {
NSLog(@"run assignController");
bool newGCControllerArrival = ![_activeGCControllers containsObject:controller];
if(!newGCControllerArrival){
VoidController* voidController = [_voidControllers objectForKey:@(controller.playerIndex)];
if(!voidController) {
NSLog(@"blablabla6666666");
voidController = [[VoidController alloc] init];
}
[self updateVoidController:voidController withGCController:controller];
[_voidControllers setObject:voidController forKey:[NSNumber numberWithInteger:voidController.playerIndex]];
return voidController;
}
for (int i = 0; i < 4; i++) {
if (!(_controllerNumbers & (1 << i))) {
_controllerNumbers |= (1 << i);
VoidController* voidController = [[VoidController alloc] init];
[_activeGCControllers addObject:controller];
controller.playerIndex = i;
voidController.playerIndex = i;
[self updateVoidController:voidController withGCController:controller];
// if(![_controllers.allValues containsObject:limeController])
[_voidControllers setObject:voidController forKey:[NSNumber numberWithInteger:controller.playerIndex]];
Log(LOG_I, @"Assigning controller index: %d", i);
return limeController;
return voidController;
}
}
return nil;
}
-(Controller*) getOscController {
-(VoidController*) getOscController {
return _oscController;
}
@@ -1208,15 +1314,31 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
-(NSUInteger) getConnectedGamepadCount
{
return _controllers.count;
return _voidControllers.count;
}
-(void)updateConfig:(StreamConfiguration*)streamConfig delegate:(id<ControllerSupportDelegate>)delegate {
- (void)assignControllers{
for (GCController* controller in [GCController controllers]) {
NSLog(@"controller count: iterating");
if ([ControllerSupport isSupportedGamepad:controller]) {
NSLog(@"controller count: is supported,is contained by dict: %d", [_activeGCControllers containsObject:controller]);
NSLog(@"controller obj +1 in dic");
[self assignController:controller];
NSLog(@"controller obj num in dict: %lu", (unsigned long)_voidControllers.allValues.count);
[self registerControllerCallbacks:controller];
// Note: We cannot report controller arrival to the host here,
// because the connection has not been established yet.play
}
}
NSLog(@"device gyro codes,update gyroMode: %d, controller count: %lu", _gyroMode, (unsigned long)_voidControllers.count);
}
- (void)updateCommonConfig:(StreamConfiguration* )streamConfig{
_streamConfig = streamConfig;
_multiController = streamConfig.multiController;
_swapABXYButtons = streamConfig.swapABXYButtons;
_gyroMode = streamConfig.gyroMode;
if(!_oscController) _oscController = [[Controller alloc] init];
_oscController.playerIndex = 0;
DataManager* dataMan = [[DataManager alloc] init];
@@ -1224,21 +1346,81 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
TemporarySettings* currentSettings = [dataMan getSettings];
_oscEnabled = true;
_gyroSensitivity = currentSettings.gyroSensitivity.floatValue;
}
- (void)updateConfig:(StreamConfiguration*)streamConfig delegate:(id<ControllerSupportDelegate>)delegate {
NSLog(@"update config call");
_gyroMode = streamConfig.gyroMode;
[self updateCommonConfig:streamConfig];
Log(LOG_I, @"Number of supported controllers connected: %d", [ControllerSupport getGamepadCount]);
Log(LOG_I, @"Multi-controller: %d", _multiController);
for (GCController* controller in [GCController controllers]) {
if ([ControllerSupport isSupportedGamepad:controller]) {
[self assignController:controller];
[self registerControllerCallbacks:controller];
// Note: We cannot report controller arrival to the host here,
// because the connection has not been established yet.
if (@available(iOS 14.0, tvOS 14.0, *)) {
switch(_gyroMode){
case GyroModeOff:
[self updateTimerStateForController:_oscController];
for(VoidController* controller in _voidControllers.allValues) [self updateTimerStateForController:controller];
break;
case GyroModeAuto:
[self stopTimerForController:_oscController];
for(VoidController* controller in _voidControllers.allValues) [self stopTimerForController:controller];
if(_voidControllers.count == 0) [self updateTimerStateForController:_oscController];
else for(VoidController* controller in _voidControllers.allValues) [self updateTimerStateForController:controller];
// to be filled
break;
case AlwaysDevice:
//[self stopTimerForController:_oscController];
for(VoidController* controller in _voidControllers.allValues){
NSLog(@"stop external controller timer %@", controller);
[self stopTimerForController:controller];
}
[self updateTimerStateForController:_oscController];
break;
case AlwaysController:
[self stopTimerForController:_oscController];
for(VoidController* controller in _voidControllers.allValues) [self stopTimerForController:controller];
for(VoidController* controller in _voidControllers.allValues) [self updateTimerStateForController:controller];
break;
}
if(_gyroMode != GyroModeOff){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
// [self->_delegate automaticallyStartSendingGyroEvents]; // this will discontine any control events sent to the remote side for a instant. anyway it works out as signature describes
});
}
}
[self assignControllers];
NSLog(@"controllerNumbers: %d", _controllerNumbers);
for(VoidController* controller in _voidControllers.allValues){
NSLog(@"controller obj in dict: %@", controller);
}
}
-(id)initWithConfig:(StreamConfiguration*)streamConfig delegate:(id<ControllerSupportDelegate>)delegate
{
self = [super init];
NSLog(@"controller support init");
_delegate = delegate;
_controllerStreamLock = [[NSLock alloc] init];
_voidControllers = [[NSMutableDictionary alloc] init];
_activeGCControllers = [[NSMutableSet alloc] init];
_controllerNumbers = 0;
_captureMouse = (streamConfig.localMousePointerMode == 0);
if (@available(iOS 14.0, tvOS 14.0, *)) {
for (GCMouse* mouse in [GCMouse mice]) {
@@ -1256,7 +1438,8 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
return;
}
Controller* limeController = [self assignController:controller];
//[self->_activeGCControllers addObject:controller];
VoidController* limeController = [self assignController:controller];
if (limeController) {
// Register callbacks on the new controller
[self registerControllerCallbacks:controller];
@@ -1265,7 +1448,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
[self reportControllerArrival:limeController];
// Re-evaluate the on-screen control mode
[self updateAutoOnScreenControlMode];
//[self updateAutoOnScreenControlMode];
// Notify the delegate
[self->_delegate gamepadPresenceChanged];
@@ -1283,28 +1466,31 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}
[self unregisterControllerCallbacks:controller];
if([self->_activeGCControllers containsObject:controller]){
[self->_activeGCControllers removeObject:controller];
self->_controllerNumbers &= ~(1 << controller.playerIndex);
}
Log(LOG_I, @"Unassigning controller index: %ld", (long)controller.playerIndex);
Controller* limeController = [self->_controllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
if (limeController) {
VoidController* voidController = [self->_voidControllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
if (voidController) {
// Stop haptics on this controller
[self cleanupControllerHaptics:limeController];
[self cleanupControllerHaptics:voidController];
// Stop motion reports on this controller
[self cleanupControllerMotion:limeController];
[self cleanupControllerMotion:voidController];
// Stop battery reports on this controller
[self cleanupControllerBattery:limeController];
[self cleanupControllerBattery:voidController];
// Disassociate this controller from any controllers merged with it
if (limeController.mergedWithController) {
assert(limeController.mergedWithController.mergedWithController == limeController);
limeController.mergedWithController.mergedWithController = nil;
if (voidController.mergedWithController) {
if(voidController.mergedWithController.mergedWithController == voidController) voidController.mergedWithController.mergedWithController = nil;
}
// Inform the server of the updated active gamepads before removing this controller
[self updateFinished:limeController];
[self updateFinished:voidController];
// Re-evaluate the on-screen control mode
[self updateAutoOnScreenControlMode];
@@ -1315,6 +1501,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
}];
if (@available(iOS 14.0, tvOS 14.0, *)) {
_mouseConnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
Log(LOG_I, @"Mouse connected!");
@@ -1355,52 +1542,68 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
// Re-evaluate the on-screen control mode
[self updateAutoOnScreenControlMode];
}];
NSLog(@"device gyro codes,update gyroMode: %d, controller count: %lu", _gyroMode, (unsigned long)_controllers.count);
for(Controller* controller in _controllers) [self updateTimerStateForController:controller];
if(_controllers.count == 0) [self updateTimerStateForController:_oscController];
}
//for(Controller* controller in _controllers) [self updateTimerStateForController:controller];
}
-(id)initWithConfig:(StreamConfiguration*)streamConfig delegate:(id<ControllerSupportDelegate>)delegate
{
self = [super init];
_delegate = delegate;
_controllerStreamLock = [[NSLock alloc] init];
_controllers = [[NSMutableDictionary alloc] init];
_controllerNumbers = 0;
[self updateConfig:streamConfig delegate:delegate];
_oscController = [[VoidController alloc] init];
_gyroMode = AlwaysDevice;
[self updateCommonConfig:streamConfig];
for(VoidController* controller in _voidControllers.allValues){
NSLog(@"stop external controller timer %@", controller);
[self stopTimerForController:controller];
}
[self updateTimerStateForController:_oscController];
[self assignControllers];
//[self updateConfig:streamConfig delegate:delegate];
return self;
}
-(void)connectionEstablished{
for (Controller* controller in [_controllers allValues]){
// Report the controller arrival to the host if we haven't done so yet
[self reportControllerArrival:controller];
[self updateTimerStateForController:controller];
}
//return;
if(_controllers.count ==0 && (_gyroMode == GyroModeAuto || _gyroMode == AlwaysDevice)){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self updateTimerStateForController:self->_oscController];
[self setButtonFlag:self->_oscController flags:A_FLAG];
[self updateFinished:self->_oscController];
[self clearButtonFlag:self->_oscController flags:A_FLAG];
[self updateFinished:self->_oscController];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)),
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self->_delegate automaticallyStartSendingBuiltinGyroEvents]; // this will discontine any control events sent to the remote side for a instant. anyway it works out as signature describes
});
});
//[self->_delegate automaticallyStartSendingGyroEvents]; // this will discontine any control events sent to the remote side for a instant. anyway it works out as signature describes
[self updateTimerStateForController:self->_oscController];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
self->_gyroMode = self->_streamConfig.gyroMode;
if(self->_gyroMode == AlwaysController){
[self stopTimerForController:self->_oscController];
for(VoidController* voidController in self->_voidControllers.allValues) [self stopTimerForController:voidController];
for(VoidController* voidController in self->_voidControllers.allValues) [self updateTimerStateForController:voidController];
//for(VoidController* controller in _voidControllers.allValues) [self updateTimerStateForController:controller];
}
});
});
}
-(void)stopTimerForController:(Controller* )controller{
-(void)stopTimerForController:(VoidController* )controller{
if (@available(iOS 14.0, *)) {
NSLog(@"stop controller obj: %@, hasAcc %d, hasGyro %d", controller, controller.hasAccelerometer, controller.hasGyroscope);
// return;
if(controller.hasAccelerometer){
[controller.accelTimer invalidate];
controller.accelTimer = nil;
}
if(controller.hasGyroscope){
[controller.gyroTimer invalidate];
controller.gyroTimer = nil;
}
}
}
-(void) cleanup
{
@@ -1420,13 +1623,14 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
_controllerNumbers = 0;
for (Controller* controller in [_controllers allValues]) {
[self stopTimerForController:_oscController];
for (VoidController* controller in [_voidControllers allValues]) {
[self stopTimerForController:controller];
[self cleanupControllerHaptics:controller];
[self cleanupControllerMotion:controller];
[self cleanupControllerBattery:controller];
}
[_controllers removeAllObjects];
[_voidControllers removeAllObjects];
#if !TARGET_OS_TV
[self cleanupControllerMotion:_oscController];
+2 -2
View File
@@ -11,7 +11,7 @@
#import "OnScreenControls.h"
#import "CustomTapGestureRecognizer.h"
#import "Controller.h"
#import "VoidController.h"
#include "Limelight.h"
#if !TARGET_OS_TV
#import <CoreMotion/CoreMotion.h>
@@ -70,7 +70,7 @@ static NSSet *validPositionButtonNames;
BOOL _visible;
ControllerSupport *_controllerSupport;
Controller *_controller;
VoidController *_controller;
NSMutableArray* _deadTouches;
BOOL _swapABXY;
BOOL _largerStickLR1;
@@ -14,7 +14,7 @@
@import CoreMotion;
#endif
@interface Controller : NSObject
@interface VoidController : NSObject
typedef struct {
float lastX;
@@ -64,11 +64,13 @@ typedef NS_ENUM(NSInteger, ControllerDeviceBatteryState) {
@property (nonatomic) float lastBatteryLevel;
@property (nonatomic) BOOL reportedArrival;
@property (nonatomic) Controller* _Nullable mergedWithController;
@property (nonatomic) VoidController* _Nullable mergedWithController;
@property(nonatomic, strong) NSMutableSet* _Nullable motionTypes;
@property(nonatomic, assign) uint16_t reportRateHz;
@property(nonatomic, assign) uint16_t controllerNumber;
@property(nonatomic, assign) BOOL hasAccelerometer;
@property(nonatomic, assign) BOOL hasGyroscope;
@end
@@ -6,8 +6,8 @@
// Copyright © 2019 Moonlight Game Streaming Project. All rights reserved.
//
#include "Controller.h"
#include "VoidController.h"
@implementation Controller
@implementation VoidController
@end
@@ -57,6 +57,7 @@
StreamView *_streamView;
UIScrollView *_scrollView;
BOOL _userIsInteracting;
bool viewJustLoaded;
CGSize _keyboardSize;
UIWindow *_extWindow;
UIView *_streamVideoRenderView;
@@ -195,7 +196,10 @@
[self->_streamView disableOnScreenControls]; //don't know why but this must be called outside the streamview class, just put it here. execute in streamview class cause hang
[self.mainFrameViewcontroller reloadStreamConfig]; // reload streamconfig
[_controllerSupport updateConfig:self.streamConfig delegate:self];// reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC
NSLog(@"viewJustloaded: %d", viewJustLoaded);
if(!viewJustLoaded) [_controllerSupport updateConfig:self.streamConfig delegate:self];
else viewJustLoaded = false;
// reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC
[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig streamFrameTopLayerView:self.view]; //reinitiate setupStreamView process.
// we got self.view passed to streamView class as the topLayerView, will be useful in many cases
[self->_streamView reloadOnScreenControlsRealtimeWith:(ControllerSupport*)_controllerSupport
@@ -215,7 +219,7 @@
NSLog(@"streamview gestures: %d", (uint32_t)[_streamView.gestureRecognizers count]);
}
-(void)automaticallyStartSendingBuiltinGyroEvents{
-(void)automaticallyStartSendingGyroEvents{
[_controllerSupport updateConfig:self.streamConfig delegate:self];// reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC
}
@@ -347,6 +351,7 @@
- (void)viewDidLoad
{
viewJustLoaded = true;
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES animated:YES];