feat: haptic engine selector
This commit is contained in:
@@ -1360,16 +1360,16 @@
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Oyk-L5-WTt" userLabel="singleTapSensitivityStack">
|
||||
<rect key="frame" x="440" y="307" width="408" height="55.5"/>
|
||||
<rect key="frame" x="440" y="307" width="432" height="55.5"/>
|
||||
<subviews>
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Tap Sensitivity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SuN-S2-8hj">
|
||||
<rect key="frame" x="0.0" y="0.0" width="408" height="20.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="432" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="2" minValue="0.0" maxValue="5" minimumValueImage="0.square" catalog="system" maximumValueImage="5.square" translatesAutoresizingMaskIntoConstraints="NO" id="j4n-De-TRX" userLabel="Single Tap Sensitivity Slider">
|
||||
<rect key="frame" x="-2" y="25.5" width="412" height="31"/>
|
||||
<rect key="frame" x="-2" y="25.5" width="436" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="qOF-42-hPO"/>
|
||||
</constraints>
|
||||
@@ -1379,6 +1379,32 @@
|
||||
<constraint firstAttribute="height" constant="55.5" id="ZRb-xy-1EW"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="MUp-Hc-VgH" userLabel="hapticEngineStack">
|
||||
<rect key="frame" x="440" y="850" width="380" height="56.5"/>
|
||||
<subviews>
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptic Engine" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YM8-us-6sh" userLabel="hapticEngine">
|
||||
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="MzN-ZR-qyM" userLabel="hapticEngineSelector">
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Auto"/>
|
||||
<segment title="Built-in"/>
|
||||
<segment title="L/R Swapped"/>
|
||||
<segment title="Disabled"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="selectedSegmentTintColor" systemColor="linkColor"/>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="56.5" id="V6b-dd-DZa"/>
|
||||
<constraint firstAttribute="width" constant="380" id="gbp-4g-Tcz"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
@@ -1422,6 +1448,8 @@
|
||||
<outlet property="gyroSensitivityStack" destination="T3L-Kz-2yA" id="iQS-ce-h0z"/>
|
||||
<outlet property="gyroToStickMinOffsetStack" destination="KRh-UP-TYS" id="loh-o6-s9D"/>
|
||||
<outlet property="gyroToStickSwitchStack" destination="8eE-nU-sk5" id="oZB-AM-iHM"/>
|
||||
<outlet property="hapticEngineSelector" destination="MzN-ZR-qyM" id="6EY-Ew-pqU"/>
|
||||
<outlet property="hapticEngineStack" destination="MUp-Hc-VgH" id="XuW-ww-cmv"/>
|
||||
<outlet property="hdrStack" destination="dH7-Sy-EdJ" id="cJm-bj-Aqo"/>
|
||||
<outlet property="hdrSwitch" destination="wIq-fF-X8l" id="Ozz-h0-nJL"/>
|
||||
<outlet property="liftStreamViewForKeyboardSelector" destination="MM5-O0-vK3" id="tSC-Rp-Qfg"/>
|
||||
@@ -2229,7 +2257,7 @@
|
||||
<image name="tray.full.fill" catalog="system" width="128" height="88"/>
|
||||
<image name="video.and.waveform" catalog="system" width="128" height="94"/>
|
||||
<systemColor name="linkColor">
|
||||
<color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="secondarySystemGroupedBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
@@ -2238,13 +2266,13 @@
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBrownColor">
|
||||
<color red="0.63529411759999999" green="0.51764705879999995" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.63529411764705879" green="0.51764705882352946" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemGray3Color">
|
||||
<color red="0.78039215689999997" green="0.78039215689999997" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.7803921568627451" green="0.7803921568627451" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemTealColor">
|
||||
<color red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.18823529411764706" green="0.69019607843137254" blue="0.7803921568627451" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -1704,16 +1704,16 @@
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="N0i-z6-WgC" userLabel="singleTapSensitivityStack">
|
||||
<rect key="frame" x="410" y="2455" width="392" height="55.5"/>
|
||||
<rect key="frame" x="410" y="2455" width="464" height="55.5"/>
|
||||
<subviews>
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Tap Sensitivity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WzD-wo-Wum">
|
||||
<rect key="frame" x="0.0" y="0.0" width="392" height="20.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="464" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<slider verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="2" minValue="0.0" maxValue="5" minimumValueImage="0.square" catalog="system" maximumValueImage="5.square" translatesAutoresizingMaskIntoConstraints="NO" id="uCa-Oa-7mv" userLabel="Single Tap Sensitivity Slider">
|
||||
<rect key="frame" x="-2" y="25.5" width="396" height="31"/>
|
||||
<rect key="frame" x="-2" y="25.5" width="468" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="XXP-GP-uhn"/>
|
||||
</constraints>
|
||||
@@ -2111,6 +2111,32 @@
|
||||
<constraint firstAttribute="height" constant="55.5" id="fI1-bQ-oWk"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="kiR-q0-FQX" userLabel="hapticEngineStack">
|
||||
<rect key="frame" x="437" y="2159" width="380" height="56.5"/>
|
||||
<subviews>
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptic Engine" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ldr-kv-d7n" userLabel="hapticEngine">
|
||||
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="nj6-9l-1j7" userLabel="hapticEngineSelector">
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Auto"/>
|
||||
<segment title="Built-in"/>
|
||||
<segment title="L/R Swapped"/>
|
||||
<segment title="Disabled"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="selectedSegmentTintColor" systemColor="linkColor"/>
|
||||
</segmentedControl>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="380" id="C6U-kW-OCn"/>
|
||||
<constraint firstAttribute="height" constant="56.5" id="P9y-0n-ygm"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
@@ -2155,6 +2181,8 @@
|
||||
<outlet property="gyroToStickMinOffsetSlider" destination="45X-gK-1ez" id="McO-cA-MQc"/>
|
||||
<outlet property="gyroToStickMinOffsetStack" destination="Orr-Nz-gJS" id="R0p-0J-nKz"/>
|
||||
<outlet property="gyroToStickSwitchStack" destination="xMx-7R-pmH" id="LbK-ie-Hsl"/>
|
||||
<outlet property="hapticEngineSelector" destination="nj6-9l-1j7" id="eqd-U9-j6U"/>
|
||||
<outlet property="hapticEngineStack" destination="kiR-q0-FQX" id="zj5-eD-N5a"/>
|
||||
<outlet property="hdrStack" destination="kFw-d7-BTn" id="3aT-Gh-bDO"/>
|
||||
<outlet property="hdrSwitch" destination="Kgb-YU-AFW" id="ksG-A4-HhS"/>
|
||||
<outlet property="liftStreamViewForKeyboardSelector" destination="TJx-6E-kgr" id="KnL-15-Q6G"/>
|
||||
|
||||
@@ -43,6 +43,13 @@ typedef NS_ENUM(NSInteger, GyroMode) {
|
||||
AlwaysController
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, HapticEnginePreference) {
|
||||
HapticEngineAuto,
|
||||
RumbleDevice,
|
||||
LeftRightSwapped,
|
||||
RumbleOff
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, FramePacingMode) {
|
||||
FramePacingModeOff,
|
||||
FramePacingModeLegacy,
|
||||
@@ -111,6 +118,7 @@ typedef NS_ENUM(NSInteger, WidgetSizeTransition) {
|
||||
sendDummyEvent:(BOOL)sendDummyEvent
|
||||
rememberFoldState:(BOOL)rememberFoldState
|
||||
singleTapSensitivy:(CGFloat)singleTapSensitivy
|
||||
hapticEngine:(NSInteger)hapticEngine
|
||||
backgroundSessionTimer:(NSInteger)backgroundSessionTimer;
|
||||
|
||||
- (NSArray*) getHosts;
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
sendDummyEvent:(BOOL)sendDummyEvent
|
||||
rememberFoldState:(BOOL)rememberFoldState
|
||||
singleTapSensitivy:(CGFloat)singleTapSensitivy
|
||||
hapticEngine:(NSInteger)hapticEngine
|
||||
backgroundSessionTimer:(NSInteger)backgroundSessionTimer{
|
||||
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
@@ -162,6 +163,7 @@
|
||||
settingsToSave.framePacingMode = [NSNumber numberWithInteger:framePacingMode];
|
||||
settingsToSave.sendDummyEvent = sendDummyEvent;
|
||||
settingsToSave.singleTapSensitivity = [NSNumber numberWithDouble:singleTapSensitivy];
|
||||
settingsToSave.hapticEngine = [NSNumber numberWithInteger:hapticEngine];
|
||||
settingsToSave.rememberFoldState = rememberFoldState;
|
||||
[self saveData];
|
||||
}];
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
@property (nonatomic) BOOL sendDummyEvent;
|
||||
@property (nonatomic) BOOL rememberFoldState;
|
||||
@property (nonatomic, retain) NSNumber * singleTapSensitivity;
|
||||
@property (nonatomic, retain) NSNumber * hapticEngine;
|
||||
@property (nonatomic, retain) NSNumber * framePacingMode;
|
||||
|
||||
- (id) initFromSettings:(Settings*)settings;
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
self.gyroBiasZ = settings.gyroBiasZ;
|
||||
self.singleTapSensitivity = settings.singleTapSensitivity;
|
||||
self.backgroundSessionTimer = settings.backroundSessionTimer;
|
||||
self.hapticEngine = settings.hapticEngine;
|
||||
#endif
|
||||
self.uniqueId = settings.uniqueId;
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
OnScreenControls *_osc;
|
||||
VoidController *_oscController;
|
||||
NSMutableSet* _activeGCControllers;
|
||||
TemporarySettings* tempSettings;
|
||||
|
||||
#define EMULATING_SELECT 0x1
|
||||
#define EMULATING_SPECIAL 0x2
|
||||
@@ -75,16 +76,40 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
-(void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor
|
||||
{
|
||||
VoidController* voidController = [_voidControllers objectForKey:[NSNumber numberWithInteger:controllerNumber]];
|
||||
|
||||
HapticEnginePreference preference = tempSettings.hapticEngine.intValue;
|
||||
|
||||
if (voidController == nil && controllerNumber == 0 && _oscEnabled) {
|
||||
// TODO: Rumble emulation for OSC
|
||||
// no physical controller connected:
|
||||
if(preference != RumbleOff){
|
||||
[_oscController.lowFreqMotor setMotorAmplitude:lowFreqMotor];
|
||||
[_oscController.highFreqMotor setMotorAmplitude:highFreqMotor];
|
||||
}
|
||||
}
|
||||
|
||||
if (voidController == nil) {
|
||||
// No connected controller for this player
|
||||
return;
|
||||
}
|
||||
|
||||
[voidController.lowFreqMotor setMotorAmplitude:lowFreqMotor];
|
||||
[voidController.highFreqMotor setMotorAmplitude:highFreqMotor];
|
||||
// physical controller connected:
|
||||
switch (preference) {
|
||||
case HapticEngineAuto:
|
||||
// if controller has no haptic profile, it already falled bakc to device engine
|
||||
[voidController.lowFreqMotor setMotorAmplitude:lowFreqMotor];
|
||||
[voidController.highFreqMotor setMotorAmplitude:highFreqMotor];
|
||||
break;
|
||||
case RumbleDevice:
|
||||
[_oscController.lowFreqMotor setMotorAmplitude:lowFreqMotor];
|
||||
[_oscController.highFreqMotor setMotorAmplitude:highFreqMotor];
|
||||
case LeftRightSwapped:
|
||||
[voidController.lowFreqMotor setMotorAmplitude:highFreqMotor];
|
||||
[voidController.highFreqMotor setMotorAmplitude:lowFreqMotor];
|
||||
case RumbleOff:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) rumbleTriggers:(uint16_t)controllerNumber leftTrigger:(uint16_t)leftTrigger rightTrigger:(uint16_t)rightTrigger
|
||||
@@ -1387,9 +1412,10 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
_oscController.playerIndex = 0;
|
||||
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
TemporarySettings* currentSettings = [dataMan getSettings];
|
||||
_oscEnabled = _oscEnabled || (OnScreenControlsLevel)[currentSettings.onscreenControls integerValue] != OnScreenControlsLevelOff || streamConfig.gyroMode != GyroModeOff;
|
||||
_gyroSensitivity = currentSettings.gyroSensitivity.floatValue;
|
||||
tempSettings = [dataMan getSettings];
|
||||
|
||||
_oscEnabled = _oscEnabled || (OnScreenControlsLevel)[tempSettings.onscreenControls integerValue] != OnScreenControlsLevelOff || streamConfig.gyroMode != GyroModeOff;
|
||||
_gyroSensitivity = tempSettings.gyroSensitivity.floatValue;
|
||||
}
|
||||
|
||||
- (void)resetGyroInputForController:(VoidController* )voidController{
|
||||
@@ -1435,7 +1461,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
self = [super init];
|
||||
|
||||
NSLog(@"controller support init");
|
||||
|
||||
|
||||
_delegate = delegate;
|
||||
_controllerStreamLock = [[NSLock alloc] init];
|
||||
_voidControllers = [[NSMutableDictionary alloc] init];
|
||||
@@ -1579,6 +1605,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
||||
|
||||
|
||||
_oscController = [[VoidController alloc] init];
|
||||
[self initializeControllerHaptics:_oscController];
|
||||
_gyroMode = AlwaysDevice;
|
||||
|
||||
[self updateCommonConfig:streamConfig];
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "HapticContext.h"
|
||||
#import "DataManager.h"
|
||||
|
||||
@import CoreHaptics;
|
||||
@import GameController;
|
||||
@@ -83,29 +84,66 @@
|
||||
}
|
||||
}
|
||||
|
||||
-(id) initDeviceEngineContextWithGamepad:(GCController*)gamepad API_AVAILABLE(ios(13.0), tvos(13.0)) {
|
||||
NSError *error = nil;
|
||||
_hapticEngine = [[CHHapticEngine alloc] initAndReturnError:&error];
|
||||
if (error != nil) {
|
||||
Log(LOG_W, @"Controller %d: iPhone Haptic engine failed to start: %@", gamepad.playerIndex, error);
|
||||
return nil;
|
||||
}
|
||||
_playerIndex = gamepad.playerIndex;
|
||||
|
||||
[_hapticEngine startAndReturnError:&error];
|
||||
if (error != nil) {
|
||||
Log(LOG_W, @"Controller %d: Haptic engine failed to start: %@", gamepad.playerIndex, error);
|
||||
return nil;
|
||||
}
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
_hapticEngine.stoppedHandler = ^(CHHapticEngineStoppedReason stoppedReason) {
|
||||
HapticContext* me = weakSelf;
|
||||
if (me == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log(LOG_W, @"Controller %d: Haptic engine stopped: %p", me->_playerIndex, stoppedReason);
|
||||
me->_hapticPlayer = nil;
|
||||
me->_hapticEngine = nil;
|
||||
me->_playing = NO;
|
||||
};
|
||||
_hapticEngine.resetHandler = ^{
|
||||
HapticContext* me = weakSelf;
|
||||
if (me == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log(LOG_W, @"Controller %d: Haptic engine reset", me->_playerIndex);
|
||||
me->_hapticPlayer = nil;
|
||||
me->_playing = NO;
|
||||
[me->_hapticEngine startAndReturnError:nil];
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(id) initWithGamepad:(GCController*)gamepad locality:(GCHapticsLocality)locality API_AVAILABLE(ios(14.0), tvos(14.0)) {
|
||||
bool needFallBackToPhoneHaptics = false;
|
||||
bool fallBackToPhoneHaptics = false;
|
||||
|
||||
if (gamepad.haptics == nil) {
|
||||
Log(LOG_W, @"Controller %d does not support haptics", gamepad.playerIndex);
|
||||
needFallBackToPhoneHaptics = true;
|
||||
fallBackToPhoneHaptics = true;
|
||||
}
|
||||
else if (![[gamepad.haptics supportedLocalities] containsObject:locality]) {
|
||||
Log(LOG_W, @"Controller %d does not support haptic locality: %@", gamepad.playerIndex, locality);
|
||||
needFallBackToPhoneHaptics = true;
|
||||
fallBackToPhoneHaptics = true;
|
||||
}
|
||||
|
||||
if (needFallBackToPhoneHaptics) {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
Log(LOG_W, @"Controller %d falls back to use iPhone Haptics for locality: %@", gamepad.playerIndex, locality);
|
||||
NSError *error = nil;
|
||||
_hapticEngine = [[CHHapticEngine alloc] initAndReturnError:&error];
|
||||
if (error != nil) {
|
||||
Log(LOG_W, @"Controller %d: iPhone Haptic engine failed to start: %@", gamepad.playerIndex, error);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
if (fallBackToPhoneHaptics) {
|
||||
Log(LOG_W, @"Controller %d falls back to use iPhone Haptics for locality: %@", gamepad.playerIndex, locality);
|
||||
NSError *error = nil;
|
||||
_hapticEngine = [[CHHapticEngine alloc] initAndReturnError:&error];
|
||||
if (error != nil) {
|
||||
Log(LOG_W, @"Controller %d: iPhone Haptic engine failed to start: %@", gamepad.playerIndex, error);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
@@ -154,7 +192,9 @@
|
||||
return [[HapticContext alloc] initWithGamepad:gamepad locality:GCHapticsLocalityRightHandle];
|
||||
}
|
||||
else {
|
||||
return nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [[HapticContext alloc] initDeviceEngineContextWithGamepad:gamepad];
|
||||
} else return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +203,9 @@
|
||||
return [[HapticContext alloc] initWithGamepad:gamepad locality:GCHapticsLocalityLeftHandle];
|
||||
}
|
||||
else {
|
||||
return nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [[HapticContext alloc] initDeviceEngineContextWithGamepad:gamepad];
|
||||
} else return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +214,9 @@
|
||||
return [[HapticContext alloc] initWithGamepad:gamepad locality:GCHapticsLocalityLeftTrigger];
|
||||
}
|
||||
else {
|
||||
return nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [[HapticContext alloc] initDeviceEngineContextWithGamepad:gamepad];
|
||||
} else return nil;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +225,9 @@
|
||||
return [[HapticContext alloc] initWithGamepad:gamepad locality:GCHapticsLocalityRightTrigger];
|
||||
}
|
||||
else {
|
||||
return nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [[HapticContext alloc] initDeviceEngineContextWithGamepad:gamepad];
|
||||
} else return nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<attribute name="gyroBiasZ" optional="YES" attributeType="Double" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="gyroMode" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="gyroSensitivity" optional="YES" attributeType="Float" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="hapticEngine" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="height" attributeType="Integer 32" defaultValueString="720" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="keyboardToggleFingers" optional="YES" attributeType="Integer 16" defaultValueString="3" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="liftStreamViewForKeyboard" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
|
||||
|
||||
@@ -324,8 +324,8 @@ static BOOL overridePersistedFoldState = YES;
|
||||
|
||||
- (void)toggleFold {
|
||||
self.isExpanded = !_expandable ? false : !self.isExpanded;
|
||||
[self updateViewForFoldState];
|
||||
if(!_expandable) self.lockedSectionHandler();
|
||||
[self updateViewForFoldState];
|
||||
[[NSUserDefaults standardUserDefaults] setBool:self.isExpanded forKey:self.identifier];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
@@ -169,6 +169,9 @@
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *singleTapSensitivityStack;
|
||||
@property (strong, nonatomic) IBOutlet UISlider *singleTapSensitivitySlider;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *hapticEngineStack;
|
||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *hapticEngineSelector;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *testStack;
|
||||
|
||||
@property (nonatomic, strong) MicHandler *micHandler;
|
||||
|
||||
@@ -700,6 +700,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[self addSetting:self.onScreenWidgetStack ofId:@"onScreenWidgetStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection];
|
||||
[self addSetting:self.buttonVisualFeedbackStack ofId:@"buttonVisualFeedbackStack" withInfoTag:NO withDynamicLabel:NO to:touchAndControlSection];
|
||||
[self addSetting:self.swapAbxyStack ofId:@"swapAbaxyStack" withInfoTag:NO withDynamicLabel:NO to:touchAndControlSection];
|
||||
[self addSetting:self.hapticEngineStack ofId:@"hapticEngineStack" withInfoTag:NO withDynamicLabel:NO to:touchAndControlSection];
|
||||
[self addSetting:self.emulatedControllerTypeStack ofId:@"emulatedControllerTypeStack" withInfoTag:YES withDynamicLabel:NO to:touchAndControlSection];
|
||||
[self addSetting:self.gyroModeStack ofId:@"gyroModeStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection];
|
||||
[self addSetting:self.gyroSensitivityStack ofId:@"gyroSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection];
|
||||
@@ -1648,6 +1649,18 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[self.multiControllerSwitch setOn:self->tempSettings.multiController];
|
||||
[self.swapAbxySwitch setOn:self->tempSettings.swapABXYButtons];
|
||||
[self.buttonVisualFeedbackSwitch setOn:self->tempSettings.buttonVisualFeedback];
|
||||
|
||||
[self.hapticEngineSelector setSelectedSegmentIndex:self->tempSettings.hapticEngine.intValue];
|
||||
bool hideHapticEngineStack = false;
|
||||
if(@available(iOS 13.0, tvOS 13.0, *)) hideHapticEngineStack = false;
|
||||
else hideHapticEngineStack = true;
|
||||
[self setHidden:hideHapticEngineStack forStack:self.hapticEngineStack];
|
||||
bool disableControllerRumble = false;
|
||||
if(@available(iOS 14.0, tvOS 14.0, *)) nil;
|
||||
else disableControllerRumble = true;
|
||||
[self.hapticEngineSelector setEnabled:!disableControllerRumble forSegmentAtIndex:LeftRightSwapped];
|
||||
[self.hapticEngineSelector setEnabled:!disableControllerRumble forSegmentAtIndex:HapticEngineAuto];
|
||||
[self.hapticEngineSelector setEnabled:[self isIPhone] forSegmentAtIndex:RumbleDevice];
|
||||
|
||||
[self.gyroModeSelector setSelectedSegmentIndex:self->tempSettings.gyroMode.intValue];
|
||||
[self.gyroSensitivitySlider setValue: (uint16_t)(self->tempSettings.gyroSensitivity.floatValue * 100) animated:NO]; // Load old setting.
|
||||
@@ -1838,6 +1851,10 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
completion:^{
|
||||
if(!CountdownAlertController.actionCancelled){
|
||||
[weakSelf.onScreenWidgetSelector setSelectedSegmentIndex:OnScreenControlsLevelCustom];
|
||||
if(weakSelf.touchModeSelector.selectedSegmentIndex == NativeTouch){
|
||||
[weakSelf.enableOswForNativeTouchSwitch setOn:true];
|
||||
[weakSelf enableOswForNativeTouchSwitchFlipped:weakSelf.enableOswForNativeTouchSwitch];
|
||||
}
|
||||
__strong typeof(weakSelf) strongSelf = weakSelf;
|
||||
if (!strongSelf) return;
|
||||
strongSelf->motionControlSection.expandable = true;
|
||||
@@ -2792,6 +2809,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
BOOL sendDummyEvent = self.sendDummyEventSwitch.isOn;
|
||||
BOOL rememberFoldState = self.rememberFoldStateSwitch.isOn;
|
||||
CGFloat singleTapSensitivity = self.singleTapSensitivitySlider.value;
|
||||
NSInteger hapticEngine = self.hapticEngineSelector.selectedSegmentIndex;
|
||||
NSInteger backgroundSessionTimer = self.backgroundSessionTimerSlider.value == self.backgroundSessionTimerSlider.maximumValue ? (uint32_t) INT16_MAX : (uint32_t)self.backgroundSessionTimerSlider.value;
|
||||
|
||||
[dataMan saveSettingsWithBitrate:_bitrate
|
||||
@@ -2844,6 +2862,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
sendDummyEvent:sendDummyEvent
|
||||
rememberFoldState:rememberFoldState
|
||||
singleTapSensitivy:singleTapSensitivity
|
||||
hapticEngine:hapticEngine
|
||||
backgroundSessionTimer:backgroundSessionTimer];
|
||||
}
|
||||
|
||||
|
||||
@@ -3145,6 +3145,126 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"MzN-ZR-qyM.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; MzN-ZR-qyM.segmentTitles[0] = \"Auto\"; ObjectID = \"MzN-ZR-qyM\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Auto"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "自动"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "自動"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "自動"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MzN-ZR-qyM.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; MzN-ZR-qyM.segmentTitles[1] = \"Built-in\"; ObjectID = \"MzN-ZR-qyM\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Built-in"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "内置"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "内建"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "内建"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MzN-ZR-qyM.segmentTitles[2]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; MzN-ZR-qyM.segmentTitles[2] = \"L/R Swapped\"; ObjectID = \"MzN-ZR-qyM\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "L/R Swapped"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "左右交换"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "左右交換"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "左右交換"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MzN-ZR-qyM.segmentTitles[3]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; MzN-ZR-qyM.segmentTitles[3] = \"Disabled\"; ObjectID = \"MzN-ZR-qyM\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Disabled"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "关闭"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "關閉"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "關閉"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nh6-cn-z23.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Toggle Local Soft Keyboard\"; ObjectID = \"nh6-cn-z23\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -4201,6 +4321,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"YM8-us-6sh.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Haptic Engine\"; ObjectID = \"YM8-us-6sh\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Haptic Engine"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "振动引擎"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "振動引擎"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "振動引擎"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yY7-Sf-Zes.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; yY7-Sf-Zes.segmentTitles[0] = \"Slide From Left Edge\"; ObjectID = \"yY7-Sf-Zes\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
|
||||
@@ -2299,6 +2299,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Ldr-kv-d7n.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Haptic Engine\"; ObjectID = \"Ldr-kv-d7n\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Haptic Engine"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "振动引擎"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "振動引擎"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "振動引擎"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"LVq-7c-3zg.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Performance Graph \"; ObjectID = \"LVq-7c-3zg\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
@@ -2521,6 +2551,126 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"nj6-9l-1j7.segmentTitles[0]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; nj6-9l-1j7.segmentTitles[0] = \"Auto\"; ObjectID = \"nj6-9l-1j7\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Auto"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "自动"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "自動"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "自動"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nj6-9l-1j7.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; nj6-9l-1j7.segmentTitles[1] = \"Built-in\"; ObjectID = \"nj6-9l-1j7\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Built-in"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "内置"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "内建"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "内建"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nj6-9l-1j7.segmentTitles[2]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; nj6-9l-1j7.segmentTitles[2] = \"L/R Swapped\"; ObjectID = \"nj6-9l-1j7\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "L/R Swapped"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "左右交换"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "左右交換"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "左右交換"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nj6-9l-1j7.segmentTitles[3]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; nj6-9l-1j7.segmentTitles[3] = \"Disabled\"; ObjectID = \"nj6-9l-1j7\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Disabled"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "关闭"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "關閉"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "關閉"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NVL-ZX-kMQ.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Soft Keyboard Toolbar\"; ObjectID = \"NVL-ZX-kMQ\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
|
||||
Reference in New Issue
Block a user