switch between built-in & controller gyros
This commit is contained in:
1 parent
3cbdba78d6
commit
578ad81b8a
7 files changed
+400
-189
No files matched your search
@@ -49,7 +49,7 @@
|
|||||||
988FCD41293B091B003050E2 /* KeyboardInputField.m in Sources */ = {isa = PBXBuildFile; fileRef = 988FCD40293B091B003050E2 /* KeyboardInputField.m */; };
|
988FCD41293B091B003050E2 /* KeyboardInputField.m in Sources */ = {isa = PBXBuildFile; fileRef = 988FCD40293B091B003050E2 /* KeyboardInputField.m */; };
|
||||||
9890CF6B203B7EE1006C4B06 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9890CF6A203B7EE1006C4B06 /* libxml2.tbd */; };
|
9890CF6B203B7EE1006C4B06 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9890CF6A203B7EE1006C4B06 /* libxml2.tbd */; };
|
||||||
9896219723D15C7000211983 /* X1Kit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9896219623D15C7000211983 /* X1Kit.swift */; };
|
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 */; };
|
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98AB2E841CAD46840089BB98 /* libmoonlight-common.a */; };
|
||||||
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; };
|
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; };
|
||||||
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
9897B6A0221260EF00966419 /* VoidController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VoidController.m; sourceTree = "<group>"; };
|
||||||
9897B6A32212610800966419 /* Controller.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Controller.h; 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>"; };
|
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; };
|
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>"; };
|
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 */,
|
FB4678EC1A50C40900377732 /* OnScreenControls.m */,
|
||||||
FB1A674B2131E65900507771 /* KeyboardSupport.h */,
|
FB1A674B2131E65900507771 /* KeyboardSupport.h */,
|
||||||
FB1A674C2131E65900507771 /* KeyboardSupport.m */,
|
FB1A674C2131E65900507771 /* KeyboardSupport.m */,
|
||||||
9897B6A0221260EF00966419 /* Controller.m */,
|
9897B6A0221260EF00966419 /* VoidController.m */,
|
||||||
9897B6A32212610800966419 /* Controller.h */,
|
9897B6A32212610800966419 /* VoidController.h */,
|
||||||
9827E7A22514366900F25707 /* HapticContext.m */,
|
9827E7A22514366900F25707 /* HapticContext.m */,
|
||||||
9827E7A7251436EA00F25707 /* HapticContext.h */,
|
9827E7A7251436EA00F25707 /* HapticContext.h */,
|
||||||
840751B12BF49B5A0096B657 /* CustomTapGestureRecognizer.h */,
|
840751B12BF49B5A0096B657 /* CustomTapGestureRecognizer.h */,
|
||||||
@@ -874,7 +874,7 @@
|
|||||||
847D2FDB2DDA015F00937A62 /* MenuSectionView.m in Sources */,
|
847D2FDB2DDA015F00937A62 /* MenuSectionView.m in Sources */,
|
||||||
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
|
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
|
||||||
189AD29A2DE7446000E24B88 /* HostCollectionViewController.m in Sources */,
|
189AD29A2DE7446000E24B88 /* HostCollectionViewController.m in Sources */,
|
||||||
9897B6A1221260EF00966419 /* Controller.m in Sources */,
|
9897B6A1221260EF00966419 /* VoidController.m in Sources */,
|
||||||
84351B112C29ACCB00A77989 /* OSCProfilesManager.m in Sources */,
|
84351B112C29ACCB00A77989 /* OSCProfilesManager.m in Sources */,
|
||||||
FB89462919F646E200339C8A /* mkcert.c in Sources */,
|
FB89462919F646E200339C8A /* mkcert.c in Sources */,
|
||||||
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
|
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
|
||||||
@@ -1135,7 +1135,7 @@
|
|||||||
"$(PROJECT_DIR)/libs/FFmpeg/lib/iOS-Sim",
|
"$(PROJECT_DIR)/libs/FFmpeg/lib/iOS-Sim",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.0.1;
|
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)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE = "";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "StreamConfiguration.h"
|
#import "StreamConfiguration.h"
|
||||||
#import "Controller.h"
|
#import "VoidController.h"
|
||||||
|
|
||||||
@class OnScreenControls;
|
@class OnScreenControls;
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
- (void)gamepadPresenceChanged;
|
- (void)gamepadPresenceChanged;
|
||||||
- (void)mousePresenceChanged;
|
- (void)mousePresenceChanged;
|
||||||
- (void)streamExitRequested;
|
- (void)streamExitRequested;
|
||||||
- (void)automaticallyStartSendingBuiltinGyroEvents;
|
- (void)automaticallyStartSendingGyroEvents;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -27,20 +27,20 @@
|
|||||||
|
|
||||||
-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc;
|
-(void) initAutoOnScreenControlMode:(OnScreenControls*)osc;
|
||||||
-(void) cleanup;
|
-(void) cleanup;
|
||||||
-(Controller*) getOscController;
|
-(VoidController*) getOscController;
|
||||||
|
|
||||||
-(void) updateLeftStick:(Controller*)controller x:(short)x y:(short)y;
|
-(void) updateLeftStick:(VoidController*)controller x:(short)x y:(short)y;
|
||||||
-(void) updateRightStick:(Controller*)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) updateLeftTrigger:(VoidController*)controller left:(unsigned char)left;
|
||||||
-(void) updateRightTrigger:(Controller*)controller right:(unsigned char)right;
|
-(void) updateRightTrigger:(VoidController*)controller right:(unsigned char)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;
|
||||||
|
|
||||||
-(void) updateButtonFlags:(Controller*)controller flags:(int)flags;
|
-(void) updateButtonFlags:(VoidController*)controller flags:(int)flags;
|
||||||
-(void) setButtonFlag:(Controller*)controller flags:(int)flags;
|
-(void) setButtonFlag:(VoidController*)controller flags:(int)flags;
|
||||||
-(void) clearButtonFlag:(Controller*)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) 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;
|
-(void) rumbleTriggers:(uint16_t)controllerNumber leftTrigger:(uint16_t)leftTrigger rightTrigger:(uint16_t)rightTrigger;
|
||||||
|
|||||||
+366
-162
@@ -10,7 +10,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
#import "Controller.h"
|
#import "VoidController.h"
|
||||||
|
|
||||||
#import "OnScreenControls.h"
|
#import "OnScreenControls.h"
|
||||||
|
|
||||||
@@ -34,9 +34,9 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
id _keyboardDisconnectObserver;
|
id _keyboardDisconnectObserver;
|
||||||
|
|
||||||
NSLock *_controllerStreamLock;
|
NSLock *_controllerStreamLock;
|
||||||
NSMutableDictionary *_controllers;
|
NSMutableDictionary *_voidControllers;
|
||||||
id<ControllerSupportDelegate> _delegate;
|
id<ControllerSupportDelegate> _delegate;
|
||||||
StreamConfiguration* streamConfig;
|
StreamConfiguration* _streamConfig;
|
||||||
|
|
||||||
float accumulatedDeltaX;
|
float accumulatedDeltaX;
|
||||||
float accumulatedDeltaY;
|
float accumulatedDeltaY;
|
||||||
@@ -44,7 +44,8 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
float accumulatedScrollY;
|
float accumulatedScrollY;
|
||||||
|
|
||||||
OnScreenControls *_osc;
|
OnScreenControls *_osc;
|
||||||
Controller *_oscController;
|
VoidController *_oscController;
|
||||||
|
NSMutableSet* _activeGCControllers;
|
||||||
|
|
||||||
#define EMULATING_SELECT 0x1
|
#define EMULATING_SELECT 0x1
|
||||||
#define EMULATING_SPECIAL 0x2
|
#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
|
-(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) {
|
if (controller == nil && controllerNumber == 0 && _oscEnabled) {
|
||||||
// TODO: Rumble emulation for OSC
|
// 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
|
-(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) {
|
if (controller == nil && controllerNumber == 0 && _oscEnabled) {
|
||||||
// TODO: Trigger rumble emulation for OSC
|
// TODO: Trigger rumble emulation for OSC
|
||||||
}
|
}
|
||||||
@@ -93,62 +94,68 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
[controller.rightTriggerMotor setMotorAmplitude:rightTrigger];
|
[controller.rightTriggerMotor setMotorAmplitude:rightTrigger];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)updateTimerStateForController:(Controller* )controller{
|
-(void)updateTimerStateForController:(VoidController* )voidController{
|
||||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
|
NSLog(@"controller obj timer update");
|
||||||
if(_gyroMode == GyroModeOff){
|
if(_gyroMode == GyroModeOff){
|
||||||
[self stopTimerForController:controller];
|
[self stopTimerForController:voidController];
|
||||||
return;
|
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;
|
uint8_t motionType = motionTypeObj.intValue;
|
||||||
|
NSLog(@"controller obj controllerNumber %d", voidController.controllerNumber);
|
||||||
|
|
||||||
if(_gyroMode != AlwaysController && controller.controllerNumber < 2){
|
if(_gyroMode != AlwaysController || voidController == _oscController){
|
||||||
|
|
||||||
#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];
|
|
||||||
}
|
|
||||||
|
|
||||||
NSLog(@"device gyro mode, motionType: %d", motionType);
|
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) {
|
switch (motionType) {
|
||||||
case LI_MOTION_TYPE_ACCEL:
|
case LI_MOTION_TYPE_ACCEL:
|
||||||
[controller.accelTimer invalidate];
|
[voidController.accelTimer invalidate];
|
||||||
controller.accelTimer = nil;
|
voidController.accelTimer = nil;
|
||||||
// Reset the last motion sample
|
// Reset the last motion sample
|
||||||
CMAcceleration emptyDeviceAccelSample = {};
|
CMAcceleration emptyDeviceAccelSample = {};
|
||||||
controller.lastDeviceAccelSample = emptyDeviceAccelSample;
|
voidController.lastDeviceAccelSample = emptyDeviceAccelSample;
|
||||||
|
|
||||||
{dispatch_async(dispatch_get_main_queue(), ^{
|
{dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
NSLog(@"setup device built-in gyro accelTimer");
|
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
|
// Don't send duplicate samples
|
||||||
CMAcceleration lastDeviceAccelSample = controller.lastDeviceAccelSample;
|
CMAcceleration lastDeviceAccelSample = voidController.lastDeviceAccelSample;
|
||||||
CMAcceleration deviceAccelSample = controller.motionManager.deviceMotion.userAcceleration;
|
CMAcceleration deviceAccelSample = voidController.motionManager.deviceMotion.userAcceleration;
|
||||||
//userAcceleration does not contain gravity, add gravity to x, y and z values:
|
//userAcceleration does not contain gravity, add gravity to x, y and z values:
|
||||||
deviceAccelSample.x += controller.motionManager.deviceMotion.gravity.x * self->_gyroSensitivity;
|
deviceAccelSample.x += voidController.motionManager.deviceMotion.gravity.x * self->_gyroSensitivity;
|
||||||
deviceAccelSample.y += controller.motionManager.deviceMotion.gravity.y * self->_gyroSensitivity;
|
deviceAccelSample.y += voidController.motionManager.deviceMotion.gravity.y * self->_gyroSensitivity;
|
||||||
deviceAccelSample.z += controller.motionManager.deviceMotion.gravity.z * self->_gyroSensitivity;
|
deviceAccelSample.z += voidController.motionManager.deviceMotion.gravity.z * self->_gyroSensitivity;
|
||||||
|
|
||||||
if (memcmp(&deviceAccelSample, &lastDeviceAccelSample, sizeof(deviceAccelSample)) == 0) {
|
if (memcmp(&deviceAccelSample, &lastDeviceAccelSample, sizeof(deviceAccelSample)) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.lastDeviceAccelSample = deviceAccelSample;
|
voidController.lastDeviceAccelSample = deviceAccelSample;
|
||||||
|
|
||||||
// Convert g to m/s^2
|
// Convert g to m/s^2
|
||||||
if(UIApplication.sharedApplication.windows.firstObject.windowScene.interfaceOrientation == 4){ //check for landscape left or landscape right
|
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,
|
LI_MOTION_TYPE_ACCEL,
|
||||||
deviceAccelSample.y * -9.80665f * self->_gyroSensitivity,
|
deviceAccelSample.y * -9.80665f * self->_gyroSensitivity,
|
||||||
deviceAccelSample.z * -9.80665f * self->_gyroSensitivity,
|
deviceAccelSample.z * -9.80665f * self->_gyroSensitivity,
|
||||||
deviceAccelSample.x * -9.80665f * self->_gyroSensitivity);
|
deviceAccelSample.x * -9.80665f * self->_gyroSensitivity);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
|
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
|
||||||
LI_MOTION_TYPE_ACCEL,
|
LI_MOTION_TYPE_ACCEL,
|
||||||
deviceAccelSample.y * +9.80665f * self->_gyroSensitivity,
|
deviceAccelSample.y * +9.80665f * self->_gyroSensitivity,
|
||||||
deviceAccelSample.z * -9.80665f * self->_gyroSensitivity,
|
deviceAccelSample.z * -9.80665f * self->_gyroSensitivity,
|
||||||
@@ -158,35 +165,37 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
});}
|
});}
|
||||||
break;
|
break;
|
||||||
case LI_MOTION_TYPE_GYRO:
|
case LI_MOTION_TYPE_GYRO:
|
||||||
[controller.gyroTimer invalidate];
|
[voidController.gyroTimer invalidate];
|
||||||
controller.gyroTimer = nil;
|
voidController.gyroTimer = nil;
|
||||||
|
|
||||||
// Reset the last motion sample
|
// Reset the last motion sample
|
||||||
CMRotationRate emptyDeviceGyroSample = {};
|
CMRotationRate emptyDeviceGyroSample = {};
|
||||||
controller.lastDeviceGyroSample = emptyDeviceGyroSample;
|
voidController.lastDeviceGyroSample = emptyDeviceGyroSample;
|
||||||
[controller.motionManager startDeviceMotionUpdates];
|
[voidController.motionManager startDeviceMotionUpdates];
|
||||||
|
|
||||||
NSLog(@"setup device built-in gyro gyroTimer");
|
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
|
// Don't send duplicate samples
|
||||||
CMRotationRate lastDeviceGyroSample = controller.lastDeviceGyroSample;
|
CMRotationRate lastDeviceGyroSample = voidController.lastDeviceGyroSample;
|
||||||
CMRotationRate deviceGyroSample = controller.motionManager.deviceMotion.rotationRate;
|
CMRotationRate deviceGyroSample = voidController.motionManager.deviceMotion.rotationRate;
|
||||||
if (memcmp(&deviceGyroSample, &lastDeviceGyroSample, sizeof(deviceGyroSample)) == 0) {
|
if (memcmp(&deviceGyroSample, &lastDeviceGyroSample, sizeof(deviceGyroSample)) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.lastDeviceGyroSample = deviceGyroSample;
|
voidController.lastDeviceGyroSample = deviceGyroSample;
|
||||||
|
|
||||||
// Convert rad/s to deg/s
|
// 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
|
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,
|
LI_MOTION_TYPE_GYRO,
|
||||||
deviceGyroSample.y * 57.2957795f * self->_gyroSensitivity,
|
deviceGyroSample.y * 57.2957795f * self->_gyroSensitivity,
|
||||||
deviceGyroSample.z * 57.2957795f * self->_gyroSensitivity,
|
deviceGyroSample.z * 57.2957795f * self->_gyroSensitivity,
|
||||||
deviceGyroSample.x * 57.2957795f * self->_gyroSensitivity);
|
deviceGyroSample.x * 57.2957795f * self->_gyroSensitivity);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
LiSendControllerMotionEvent((uint8_t)controller.controllerNumber,
|
LiSendControllerMotionEvent((uint8_t)voidController.controllerNumber,
|
||||||
LI_MOTION_TYPE_GYRO,
|
LI_MOTION_TYPE_GYRO,
|
||||||
deviceGyroSample.y * -57.2957795f * self->_gyroSensitivity,
|
deviceGyroSample.y * -57.2957795f * self->_gyroSensitivity,
|
||||||
deviceGyroSample.z * 57.2957795f * self->_gyroSensitivity,
|
deviceGyroSample.z * 57.2957795f * self->_gyroSensitivity,
|
||||||
@@ -199,98 +208,140 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else{
|
else{
|
||||||
|
NSLog(@"controller obj timer update: controller timer ");
|
||||||
switch (motionType) {
|
switch (motionType) {
|
||||||
case LI_MOTION_TYPE_ACCEL:
|
case LI_MOTION_TYPE_ACCEL:
|
||||||
[controller.accelTimer invalidate];
|
[voidController.accelTimer invalidate];
|
||||||
controller.accelTimer = nil;
|
voidController.accelTimer = nil;
|
||||||
NSLog(@"LI_MOTION_TYPE_ACCEL: setup controller gyro accelTimer");
|
|
||||||
|
|
||||||
if (controller.reportRateHz && controller.gamepad.motion.hasGravityAndUserAcceleration) {
|
if (voidController.reportRateHz && voidController.gamepad.motion.hasGravityAndUserAcceleration) {
|
||||||
// Reset the last motion sample
|
// Reset the last motion sample
|
||||||
GCAcceleration emptyAccelSample = {};
|
GCAcceleration emptyAccelSample = {};
|
||||||
controller.lastAccelSample = emptyAccelSample;
|
voidController.lastAccelSample = emptyAccelSample;
|
||||||
NSLog(@"setup controller gyro accelTimer");
|
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
|
// Don't send duplicate samples
|
||||||
GCAcceleration lastAccelSample = controller.lastAccelSample;
|
NSLog(@"gyro not returned here, gyro obj:%@", voidController);
|
||||||
GCAcceleration accelSample = controller.gamepad.motion.acceleration;
|
GCAcceleration lastAccelSample = voidController.lastAccelSample;
|
||||||
|
GCAcceleration accelSample = voidController.gamepad.motion.acceleration;
|
||||||
|
|
||||||
if (memcmp(&accelSample, &lastAccelSample, sizeof(accelSample)) == 0) {
|
if (memcmp(&accelSample, &lastAccelSample, sizeof(accelSample)) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.lastAccelSample = accelSample;
|
voidController.lastAccelSample = accelSample;
|
||||||
|
|
||||||
// Convert g to m/s^2
|
// 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,
|
LI_MOTION_TYPE_ACCEL,
|
||||||
accelSample.x * -9.80665f * self->_gyroSensitivity,
|
accelSample.x * -9.80665f * self->_gyroSensitivity,
|
||||||
accelSample.y * -9.80665f * self->_gyroSensitivity,
|
accelSample.y * -9.80665f * self->_gyroSensitivity,
|
||||||
accelSample.z * -9.80665f * self->_gyroSensitivity);
|
accelSample.z * -9.80665f * self->_gyroSensitivity);
|
||||||
}];
|
}];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LI_MOTION_TYPE_GYRO:
|
case LI_MOTION_TYPE_GYRO:
|
||||||
[controller.gyroTimer invalidate];
|
[voidController.gyroTimer invalidate];
|
||||||
controller.gyroTimer = nil;
|
voidController.gyroTimer = nil;
|
||||||
|
|
||||||
if (controller.reportRateHz && controller.gamepad.motion.hasRotationRate) {
|
if (voidController.reportRateHz && voidController.gamepad.motion.hasRotationRate) {
|
||||||
// Reset the last motion sample
|
// Reset the last motion sample
|
||||||
GCRotationRate emptyGyroSample = {};
|
GCRotationRate emptyGyroSample = {};
|
||||||
controller.lastGyroSample = emptyGyroSample;
|
voidController.lastGyroSample = emptyGyroSample;
|
||||||
NSLog(@"setup controller gyro gyroTimer");
|
NSLog(@"setup controller gyro gyroTimer, controller obj: %@, reportRate %d", voidController, voidController.reportRateHz);
|
||||||
controller.gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / controller.reportRateHz repeats:YES block:^(NSTimer *timer) {
|
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
|
// Don't send duplicate samples
|
||||||
GCRotationRate lastGyroSample = controller.lastGyroSample;
|
NSLog(@"gyro not returned here, voidcon obj:%@, gcCon obj %@", voidController, voidController.gamepad);
|
||||||
GCRotationRate gyroSample = controller.gamepad.motion.rotationRate;
|
GCRotationRate lastGyroSample = voidController.lastGyroSample;
|
||||||
|
GCRotationRate gyroSample = voidController.gamepad.motion.rotationRate;
|
||||||
if (memcmp(&gyroSample, &lastGyroSample, sizeof(gyroSample)) == 0) {
|
if (memcmp(&gyroSample, &lastGyroSample, sizeof(gyroSample)) == 0) {
|
||||||
|
NSLog(@"gyro returned here");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
controller.lastGyroSample = gyroSample;
|
voidController.lastGyroSample = gyroSample;
|
||||||
|
|
||||||
// Convert rad/s to deg/s
|
// 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,
|
LI_MOTION_TYPE_GYRO,
|
||||||
gyroSample.x * 57.2957795f * self->_gyroSensitivity,
|
gyroSample.x * 57.2957795f * self->_gyroSensitivity,
|
||||||
gyroSample.z * 57.2957795f * self->_gyroSensitivity,
|
gyroSample.z * 57.2957795f * self->_gyroSensitivity,
|
||||||
gyroSample.y * -57.2957795f * self->_gyroSensitivity);
|
gyroSample.y * -57.2957795f * self->_gyroSensitivity);
|
||||||
}];
|
}];
|
||||||
|
// });
|
||||||
|
});}
|
||||||
}
|
}
|
||||||
break;
|
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 {
|
- (void) setMotionEventState:(uint16_t)controllerNumber motionType:(uint8_t)motionType reportRateHz:(uint16_t)reportRateHz {
|
||||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
NSLog(@"gyroMode: %ld", (long)_gyroMode);
|
NSLog(@"gyroMode: %ld", (long)_gyroMode);
|
||||||
|
|
||||||
Controller* controller = [_controllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
|
VoidController* voidController = [_voidControllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
|
||||||
//using device motion
|
//using device motion
|
||||||
if (controller == nil) {
|
if (voidController == nil || _gyroMode == AlwaysDevice) {
|
||||||
// No connected controller for this player, use the _oscController instead
|
// 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
|
// 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 {
|
-(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, *)) {
|
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) {
|
if (controller == nil) {
|
||||||
// No connected controller for this player
|
// No connected controller for this player
|
||||||
return;
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastLeftStickX = x;
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastRightStickX = x;
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastLeftTrigger = left;
|
controller.lastLeftTrigger = left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) updateRightTrigger:(Controller*)controller right:(unsigned char)right
|
-(void) updateRightTrigger:(VoidController*)controller right:(unsigned char)right
|
||||||
{
|
{
|
||||||
@synchronized(controller) {
|
@synchronized(controller) {
|
||||||
controller.lastRightTrigger = right;
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastLeftTrigger = left;
|
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))) {
|
if ((controller.emulatingButtonFlags & EMULATING_SELECT) && (releasedButtons & (LB_FLAG | PLAY_FLAG))) {
|
||||||
controller.lastButtonFlags &= ~BACK_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
|
// Special button combos for select and special
|
||||||
if (controller.lastButtonFlags & PLAY_FLAG) {
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastButtonFlags = flags;
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastButtonFlags |= flags;
|
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) {
|
@synchronized(controller) {
|
||||||
controller.lastButtonFlags &= ~flags;
|
controller.lastButtonFlags &= ~flags;
|
||||||
@@ -437,7 +488,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
return (_multiController ? _controllerNumbers : 1) | (_oscEnabled ? 1 : 0);
|
return (_multiController ? _controllerNumbers : 1) | (_oscEnabled ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) updateFinished:(Controller*)controller
|
-(void) updateFinished:(VoidController*)controller
|
||||||
{
|
{
|
||||||
BOOL exitRequested = NO;
|
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.lowFreqMotor = [HapticContext createContextForLowFreqMotor:controller.gamepad];
|
||||||
controller.highFreqMotor = [HapticContext createContextForHighFreqMotor: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];
|
controller.rightTriggerMotor = [HapticContext createContextForRightTrigger:controller.gamepad];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) cleanupControllerHaptics:(Controller*) controller
|
-(void) cleanupControllerHaptics:(VoidController*) controller
|
||||||
{
|
{
|
||||||
[controller.lowFreqMotor cleanup];
|
[controller.lowFreqMotor cleanup];
|
||||||
[controller.highFreqMotor cleanup];
|
[controller.highFreqMotor cleanup];
|
||||||
@@ -549,7 +600,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
[controller.rightTriggerMotor cleanup];
|
[controller.rightTriggerMotor cleanup];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) cleanupControllerMotion:(Controller*) controller
|
-(void) cleanupControllerMotion:(VoidController*) controller
|
||||||
{
|
{
|
||||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
// Stop sensor sampling timers
|
// 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 (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
if (controller.gamepad.battery) {
|
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, *)) {
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
[controller.batteryTimer invalidate];
|
[controller.batteryTimer invalidate];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(BOOL) reportControllerArrival:(Controller*) limeController
|
-(BOOL) reportControllerArrival:(VoidController*) limeController
|
||||||
{
|
{
|
||||||
// Only report arrival once
|
// Only report arrival once
|
||||||
if (limeController.reportedArrival) {
|
if (limeController.reportedArrival) {
|
||||||
@@ -770,7 +821,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
return YES;
|
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;
|
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) {
|
if (useLegacyPausedHandler) {
|
||||||
controller.controllerPausedHandler = ^(GCController *controller) {
|
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
|
// Get off the main thread
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
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.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 leftStickX, leftStickY;
|
||||||
short rightStickX, rightStickY;
|
short rightStickX, rightStickY;
|
||||||
unsigned char leftTrigger, rightTrigger;
|
unsigned char leftTrigger, rightTrigger;
|
||||||
@@ -1109,26 +1160,46 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
[self updateAutoOnScreenControlMode];
|
[self updateAutoOnScreenControlMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(Controller*) assignController:(GCController*)controller {
|
-(VoidController* )controllerHasBeenAssignedDeprecated:(GCController*)controller{
|
||||||
for (int i = 0; i < 4; i++) {
|
if(controller.playerIndex == 0) return nil;
|
||||||
if (!(_controllerNumbers & (1 << i))) {
|
if(controller.playerIndex > 0){
|
||||||
_controllerNumbers |= (1 << i);
|
for(VoidController* voidController in _voidControllers){
|
||||||
controller.playerIndex = i;
|
if(voidController.gamepad == controller) return voidController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
Controller* limeController = [[Controller alloc] init];
|
|
||||||
limeController.playerIndex = i;
|
- (void)updateVoidController:(VoidController* )voidController withGCController:(GCController* )controller{
|
||||||
limeController.supportedEmulationFlags = EMULATING_SPECIAL | EMULATING_SELECT;
|
voidController.playerIndex = controller.playerIndex == -1 ? 0 : (uint8_t) controller.playerIndex;
|
||||||
limeController.gamepad = controller;
|
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
|
// If this is player 0, it shares state with the OSC
|
||||||
limeController.mergedWithController = _oscController;
|
voidController.mergedWithController = _oscController;
|
||||||
_oscController.mergedWithController = limeController;
|
_oscController.mergedWithController = voidController;
|
||||||
|
|
||||||
if (@available(iOS 13.0, tvOS 13.0, *)) {
|
if (@available(iOS 13.0, tvOS 13.0, *)) {
|
||||||
if (controller.extendedGamepad != nil &&
|
if (controller.extendedGamepad != nil &&
|
||||||
controller.extendedGamepad.buttonOptions != nil) {
|
controller.extendedGamepad.buttonOptions != nil) {
|
||||||
// Disable select button emulation since we have a physical select button
|
// 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 &&
|
if (controller.extendedGamepad != nil &&
|
||||||
controller.extendedGamepad.buttonHome != nil) {
|
controller.extendedGamepad.buttonHome != nil) {
|
||||||
// Disable special button emulation since we have a physical special button
|
// Disable special button emulation since we have a physical special button
|
||||||
limeController.supportedEmulationFlags &= ~EMULATING_SPECIAL;
|
voidController.supportedEmulationFlags &= ~EMULATING_SPECIAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare controller haptics for use
|
// 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);
|
Log(LOG_I, @"Assigning controller index: %d", i);
|
||||||
return limeController;
|
|
||||||
|
return voidController;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(Controller*) getOscController {
|
-(VoidController*) getOscController {
|
||||||
return _oscController;
|
return _oscController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1208,15 +1314,31 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
|
|
||||||
-(NSUInteger) getConnectedGamepadCount
|
-(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;
|
_multiController = streamConfig.multiController;
|
||||||
_swapABXYButtons = streamConfig.swapABXYButtons;
|
_swapABXYButtons = streamConfig.swapABXYButtons;
|
||||||
_gyroMode = streamConfig.gyroMode;
|
|
||||||
|
|
||||||
if(!_oscController) _oscController = [[Controller alloc] init];
|
|
||||||
_oscController.playerIndex = 0;
|
_oscController.playerIndex = 0;
|
||||||
|
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
@@ -1224,21 +1346,81 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
TemporarySettings* currentSettings = [dataMan getSettings];
|
TemporarySettings* currentSettings = [dataMan getSettings];
|
||||||
_oscEnabled = true;
|
_oscEnabled = true;
|
||||||
_gyroSensitivity = currentSettings.gyroSensitivity.floatValue;
|
_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, @"Number of supported controllers connected: %d", [ControllerSupport getGamepadCount]);
|
||||||
Log(LOG_I, @"Multi-controller: %d", _multiController);
|
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,
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
// because the connection has not been established yet.
|
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);
|
_captureMouse = (streamConfig.localMousePointerMode == 0);
|
||||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
for (GCMouse* mouse in [GCMouse mice]) {
|
for (GCMouse* mouse in [GCMouse mice]) {
|
||||||
@@ -1256,7 +1438,8 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller* limeController = [self assignController:controller];
|
//[self->_activeGCControllers addObject:controller];
|
||||||
|
VoidController* limeController = [self assignController:controller];
|
||||||
if (limeController) {
|
if (limeController) {
|
||||||
// Register callbacks on the new controller
|
// Register callbacks on the new controller
|
||||||
[self registerControllerCallbacks:controller];
|
[self registerControllerCallbacks:controller];
|
||||||
@@ -1265,12 +1448,12 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
[self reportControllerArrival:limeController];
|
[self reportControllerArrival:limeController];
|
||||||
|
|
||||||
// Re-evaluate the on-screen control mode
|
// Re-evaluate the on-screen control mode
|
||||||
[self updateAutoOnScreenControlMode];
|
//[self updateAutoOnScreenControlMode];
|
||||||
|
|
||||||
// Notify the delegate
|
// Notify the delegate
|
||||||
[self->_delegate gamepadPresenceChanged];
|
[self->_delegate gamepadPresenceChanged];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
_controllerDisconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
_controllerDisconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
Log(LOG_I, @"Controller disconnected!");
|
Log(LOG_I, @"Controller disconnected!");
|
||||||
@@ -1283,28 +1466,31 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
}
|
}
|
||||||
|
|
||||||
[self unregisterControllerCallbacks:controller];
|
[self unregisterControllerCallbacks:controller];
|
||||||
|
|
||||||
|
if([self->_activeGCControllers containsObject:controller]){
|
||||||
|
[self->_activeGCControllers removeObject:controller];
|
||||||
self->_controllerNumbers &= ~(1 << controller.playerIndex);
|
self->_controllerNumbers &= ~(1 << controller.playerIndex);
|
||||||
|
}
|
||||||
Log(LOG_I, @"Unassigning controller index: %ld", (long)controller.playerIndex);
|
Log(LOG_I, @"Unassigning controller index: %ld", (long)controller.playerIndex);
|
||||||
|
|
||||||
Controller* limeController = [self->_controllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
VoidController* voidController = [self->_voidControllers objectForKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
||||||
if (limeController) {
|
if (voidController) {
|
||||||
// Stop haptics on this controller
|
// Stop haptics on this controller
|
||||||
[self cleanupControllerHaptics:limeController];
|
[self cleanupControllerHaptics:voidController];
|
||||||
|
|
||||||
// Stop motion reports on this controller
|
// Stop motion reports on this controller
|
||||||
[self cleanupControllerMotion:limeController];
|
[self cleanupControllerMotion:voidController];
|
||||||
|
|
||||||
// Stop battery reports on this controller
|
// Stop battery reports on this controller
|
||||||
[self cleanupControllerBattery:limeController];
|
[self cleanupControllerBattery:voidController];
|
||||||
|
|
||||||
// Disassociate this controller from any controllers merged with it
|
// Disassociate this controller from any controllers merged with it
|
||||||
if (limeController.mergedWithController) {
|
if (voidController.mergedWithController) {
|
||||||
assert(limeController.mergedWithController.mergedWithController == limeController);
|
if(voidController.mergedWithController.mergedWithController == voidController) voidController.mergedWithController.mergedWithController = nil;
|
||||||
limeController.mergedWithController.mergedWithController = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inform the server of the updated active gamepads before removing this controller
|
// 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
|
// Re-evaluate the on-screen control mode
|
||||||
[self updateAutoOnScreenControlMode];
|
[self updateAutoOnScreenControlMode];
|
||||||
@@ -1315,6 +1501,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
if (@available(iOS 14.0, tvOS 14.0, *)) {
|
||||||
|
|
||||||
_mouseConnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
_mouseConnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
Log(LOG_I, @"Mouse connected!");
|
Log(LOG_I, @"Mouse connected!");
|
||||||
|
|
||||||
@@ -1355,51 +1542,67 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
// Re-evaluate the on-screen control mode
|
// Re-evaluate the on-screen control mode
|
||||||
[self updateAutoOnScreenControlMode];
|
[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];
|
||||||
|
|
||||||
for(Controller* controller in _controllers) [self updateTimerStateForController:controller];
|
|
||||||
if(_controllers.count == 0) [self updateTimerStateForController:_oscController];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
-(id)initWithConfig:(StreamConfiguration*)streamConfig delegate:(id<ControllerSupportDelegate>)delegate
|
|
||||||
{
|
|
||||||
self = [super init];
|
_oscController = [[VoidController alloc] init];
|
||||||
_delegate = delegate;
|
_gyroMode = AlwaysDevice;
|
||||||
_controllerStreamLock = [[NSLock alloc] init];
|
|
||||||
_controllers = [[NSMutableDictionary alloc] init];
|
[self updateCommonConfig:streamConfig];
|
||||||
_controllerNumbers = 0;
|
|
||||||
[self updateConfig:streamConfig delegate:delegate];
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) connectionEstablished{
|
-(void)connectionEstablished{
|
||||||
for (Controller* controller in [_controllers allValues]){
|
[self updateTimerStateForController:self->_oscController];
|
||||||
// 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 setButtonFlag:self->_oscController flags:A_FLAG];
|
[self setButtonFlag:self->_oscController flags:A_FLAG];
|
||||||
[self updateFinished:self->_oscController];
|
[self updateFinished:self->_oscController];
|
||||||
[self clearButtonFlag:self->_oscController flags:A_FLAG];
|
[self clearButtonFlag:self->_oscController flags:A_FLAG];
|
||||||
[self updateFinished:self->_oscController];
|
[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(), ^{
|
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 invalidate];
|
||||||
controller.accelTimer = nil;
|
controller.accelTimer = nil;
|
||||||
|
}
|
||||||
|
if(controller.hasGyroscope){
|
||||||
[controller.gyroTimer invalidate];
|
[controller.gyroTimer invalidate];
|
||||||
controller.gyroTimer = nil;
|
controller.gyroTimer = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) cleanup
|
-(void) cleanup
|
||||||
@@ -1420,13 +1623,14 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
|
|
||||||
_controllerNumbers = 0;
|
_controllerNumbers = 0;
|
||||||
|
|
||||||
for (Controller* controller in [_controllers allValues]) {
|
[self stopTimerForController:_oscController];
|
||||||
|
for (VoidController* controller in [_voidControllers allValues]) {
|
||||||
[self stopTimerForController:controller];
|
[self stopTimerForController:controller];
|
||||||
[self cleanupControllerHaptics:controller];
|
[self cleanupControllerHaptics:controller];
|
||||||
[self cleanupControllerMotion:controller];
|
[self cleanupControllerMotion:controller];
|
||||||
[self cleanupControllerBattery:controller];
|
[self cleanupControllerBattery:controller];
|
||||||
}
|
}
|
||||||
[_controllers removeAllObjects];
|
[_voidControllers removeAllObjects];
|
||||||
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
[self cleanupControllerMotion:_oscController];
|
[self cleanupControllerMotion:_oscController];
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#import "OnScreenControls.h"
|
#import "OnScreenControls.h"
|
||||||
#import "CustomTapGestureRecognizer.h"
|
#import "CustomTapGestureRecognizer.h"
|
||||||
#import "Controller.h"
|
#import "VoidController.h"
|
||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
#import <CoreMotion/CoreMotion.h>
|
#import <CoreMotion/CoreMotion.h>
|
||||||
@@ -70,7 +70,7 @@ static NSSet *validPositionButtonNames;
|
|||||||
BOOL _visible;
|
BOOL _visible;
|
||||||
|
|
||||||
ControllerSupport *_controllerSupport;
|
ControllerSupport *_controllerSupport;
|
||||||
Controller *_controller;
|
VoidController *_controller;
|
||||||
NSMutableArray* _deadTouches;
|
NSMutableArray* _deadTouches;
|
||||||
BOOL _swapABXY;
|
BOOL _swapABXY;
|
||||||
BOOL _largerStickLR1;
|
BOOL _largerStickLR1;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
@import CoreMotion;
|
@import CoreMotion;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@interface Controller : NSObject
|
@interface VoidController : NSObject
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float lastX;
|
float lastX;
|
||||||
@@ -64,11 +64,13 @@ typedef NS_ENUM(NSInteger, ControllerDeviceBatteryState) {
|
|||||||
@property (nonatomic) float lastBatteryLevel;
|
@property (nonatomic) float lastBatteryLevel;
|
||||||
|
|
||||||
@property (nonatomic) BOOL reportedArrival;
|
@property (nonatomic) BOOL reportedArrival;
|
||||||
@property (nonatomic) Controller* _Nullable mergedWithController;
|
@property (nonatomic) VoidController* _Nullable mergedWithController;
|
||||||
|
|
||||||
@property(nonatomic, strong) NSMutableSet* _Nullable motionTypes;
|
@property(nonatomic, strong) NSMutableSet* _Nullable motionTypes;
|
||||||
@property(nonatomic, assign) uint16_t reportRateHz;
|
@property(nonatomic, assign) uint16_t reportRateHz;
|
||||||
@property(nonatomic, assign) uint16_t controllerNumber;
|
@property(nonatomic, assign) uint16_t controllerNumber;
|
||||||
|
@property(nonatomic, assign) BOOL hasAccelerometer;
|
||||||
|
@property(nonatomic, assign) BOOL hasGyroscope;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
// Copyright © 2019 Moonlight Game Streaming Project. All rights reserved.
|
// Copyright © 2019 Moonlight Game Streaming Project. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Controller.h"
|
#include "VoidController.h"
|
||||||
|
|
||||||
@implementation Controller
|
@implementation VoidController
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -57,6 +57,7 @@
|
|||||||
StreamView *_streamView;
|
StreamView *_streamView;
|
||||||
UIScrollView *_scrollView;
|
UIScrollView *_scrollView;
|
||||||
BOOL _userIsInteracting;
|
BOOL _userIsInteracting;
|
||||||
|
bool viewJustLoaded;
|
||||||
CGSize _keyboardSize;
|
CGSize _keyboardSize;
|
||||||
UIWindow *_extWindow;
|
UIWindow *_extWindow;
|
||||||
UIView *_streamVideoRenderView;
|
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->_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
|
[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.
|
[_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
|
// we got self.view passed to streamView class as the topLayerView, will be useful in many cases
|
||||||
[self->_streamView reloadOnScreenControlsRealtimeWith:(ControllerSupport*)_controllerSupport
|
[self->_streamView reloadOnScreenControlsRealtimeWith:(ControllerSupport*)_controllerSupport
|
||||||
@@ -215,7 +219,7 @@
|
|||||||
NSLog(@"streamview gestures: %d", (uint32_t)[_streamView.gestureRecognizers count]);
|
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
|
[_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
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
|
viewJustLoaded = true;
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
|
||||||
[self.navigationController setNavigationBarHidden:YES animated:YES];
|
[self.navigationController setNavigationBarHidden:YES animated:YES];
|
||||||
|
|||||||
Reference in new issue
Block a user