feat: motion control - direct mapping from gyro to mouse or controller sticks, with on-screen button "gyro" for toggling
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#import "ThemeManager.h"
|
||||
#import "Connection.h"
|
||||
#import "Plot.h"
|
||||
#import "OSCProfilesManager.h"
|
||||
|
||||
#import <UIKit/UIGestureRecognizerSubclass.h>
|
||||
#import <VideoToolbox/VideoToolbox.h>
|
||||
@@ -24,6 +25,8 @@
|
||||
@implementation SettingsViewController {
|
||||
TemporarySettings* tempSettings;
|
||||
DataManager* dataMan;
|
||||
OSCProfilesManager* oscProfileMan;
|
||||
OSCProfile* oscProfile;
|
||||
|
||||
NSLayoutConstraint *parentStackLeadingConstraint;
|
||||
NSLayoutConstraint *parentStackWidthConstraint;
|
||||
@@ -43,6 +46,7 @@
|
||||
CGFloat _scrollSpeed;
|
||||
CGFloat _currentRefreshRate;
|
||||
MenuSectionView *touchAndControlSection;
|
||||
MenuSectionView *motionControlSection;
|
||||
MenuSectionView *videoSection;
|
||||
MenuSectionView *otherSection;
|
||||
MenuSectionView *experimentalSection;
|
||||
@@ -342,6 +346,47 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
NSLog(@"Mic error: %@", error);
|
||||
}
|
||||
|
||||
- (void)reloadMotionControlConfigs{
|
||||
oscProfile = [oscProfileMan getSelectedProfile];
|
||||
[self.mapGyroToSelector setSelectedSegmentIndex:oscProfile.mapGyroTo];
|
||||
[self mapGyroToChanged:self.mapGyroToSelector];
|
||||
if(self.mapGyroToSelector.selectedSegmentIndex == mapGyroToControllerStick){
|
||||
[self.yawPitchToRightStickSwitch setOn:oscProfile.yawPitchToRightStick];
|
||||
[self yawPitchToRightStickSwitchFlipped:self.yawPitchToRightStickSwitch];
|
||||
[self.rollToLeftStickSwitch setOn:oscProfile.rollToLeftStick];
|
||||
[self rollToLeftStickSwitchFlipped:self.rollToLeftStickSwitch];
|
||||
}
|
||||
[self.yawSensitivitySlider setValue:[self map_SliderValue_fromVelocFactor:oscProfile.gyroSensitivityYaw]];
|
||||
[self yawSensitivitySliderMoved:self.yawSensitivitySlider];
|
||||
[self.pitchSensitivitySlider setValue:[self map_SliderValue_fromVelocFactor:oscProfile.gyroSensitivityPitch]];
|
||||
[self pitchSensitivitySliderMoved:self.pitchSensitivitySlider];
|
||||
[self.rollSensitivitySlider setValue:[self map_SliderValue_fromVelocFactor:oscProfile.gyroSensitivityRoll]];
|
||||
[self rollSensitivitySliderMoved:self.rollSensitivitySlider];
|
||||
}
|
||||
|
||||
- (void)saveMotionControlConfigs{
|
||||
|
||||
CGFloat yawSensitivityPercent = [self map_velocFactorDisplay_fromSliderValue:self.yawSensitivitySlider.value];
|
||||
CGFloat pitchSensitivityPercent = [self map_velocFactorDisplay_fromSliderValue:self.pitchSensitivitySlider.value];
|
||||
CGFloat rollSensitivityPercent = [self map_velocFactorDisplay_fromSliderValue:self.rollSensitivitySlider.value];
|
||||
|
||||
bool configNotChanged = (oscProfile.mapGyroTo == self.mapGyroToSelector.selectedSegmentIndex
|
||||
&& oscProfile.yawPitchToRightStick == self.yawPitchToRightStickSwitch.isOn
|
||||
&& oscProfile.rollToLeftStick == self.rollToLeftStickSwitch.isOn
|
||||
&& (int16_t)(oscProfile.gyroSensitivityYaw*100) == (int16_t)yawSensitivityPercent
|
||||
&& (int16_t)(oscProfile.gyroSensitivityPitch*100) == (int16_t)pitchSensitivityPercent
|
||||
&& (int16_t)(oscProfile.gyroSensitivityRoll*100) == (int16_t)rollSensitivityPercent);
|
||||
if(!configNotChanged){
|
||||
oscProfile.mapGyroTo = self.mapGyroToSelector.selectedSegmentIndex;
|
||||
oscProfile.yawPitchToRightStick = self.yawPitchToRightStickSwitch.isOn;
|
||||
oscProfile.rollToLeftStick = self.rollToLeftStickSwitch.isOn;
|
||||
oscProfile.gyroSensitivityYaw = yawSensitivityPercent/100;
|
||||
oscProfile.gyroSensitivityPitch = pitchSensitivityPercent/100;
|
||||
oscProfile.gyroSensitivityRoll = rollSensitivityPercent/100;
|
||||
[oscProfileMan replaceSelectedProfileWith:oscProfile overwriteDefault:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated{
|
||||
[super viewWillAppear:NO];
|
||||
|
||||
@@ -350,7 +395,6 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
self.micHandler = [MicHandler new];
|
||||
[self.micHandler startTapping];
|
||||
*/
|
||||
|
||||
|
||||
[self updateParentStackHorizontalConstraints];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
@@ -362,6 +406,11 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
selector:@selector(updateTheme)
|
||||
name:ThemeDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(reloadMotionControlConfigs)
|
||||
name:@"OscLayoutCloseNotification"
|
||||
object:nil];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||
if(self.mainFrameViewController.settingsExpandedInStreamView){
|
||||
@@ -383,6 +432,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
if(![self manuallyChangedFPS]) [self framerateChanged];
|
||||
|
||||
[self reloadMotionControlConfigs];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated{
|
||||
@@ -390,10 +441,10 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[self updateResolutionTable];
|
||||
[self.customResolutionSwitch addTarget:self action:@selector(customResolutionSwitched:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
tempSettings = [dataMan getSettings];
|
||||
|
||||
self->tempSettings = [self->dataMan getSettings];
|
||||
|
||||
//CGSize currentResolution = CGSizeMake(currentSettings.width.intValue, currentSettings.height.intValue);
|
||||
[self.customResolutionSwitch setOn: isCustomResolution(tempSettings.resolutionSelected.intValue)];
|
||||
[self.customResolutionSwitch setOn: isCustomResolution(self->tempSettings.resolutionSelected.intValue)];
|
||||
[self.resolutionSelector setEnabled:!self.customResolutionSwitch.isOn];
|
||||
}
|
||||
|
||||
@@ -648,6 +699,22 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[self addSetting:self.gyroSensitivityStack ofId:@"gyroSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection];
|
||||
[touchAndControlSection addToParentStack:_parentStack];
|
||||
// [touchAndControlSection setExpanded:NO];
|
||||
|
||||
motionControlSection = [[MenuSectionView alloc] init];
|
||||
motionControlSection.delegate = self;
|
||||
motionControlSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Motion Control"];
|
||||
motionControlSection.identifier = @"SettingsSectionMotionControl";
|
||||
if (@available(iOS 13.0, *)) {
|
||||
// [motionControlSection setSectionWithIcon:[UIImage imageNamed:@"gyroscope"] andSize:23];
|
||||
[motionControlSection setSectionWithIcon:[UIImage imageNamed:@"gyroscope"] andSize:23];
|
||||
}
|
||||
[self addSetting:self.mapGyroToStack ofId:@"mapGyroToStack" withInfoTag:NO withDynamicLabel:NO to:motionControlSection];
|
||||
[self addSetting:self.gyroToStickSwitchStack ofId:@"gyroToStickStack" withInfoTag:NO withDynamicLabel:NO to:motionControlSection];
|
||||
[self addSetting:self.yawPitchSensitivityStack ofId:@"yawPitchSensitivityStack" withInfoTag:NO withDynamicLabel:NO to:motionControlSection];
|
||||
[self addDynamicLabelForStack:self.yawSensitivityStack];
|
||||
[self addDynamicLabelForStack:self.pitchSensitivityStack];
|
||||
[self addSetting:self.rollSensitivityStack ofId:@"rollSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:motionControlSection];
|
||||
[motionControlSection addToParentStack:_parentStack];
|
||||
|
||||
MenuSectionView *gesturesSection = [[MenuSectionView alloc] init];
|
||||
gesturesSection.delegate = self;
|
||||
@@ -1399,347 +1466,387 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
settingStackWillBeRelocatedToLowestPosition = false;
|
||||
hiddenStacks = [[NSMutableSet alloc] init];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"_UIConstraintBasedLayoutLogUnsatisfiable"];
|
||||
|
||||
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
|
||||
[self.view addGestureRecognizer:longPress];
|
||||
|
||||
_settingStackDict = [[NSMutableDictionary alloc] init];
|
||||
|
||||
|
||||
for(UIView* view in self.view.subviews){
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
|
||||
[self initParentStack];
|
||||
[UIView animateWithDuration:0 animations:^{
|
||||
|
||||
// load rememberFoldState before section layout
|
||||
dataMan = [[DataManager alloc] init];
|
||||
tempSettings = [dataMan getSettings];
|
||||
[self.rememberFoldStateSwitch setOn:tempSettings.rememberFoldState];// Load old setting
|
||||
MenuSectionView.overridePersistedFoldState = !tempSettings.rememberFoldState;
|
||||
[self.rememberFoldStateSwitch addTarget:self action:@selector(rememberFoldStateSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
[self layoutSections];
|
||||
self->oscProfileMan = [OSCProfilesManager sharedManager:CGRectZero];
|
||||
|
||||
self->settingStackWillBeRelocatedToLowestPosition = false;
|
||||
self->hiddenStacks = [[NSMutableSet alloc] init];
|
||||
|
||||
// [self swi];
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"_UIConstraintBasedLayoutLogUnsatisfiable"];
|
||||
|
||||
self->slideToCloseSettingsViewRecognizer = [[CustomEdgeSlideGestureRecognizer alloc] initWithTarget:self action:@selector(edgeSwiped)];
|
||||
slideToCloseSettingsViewRecognizer.edges = UIRectEdgeLeft;
|
||||
slideToCloseSettingsViewRecognizer.normalizedThresholdDistance = 0.0;
|
||||
slideToCloseSettingsViewRecognizer.EDGE_TOLERANCE = 10;
|
||||
slideToCloseSettingsViewRecognizer.immediateTriggering = true;
|
||||
slideToCloseSettingsViewRecognizer.delaysTouchesBegan = NO;
|
||||
slideToCloseSettingsViewRecognizer.delaysTouchesEnded = NO;
|
||||
[self.view addGestureRecognizer:slideToCloseSettingsViewRecognizer];
|
||||
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
|
||||
[self.view addGestureRecognizer:longPress];
|
||||
|
||||
settingsViewJustLoaded = true;
|
||||
self->_settingStackDict = [[NSMutableDictionary alloc] init];
|
||||
|
||||
// Always run settings in dark mode because we want the light fonts
|
||||
if (@available(iOS 13.0, tvOS 13.0, *)) {
|
||||
self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
|
||||
}
|
||||
|
||||
|
||||
currentSettingsMenuMode = tempSettings.settingsMenuMode.intValue;
|
||||
[self loadFavoriteSettingStackIdentifiers];
|
||||
if(tempSettings.settingsMenuMode.intValue == FavoriteSettings) [self switchToFavoriteSettings];
|
||||
|
||||
// Ensure we pick a bitrate that falls exactly onto a slider notch
|
||||
_bitrate = bitrateTable[[self getSliderValueForBitrate:[tempSettings.bitrate intValue]]];
|
||||
|
||||
// Get the size of the screen with and without safe area insets
|
||||
// UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
|
||||
// CGFloat screenScale = window.screen.scale;
|
||||
// CGFloat safeAreaWidth = (window.frame.size.width - window.safeAreaInsets.left - window.safeAreaInsets.right) * screenScale;
|
||||
// CGFloat fullScreenWidth = window.frame.size.width * screenScale;
|
||||
// CGFloat fullScreenHeight = window.frame.size.height * screenScale;
|
||||
|
||||
[self.resolutionSelector removeSegmentAtIndex:0 animated:NO]; // remove 360p
|
||||
[self.resolutionSelector removeSegmentAtIndex:5 animated:NO]; // remove custom segment
|
||||
// iOS12 compatibility:
|
||||
self.resolutionSelector.selectedSegmentIndex = 3;
|
||||
[self.resolutionSelector setNeedsLayout];
|
||||
|
||||
resolutionTable[5] = CGSizeMake([tempSettings.width integerValue], [tempSettings.height integerValue]); // custom initial value
|
||||
[self updateResolutionTable];
|
||||
|
||||
|
||||
NSInteger framerate;
|
||||
switch ([tempSettings.framerate integerValue]) {
|
||||
case 30:
|
||||
framerate = 0;
|
||||
break;
|
||||
default:
|
||||
case 60:
|
||||
framerate = 1;
|
||||
break;
|
||||
case 120:
|
||||
framerate = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
NSInteger resolution = tempSettings.resolutionSelected.integerValue;
|
||||
if(resolution >= RESOLUTION_TABLE_SIZE){
|
||||
resolution = 0;
|
||||
}
|
||||
|
||||
// Only show the 120 FPS option if we have a > 60-ish Hz display
|
||||
bool enable120Fps = false;
|
||||
if (@available(iOS 10.3, tvOS 10.3, *)) {
|
||||
if ([UIScreen mainScreen].maximumFramesPerSecond > 62) {
|
||||
enable120Fps = true;
|
||||
|
||||
for(UIView* view in self.view.subviews){
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
}
|
||||
if (!enable120Fps) {
|
||||
[self.framerateSelector removeSegmentAtIndex:2 animated:NO];
|
||||
}
|
||||
|
||||
// Disable codec selector segments for unsupported codecs
|
||||
#if defined(__IPHONE_16_0) || defined(__TVOS_16_0)
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1))
|
||||
#endif
|
||||
{
|
||||
[self.codecSelector removeSegmentAtIndex:2 animated:NO];
|
||||
}
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
|
||||
[self.codecSelector removeSegmentAtIndex:1 animated:NO];
|
||||
|
||||
// Only enable the 4K option for "recent" devices. We'll judge that by whether
|
||||
// they support HEVC decoding (A9 or later).
|
||||
[self.resolutionSelector setEnabled:NO forSegmentAtIndex:2];
|
||||
}
|
||||
switch (tempSettings.preferredCodec) {
|
||||
case CODEC_PREF_AUTO:
|
||||
[self.codecSelector setSelectedSegmentIndex:self.codecSelector.numberOfSegments - 1];
|
||||
break;
|
||||
[self initParentStack];
|
||||
|
||||
// load rememberFoldState before section layout
|
||||
self->dataMan = [[DataManager alloc] init];
|
||||
self->tempSettings = [self->dataMan getSettings];
|
||||
[self.rememberFoldStateSwitch setOn:self->tempSettings.rememberFoldState];// Load old setting
|
||||
MenuSectionView.overridePersistedFoldState = !self->tempSettings.rememberFoldState;
|
||||
[self.rememberFoldStateSwitch addTarget:self action:@selector(rememberFoldStateSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
[self layoutSections];
|
||||
|
||||
|
||||
// [self swi];
|
||||
|
||||
self->slideToCloseSettingsViewRecognizer = [[CustomEdgeSlideGestureRecognizer alloc] initWithTarget:self action:@selector(edgeSwiped)];
|
||||
self->slideToCloseSettingsViewRecognizer.edges = UIRectEdgeLeft;
|
||||
self->slideToCloseSettingsViewRecognizer.normalizedThresholdDistance = 0.0;
|
||||
self->slideToCloseSettingsViewRecognizer.EDGE_TOLERANCE = 10;
|
||||
self->slideToCloseSettingsViewRecognizer.immediateTriggering = true;
|
||||
self->slideToCloseSettingsViewRecognizer.delaysTouchesBegan = NO;
|
||||
self->slideToCloseSettingsViewRecognizer.delaysTouchesEnded = NO;
|
||||
[self.view addGestureRecognizer:self->slideToCloseSettingsViewRecognizer];
|
||||
|
||||
self->settingsViewJustLoaded = true;
|
||||
|
||||
// Always run settings in dark mode because we want the light fonts
|
||||
if (@available(iOS 13.0, tvOS 13.0, *)) {
|
||||
self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
|
||||
}
|
||||
|
||||
|
||||
self->currentSettingsMenuMode = self->tempSettings.settingsMenuMode.intValue;
|
||||
[self loadFavoriteSettingStackIdentifiers];
|
||||
if(self->tempSettings.settingsMenuMode.intValue == FavoriteSettings) [self switchToFavoriteSettings];
|
||||
|
||||
// Ensure we pick a bitrate that falls exactly onto a slider notch
|
||||
self->_bitrate = bitrateTable[[self getSliderValueForBitrate:[self->tempSettings.bitrate intValue]]];
|
||||
|
||||
// Get the size of the screen with and without safe area insets
|
||||
// UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
|
||||
// CGFloat screenScale = window.screen.scale;
|
||||
// CGFloat safeAreaWidth = (window.frame.size.width - window.safeAreaInsets.left - window.safeAreaInsets.right) * screenScale;
|
||||
// CGFloat fullScreenWidth = window.frame.size.width * screenScale;
|
||||
// CGFloat fullScreenHeight = window.frame.size.height * screenScale;
|
||||
|
||||
[self.resolutionSelector removeSegmentAtIndex:0 animated:NO]; // remove 360p
|
||||
[self.resolutionSelector removeSegmentAtIndex:5 animated:NO]; // remove custom segment
|
||||
// iOS12 compatibility:
|
||||
self.resolutionSelector.selectedSegmentIndex = 3;
|
||||
[self.resolutionSelector setNeedsLayout];
|
||||
|
||||
resolutionTable[5] = CGSizeMake([self->tempSettings.width integerValue], [self->tempSettings.height integerValue]); // custom initial value
|
||||
[self updateResolutionTable];
|
||||
|
||||
|
||||
NSInteger framerate;
|
||||
switch ([self->tempSettings.framerate integerValue]) {
|
||||
case 30:
|
||||
framerate = 0;
|
||||
break;
|
||||
default:
|
||||
case 60:
|
||||
framerate = 1;
|
||||
break;
|
||||
case 120:
|
||||
framerate = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
NSInteger resolution = self->tempSettings.resolutionSelected.integerValue;
|
||||
if(resolution >= RESOLUTION_TABLE_SIZE){
|
||||
resolution = 0;
|
||||
}
|
||||
|
||||
// Only show the 120 FPS option if we have a > 60-ish Hz display
|
||||
bool enable120Fps = false;
|
||||
if (@available(iOS 10.3, tvOS 10.3, *)) {
|
||||
if ([UIScreen mainScreen].maximumFramesPerSecond > 62) {
|
||||
enable120Fps = true;
|
||||
}
|
||||
}
|
||||
if (!enable120Fps) {
|
||||
[self.framerateSelector removeSegmentAtIndex:2 animated:NO];
|
||||
}
|
||||
|
||||
[UIView animateWithDuration:0 animations:^{
|
||||
// Disable codec selector segments for unsupported codecs
|
||||
#if defined(__IPHONE_16_0) || defined(__TVOS_16_0)
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_AV1))
|
||||
#endif
|
||||
{
|
||||
[self.codecSelector removeSegmentAtIndex:2 animated:NO];
|
||||
}
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC)) {
|
||||
[self.codecSelector removeSegmentAtIndex:1 animated:NO];
|
||||
|
||||
// Only enable the 4K option for "recent" devices. We'll judge that by whether
|
||||
// they support HEVC decoding (A9 or later).
|
||||
[self.resolutionSelector setEnabled:NO forSegmentAtIndex:2];
|
||||
}
|
||||
|
||||
case CODEC_PREF_AV1:
|
||||
[self.codecSelector setSelectedSegmentIndex:2];
|
||||
break;
|
||||
|
||||
case CODEC_PREF_HEVC:
|
||||
[self.codecSelector setSelectedSegmentIndex:1];
|
||||
break;
|
||||
|
||||
case CODEC_PREF_H264:
|
||||
[self.codecSelector setSelectedSegmentIndex:0];
|
||||
break;
|
||||
}
|
||||
switch (self->tempSettings.preferredCodec) {
|
||||
case CODEC_PREF_AUTO:
|
||||
[self.codecSelector setSelectedSegmentIndex:self.codecSelector.numberOfSegments - 1];
|
||||
break;
|
||||
|
||||
case CODEC_PREF_AV1:
|
||||
[self.codecSelector setSelectedSegmentIndex:2];
|
||||
break;
|
||||
|
||||
case CODEC_PREF_HEVC:
|
||||
[self.codecSelector setSelectedSegmentIndex:1];
|
||||
break;
|
||||
|
||||
case CODEC_PREF_H264:
|
||||
[self.codecSelector setSelectedSegmentIndex:0];
|
||||
break;
|
||||
}
|
||||
}];
|
||||
|
||||
if (![self hdrSupported]) {
|
||||
[self.hdrSwitch setOn:NO];
|
||||
[self.hdrSwitch setEnabled:NO];
|
||||
}
|
||||
else {
|
||||
[self.hdrSwitch setOn:tempSettings.enableHdr];
|
||||
}
|
||||
if (![self hdrSupported]) {
|
||||
[self.hdrSwitch setOn:NO];
|
||||
[self.hdrSwitch setEnabled:NO];
|
||||
}
|
||||
else {
|
||||
[self.hdrSwitch setOn:self->tempSettings.enableHdr];
|
||||
}
|
||||
|
||||
[self.yuv444Switch setOn:tempSettings.enableYUV444];
|
||||
|
||||
[self.pipSwitch setOn:tempSettings.enablePIP];
|
||||
if(@available(iOS 15.0, *)) [self.pipSwitch setEnabled:true];
|
||||
else{
|
||||
[self.pipSwitch setOn:false];
|
||||
[self.pipSwitch setEnabled:false];
|
||||
}
|
||||
|
||||
[self.statsOverlaySelector setSelectedSegmentIndex:tempSettings.statsOverlayLevel.intValue];
|
||||
[self.yuv444Switch setOn:self->tempSettings.enableYUV444];
|
||||
|
||||
[self.pipSwitch setOn:self->tempSettings.enablePIP];
|
||||
if(@available(iOS 15.0, *)) [self.pipSwitch setEnabled:true];
|
||||
else{
|
||||
[self.pipSwitch setOn:false];
|
||||
[self.pipSwitch setEnabled:false];
|
||||
}
|
||||
|
||||
[self.statsOverlaySelector setSelectedSegmentIndex:self->tempSettings.statsOverlayLevel.intValue];
|
||||
|
||||
NSInteger renderingBackend = [tempSettings.renderingBackend integerValue];
|
||||
[self.renderingBackendSelector setSelectedSegmentIndex:renderingBackend];
|
||||
[self.renderingBackendSelector addTarget:self action:@selector(renderingBackendChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
NSInteger renderingBackend = [self->tempSettings.renderingBackend integerValue];
|
||||
[self.renderingBackendSelector setSelectedSegmentIndex:renderingBackend];
|
||||
[self.renderingBackendSelector addTarget:self action:@selector(renderingBackendChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
NSInteger framePacingMode = [tempSettings.framePacingMode integerValue];
|
||||
[self.framePacingModeSelector setSelectedSegmentIndex:framePacingMode];
|
||||
[self.framePacingModeSelector addTarget:self action:@selector(framePacingModeChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self framePacingModeChanged:self.framePacingModeSelector];
|
||||
NSInteger framePacingMode = [self->tempSettings.framePacingMode integerValue];
|
||||
[self.framePacingModeSelector setSelectedSegmentIndex:framePacingMode];
|
||||
[self.framePacingModeSelector addTarget:self action:@selector(framePacingModeChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self framePacingModeChanged:self.framePacingModeSelector];
|
||||
|
||||
[self renderingBackendChanged:self.renderingBackendSelector]; // Update PiP and frame pacing state based on current selection
|
||||
[self renderingBackendChanged:self.renderingBackendSelector]; // Update PiP and frame pacing state based on current selection
|
||||
|
||||
[self.citrixX1MouseSwitch setOn:tempSettings.btMouseSupport];
|
||||
[self.optimizeGamesSwitch setOn: tempSettings.optimizeGames];
|
||||
[self.multiControllerSwitch setOn:tempSettings.multiController];
|
||||
[self.swapAbxySwitch setOn:tempSettings.swapABXYButtons];
|
||||
[self.buttonVisualFeedbackSwitch setOn:tempSettings.buttonVisualFeedback];
|
||||
[self.citrixX1MouseSwitch setOn:self->tempSettings.btMouseSupport];
|
||||
[self.optimizeGamesSwitch setOn: self->tempSettings.optimizeGames];
|
||||
[self.multiControllerSwitch setOn:self->tempSettings.multiController];
|
||||
[self.swapAbxySwitch setOn:self->tempSettings.swapABXYButtons];
|
||||
[self.buttonVisualFeedbackSwitch setOn:self->tempSettings.buttonVisualFeedback];
|
||||
|
||||
[self.gyroModeSelector setSelectedSegmentIndex:tempSettings.gyroMode.intValue];
|
||||
[self.gyroSensitivitySlider setValue: (uint16_t)(tempSettings.gyroSensitivity.floatValue * 100) animated:YES]; // Load old setting.
|
||||
[self.gyroSensitivitySlider addTarget:self action:@selector(gyroSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self gyroSensitivitySliderMoved:self.gyroSensitivitySlider];
|
||||
|
||||
if (@available(iOS 14.0, tvOS 14.0, *)) nil;
|
||||
else{
|
||||
[self.gyroModeSelector setEnabled:false forSegmentAtIndex:1];
|
||||
[self.gyroModeSelector setEnabled:false forSegmentAtIndex:3];
|
||||
}
|
||||
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
|
||||
[self.gyroModeSelector setEnabled:[motionManager isGyroAvailable] forSegmentAtIndex:2];
|
||||
|
||||
[self.emulatedControllerTypeSelector setSelectedSegmentIndex:[self controllerTypeToSegmentIndex:tempSettings.emulatedControllerType.intValue]];
|
||||
[self.emulatedControllerTypeSelector addTarget:self action:@selector(emulatedControllerTypeChanged:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self emulatedControllerTypeChanged:self.emulatedControllerTypeSelector];
|
||||
|
||||
[self.audioOnPcSwitch setOn:tempSettings.playAudioOnPC];
|
||||
|
||||
[self.localVolumeSlider setValue:tempSettings.localVolume.floatValue*100];
|
||||
[self.localVolumeSlider addTarget:self action:@selector(localVolumeSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self localVolumeSliderMoved:self.localVolumeSlider];
|
||||
|
||||
[self.micVolumeSlider setValue:tempSettings.micVolume.floatValue*100];
|
||||
[self.micVolumeSlider addTarget:self action:@selector(micVolumeSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self micVolumeSliderMoved:self.self.micVolumeSlider];
|
||||
|
||||
[self.redirectMicSwitch setOn:tempSettings.redirectMic];
|
||||
[self.redirectMicSwitch addTarget:self action:@selector(redirectMicSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self redirectMicSwitchFlipped:self.redirectMicSwitch];
|
||||
|
||||
[self.useBuiltinMicSwitch setOn:tempSettings.useBuiltinMic];
|
||||
|
||||
_lastSelectedResolutionIndex = resolution;
|
||||
[self.resolutionSelector setSelectedSegmentIndex:resolution];
|
||||
[self.resolutionSelector addTarget:self action:@selector(newResolutionChosen) forControlEvents:UIControlEventValueChanged];
|
||||
[self.gyroModeSelector setSelectedSegmentIndex:self->tempSettings.gyroMode.intValue];
|
||||
[self.gyroSensitivitySlider setValue: (uint16_t)(self->tempSettings.gyroSensitivity.floatValue * 100) animated:YES]; // Load old setting.
|
||||
[self.gyroSensitivitySlider addTarget:self action:@selector(gyroSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self gyroSensitivitySliderMoved:self.gyroSensitivitySlider];
|
||||
|
||||
if (@available(iOS 14.0, tvOS 14.0, *)) nil;
|
||||
else{
|
||||
[self.gyroModeSelector setEnabled:false forSegmentAtIndex:1];
|
||||
[self.gyroModeSelector setEnabled:false forSegmentAtIndex:3];
|
||||
}
|
||||
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
|
||||
[self.gyroModeSelector setEnabled:[motionManager isGyroAvailable] forSegmentAtIndex:2];
|
||||
|
||||
[self.emulatedControllerTypeSelector setSelectedSegmentIndex:[self controllerTypeToSegmentIndex:self->tempSettings.emulatedControllerType.intValue]];
|
||||
[self.emulatedControllerTypeSelector addTarget:self action:@selector(emulatedControllerTypeChanged:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self emulatedControllerTypeChanged:self.emulatedControllerTypeSelector];
|
||||
|
||||
[self.audioOnPcSwitch setOn:self->tempSettings.playAudioOnPC];
|
||||
|
||||
[self.localVolumeSlider setValue:self->tempSettings.localVolume.floatValue*100];
|
||||
[self.localVolumeSlider addTarget:self action:@selector(localVolumeSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self localVolumeSliderMoved:self.localVolumeSlider];
|
||||
|
||||
[self.micVolumeSlider setValue:self->tempSettings.micVolume.floatValue*100];
|
||||
[self.micVolumeSlider addTarget:self action:@selector(micVolumeSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self micVolumeSliderMoved:self.self.micVolumeSlider];
|
||||
|
||||
[self.redirectMicSwitch setOn:self->tempSettings.redirectMic];
|
||||
[self.redirectMicSwitch addTarget:self action:@selector(redirectMicSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self redirectMicSwitchFlipped:self.redirectMicSwitch];
|
||||
|
||||
[self.useBuiltinMicSwitch setOn:self->tempSettings.useBuiltinMic];
|
||||
|
||||
self->_lastSelectedResolutionIndex = resolution;
|
||||
[self.resolutionSelector setSelectedSegmentIndex:resolution];
|
||||
[self.resolutionSelector addTarget:self action:@selector(newResolutionChosen) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
[self.framerateSelector setSelectedSegmentIndex:framerate];
|
||||
[self.framerateSelector addTarget:self action:@selector(framerateChanged) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
[self.bitrateSlider setMinimumValue:0];
|
||||
[self.bitrateSlider setMaximumValue:(sizeof(bitrateTable) / sizeof(*bitrateTable)) - 1];
|
||||
[self.bitrateSlider setValue:[self getSliderValueForBitrate:_bitrate] animated:YES];
|
||||
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
|
||||
[self updateBitrateText];
|
||||
[self updateResolutionDisplayLabel];
|
||||
[self.framerateSelector setSelectedSegmentIndex:framerate];
|
||||
[self.framerateSelector addTarget:self action:@selector(framerateChanged) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
[self.bitrateSlider setMinimumValue:0];
|
||||
[self.bitrateSlider setMaximumValue:(sizeof(bitrateTable) / sizeof(*bitrateTable)) - 1];
|
||||
[self.bitrateSlider setValue:[self getSliderValueForBitrate:self->_bitrate] animated:YES];
|
||||
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
|
||||
[self updateBitrateText];
|
||||
[self updateResolutionDisplayLabel];
|
||||
|
||||
[self.frameQueueSizeSlider setMinimumValue:1];
|
||||
[self.frameQueueSizeSlider setMaximumValue:5];
|
||||
[self.frameQueueSizeSlider setValue:tempSettings.frameQueueSize.intValue];
|
||||
[self.frameQueueSizeSlider addTarget:self action:@selector(frameQueueSizeSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self frameQueueSizeSliderMoved:self.frameQueueSizeSlider];
|
||||
[self.frameQueueSizeSlider setMinimumValue:1];
|
||||
[self.frameQueueSizeSlider setMaximumValue:5];
|
||||
[self.frameQueueSizeSlider setValue:self->tempSettings.frameQueueSize.intValue];
|
||||
[self.frameQueueSizeSlider addTarget:self action:@selector(frameQueueSizeSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self frameQueueSizeSliderMoved:self.frameQueueSizeSlider];
|
||||
|
||||
[self.enableGraphsSwitch setOn:tempSettings.enableGraphs animated:NO]; // Add this line
|
||||
[self.enableGraphsSwitch addTarget:self action:@selector(enableGraphsChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self enableGraphsChanged:self.enableGraphsSwitch];
|
||||
[self.graphOpacityStepper setMinimumValue:0];
|
||||
[self.graphOpacityStepper setMaximumValue:100];
|
||||
[self.graphOpacityStepper setValue:(int)tempSettings.graphOpacity.intValue];
|
||||
[self.graphOpacityStepper addTarget:self action:@selector(graphOpacityStepperTapped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self graphOpacityStepperTapped:self.graphOpacityStepper];
|
||||
[self.enableGraphsSwitch setOn:self->tempSettings.enableGraphs animated:NO]; // Add this line
|
||||
[self.enableGraphsSwitch addTarget:self action:@selector(enableGraphsChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self enableGraphsChanged:self.enableGraphsSwitch];
|
||||
[self.graphOpacityStepper setMinimumValue:0];
|
||||
[self.graphOpacityStepper setMaximumValue:100];
|
||||
[self.graphOpacityStepper setValue:(int)self->tempSettings.graphOpacity.intValue];
|
||||
[self.graphOpacityStepper addTarget:self action:@selector(graphOpacityStepperTapped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self graphOpacityStepperTapped:self.graphOpacityStepper];
|
||||
|
||||
if (@available(iOS 18.0, tvOS 18.0, *)) {}else{
|
||||
[self.audioConfigSelector removeSegmentAtIndex:1 animated:false];
|
||||
[self.audioConfigSelector removeSegmentAtIndex:1 animated:false]; // segment 2 goes away when you remove index 2
|
||||
[self.audioConfigSelector setTitle:[LocalizationHelper localizedStringForKey:@"Stereo (surround sound available for iOS18+)"] forSegmentAtIndex:0];
|
||||
[self.audioConfigSelector setEnabled:NO];
|
||||
}
|
||||
switch ([tempSettings.audioConfig integerValue]) {
|
||||
case 2:
|
||||
[self.audioConfigSelector setSelectedSegmentIndex:0];
|
||||
break;
|
||||
case 6:
|
||||
[self.audioConfigSelector setSelectedSegmentIndex:1];
|
||||
break;
|
||||
case 8:
|
||||
[self.audioConfigSelector setSelectedSegmentIndex:2];
|
||||
break;
|
||||
}
|
||||
if (@available(iOS 18.0, tvOS 18.0, *)) {}else{
|
||||
[self.audioConfigSelector removeSegmentAtIndex:1 animated:false];
|
||||
[self.audioConfigSelector removeSegmentAtIndex:1 animated:false]; // segment 2 goes away when you remove index 2
|
||||
[self.audioConfigSelector setTitle:[LocalizationHelper localizedStringForKey:@"Stereo (surround sound available for iOS18+)"] forSegmentAtIndex:0];
|
||||
[self.audioConfigSelector setEnabled:NO];
|
||||
}
|
||||
switch ([self->tempSettings.audioConfig integerValue]) {
|
||||
case 2:
|
||||
[self.audioConfigSelector setSelectedSegmentIndex:0];
|
||||
break;
|
||||
case 6:
|
||||
[self.audioConfigSelector setSelectedSegmentIndex:1];
|
||||
break;
|
||||
case 8:
|
||||
[self.audioConfigSelector setSelectedSegmentIndex:2];
|
||||
break;
|
||||
}
|
||||
|
||||
// Unlock Display Orientation setting
|
||||
bool unlockDisplayOrientationSelectorEnabled = [self isFullScreenRequired] || [self isIPhone];//need "requires fullscreen" enabled in the app bunddle to make runtime orientation limitation working
|
||||
if(unlockDisplayOrientationSelectorEnabled) [self.unlockDisplayOrientationSelector setSelectedSegmentIndex:tempSettings.unlockDisplayOrientation ? 1 : 0];
|
||||
else [self.unlockDisplayOrientationSelector setSelectedSegmentIndex:1]; // can't lock screen orientation in this mode = Display Orientation always unlocked
|
||||
[self.unlockDisplayOrientationSelector setEnabled:unlockDisplayOrientationSelectorEnabled];
|
||||
// Unlock Display Orientation setting
|
||||
bool unlockDisplayOrientationSelectorEnabled = [self isFullScreenRequired] || [self isIPhone];//need "requires fullscreen" enabled in the app bunddle to make runtime orientation limitation working
|
||||
if(unlockDisplayOrientationSelectorEnabled) [self.unlockDisplayOrientationSelector setSelectedSegmentIndex:self->tempSettings.unlockDisplayOrientation ? 1 : 0];
|
||||
else [self.unlockDisplayOrientationSelector setSelectedSegmentIndex:1]; // can't lock screen orientation in this mode = Display Orientation always unlocked
|
||||
[self.unlockDisplayOrientationSelector setEnabled:unlockDisplayOrientationSelectorEnabled];
|
||||
|
||||
[self.backgroundSessionTimerSlider setValue:(uint32_t)tempSettings.backgroundSessionTimer.floatValue];
|
||||
[self.backgroundSessionTimerSlider addTarget:self action:@selector(backgroundSessionTimerSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self backgroundSessionTimerSliderMoved:self.backgroundSessionTimerSlider];
|
||||
[self.backgroundSessionTimerSlider setValue:(uint32_t)self->tempSettings.backgroundSessionTimer.floatValue];
|
||||
[self.backgroundSessionTimerSlider addTarget:self action:@selector(backgroundSessionTimerSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self backgroundSessionTimerSliderMoved:self.backgroundSessionTimerSlider];
|
||||
|
||||
// lift streamview setting
|
||||
[self.liftStreamViewForKeyboardSelector setSelectedSegmentIndex:tempSettings.liftStreamViewForKeyboard ? 1 : 0];// Load old setting
|
||||
// lift streamview setting
|
||||
[self.liftStreamViewForKeyboardSelector setSelectedSegmentIndex:self->tempSettings.liftStreamViewForKeyboard ? 1 : 0];// Load old setting
|
||||
|
||||
// showkeyboard toolbar setting
|
||||
[self.softKeyboardToolbarSwitch setOn:tempSettings.showKeyboardToolbar];// Load old setting
|
||||
// showkeyboard toolbar setting
|
||||
[self.softKeyboardToolbarSwitch setOn:self->tempSettings.showKeyboardToolbar];// Load old setting
|
||||
|
||||
// reverse mouse wheel direction setting
|
||||
[self.reverseMouseWheelDirectionSelector setSelectedSegmentIndex:tempSettings.reverseMouseWheelDirection ? 1 : 0];// Load old setting
|
||||
// reverse mouse wheel direction setting
|
||||
[self.reverseMouseWheelDirectionSelector setSelectedSegmentIndex:self->tempSettings.reverseMouseWheelDirection ? 1 : 0];// Load old setting
|
||||
|
||||
// slide to menu settings
|
||||
[self.slideToSettingsScreenEdgeSelector setSelectedSegmentIndex:[self getSelectorIndexFromScreenEdge:(uint32_t)tempSettings.slideToSettingsScreenEdge.integerValue]];
|
||||
// Load old setting
|
||||
[self.slideToToolboxScreenEdgeSelector setEnabled:false];
|
||||
[self.slideToSettingsScreenEdgeSelector addTarget:self action:@selector(slideToSettingsScreenEdgeChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[self slideToSettingsScreenEdgeChanged];
|
||||
// slide to menu settings
|
||||
[self.slideToSettingsScreenEdgeSelector setSelectedSegmentIndex:[self getSelectorIndexFromScreenEdge:(uint32_t)self->tempSettings.slideToSettingsScreenEdge.integerValue]];
|
||||
// Load old setting
|
||||
[self.slideToToolboxScreenEdgeSelector setEnabled:false];
|
||||
[self.slideToSettingsScreenEdgeSelector addTarget:self action:@selector(slideToSettingsScreenEdgeChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[self slideToSettingsScreenEdgeChanged];
|
||||
|
||||
[self.slideToMenuDistanceSlider setValue:tempSettings.slideToSettingsDistance.floatValue];
|
||||
[self.slideToMenuDistanceSlider addTarget:self action:@selector(slideToMenuDistanceSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self slideToMenuDistanceSliderMoved:self.slideToMenuDistanceSlider];
|
||||
[self.slideToMenuDistanceSlider setValue:self->tempSettings.slideToSettingsDistance.floatValue];
|
||||
[self.slideToMenuDistanceSlider addTarget:self action:@selector(slideToMenuDistanceSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self slideToMenuDistanceSliderMoved:self.slideToMenuDistanceSlider];
|
||||
|
||||
|
||||
|
||||
//TouchMode & OSC Related Settings:
|
||||
//TouchMode & OSC Related Settings:
|
||||
|
||||
// pointer veloc setting, will be enable/disabled by touchMode
|
||||
[self.pointerVelocityModeDividerSlider setValue: (uint8_t)(tempSettings.pointerVelocityModeDivider.floatValue * 100) animated:YES]; // Load old setting.
|
||||
[self.pointerVelocityModeDividerSlider addTarget:self action:@selector(pointerVelocityModeDividerSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self pointerVelocityModeDividerSliderMoved:self.pointerVelocityModeDividerSlider];
|
||||
// pointer veloc setting, will be enable/disabled by touchMode
|
||||
[self.pointerVelocityModeDividerSlider setValue: (uint8_t)(self->tempSettings.pointerVelocityModeDivider.floatValue * 100) animated:YES]; // Load old setting.
|
||||
[self.pointerVelocityModeDividerSlider addTarget:self action:@selector(pointerVelocityModeDividerSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self pointerVelocityModeDividerSliderMoved:self.pointerVelocityModeDividerSlider];
|
||||
|
||||
// init pointer veloc setting, will be enable/disabled by touchMode
|
||||
[self.touchPointerVelocityFactorSlider setValue: [self map_SliderValue_fromVelocFactor: tempSettings.touchPointerVelocityFactor.floatValue] animated:YES]; // Load old setting.
|
||||
[self.touchPointerVelocityFactorSlider addTarget:self action:@selector(touchPointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self touchPointerVelocityFactorSliderMoved:self.touchPointerVelocityFactorSlider];
|
||||
// init pointer veloc setting, will be enable/disabled by touchMode
|
||||
[self.touchPointerVelocityFactorSlider setValue: [self map_SliderValue_fromVelocFactor: self->tempSettings.touchPointerVelocityFactor.floatValue] animated:YES]; // Load old setting.
|
||||
[self.touchPointerVelocityFactorSlider addTarget:self action:@selector(touchPointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self touchPointerVelocityFactorSliderMoved:self.touchPointerVelocityFactorSlider];
|
||||
|
||||
// async native touch event
|
||||
// [self.asyncNativeTouchPrioritySelector setSelectedSegmentIndex:currentSettings.asyncNativeTouchPriority.intValue]; // load old setting of asyncNativeTouchPriority
|
||||
// [self.asyncNativeTouchPrioritySelector addTarget:self action:@selector(asyncNativeTouchPriorityChanged) forControlEvents:UIControlEventValueChanged];
|
||||
// async native touch event
|
||||
// [self.asyncNativeTouchPrioritySelector setSelectedSegmentIndex:currentSettings.asyncNativeTouchPriority.intValue]; // load old setting of asyncNativeTouchPriority
|
||||
// [self.asyncNativeTouchPrioritySelector addTarget:self action:@selector(asyncNativeTouchPriorityChanged) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
// init relative touch mouse pointer veloc setting, will be enable/disabled by touchMode
|
||||
[self.mousePointerVelocityFactorSlider setValue:[self map_SliderValue_fromVelocFactor: tempSettings.mousePointerVelocityFactor.floatValue] animated:YES]; // Load old setting.
|
||||
[self.mousePointerVelocityFactorSlider addTarget:self action:@selector(mousePointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self mousePointerVelocityFactorSliderMoved:self.mousePointerVelocityFactorSlider];
|
||||
// init relative touch mouse pointer veloc setting, will be enable/disabled by touchMode
|
||||
[self.mousePointerVelocityFactorSlider setValue:[self map_SliderValue_fromVelocFactor: self->tempSettings.mousePointerVelocityFactor.floatValue] animated:YES]; // Load old setting.
|
||||
[self.mousePointerVelocityFactorSlider addTarget:self action:@selector(mousePointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self mousePointerVelocityFactorSliderMoved:self.mousePointerVelocityFactorSlider];
|
||||
|
||||
|
||||
// these settings will be affected by onscreenControl & touchMode, must be loaded before them.
|
||||
// NSLog(@"osc tool fingers setting test: %d", currentSettings.oscLayoutToolFingers.intValue);
|
||||
self->oswLayoutFingers = (uint16_t)tempSettings.oscLayoutToolFingers.intValue; // load old setting of oscLayoutFingers
|
||||
uint8_t keyboardToggleFingers = tempSettings.keyboardToggleFingers.intValue;
|
||||
// these settings will be affected by onscreenControl & touchMode, must be loaded before them.
|
||||
// NSLog(@"osc tool fingers setting test: %d", currentSettings.oscLayoutToolFingers.intValue);
|
||||
self->oswLayoutFingers = (uint16_t)self->tempSettings.oscLayoutToolFingers.intValue; // load old setting of oscLayoutFingers
|
||||
uint8_t keyboardToggleFingers = self->tempSettings.keyboardToggleFingers.intValue;
|
||||
|
||||
[self.softKeyboardGestureSelector setSelectedSegmentIndex:keyboardToggleFingers>=5 ? 3 : keyboardToggleFingers-3];
|
||||
[self.softKeyboardGestureSelector setSelectedSegmentIndex:keyboardToggleFingers>=5 ? 3 : keyboardToggleFingers-3];
|
||||
|
||||
|
||||
|
||||
// this setting will be affected by touchMode, must be loaded before them.
|
||||
NSInteger onscreenControlsLevel = [tempSettings.onscreenControls integerValue];
|
||||
[self.onScreenWidgetSelector setSelectedSegmentIndex:onscreenControlsLevel];
|
||||
[self.onScreenWidgetSelector addTarget:self action:@selector(onScreenWidgetChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[self onScreenWidgetChanged];
|
||||
// this setting will be affected by touchMode, must be loaded before them.
|
||||
NSInteger onscreenControlsLevel = [self->tempSettings.onscreenControls integerValue];
|
||||
[self.onScreenWidgetSelector setSelectedSegmentIndex:onscreenControlsLevel];
|
||||
[self.onScreenWidgetSelector addTarget:self action:@selector(onScreenWidgetChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[self onScreenWidgetChanged];
|
||||
|
||||
// touch move event interval for native-touch.
|
||||
[self.touchMoveEventIntervalSlider setValue:tempSettings.touchMoveEventInterval.intValue animated:YES]; // Load old setting.
|
||||
[self.touchMoveEventIntervalSlider addTarget:self action:@selector(touchMoveEventIntervalSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
|
||||
// touch move event interval for native-touch.
|
||||
[self.touchMoveEventIntervalSlider setValue:self->tempSettings.touchMoveEventInterval.intValue animated:YES]; // Load old setting.
|
||||
[self.touchMoveEventIntervalSlider addTarget:self action:@selector(touchMoveEventIntervalSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
|
||||
|
||||
|
||||
// this part will enable/disable oscSelector & the asyncNativeTouchPriority selector
|
||||
uint8_t touchModeSelectorIndex = tempSettings.touchMode.intValue == NativeTouchOnly ? NativeTouch : tempSettings.touchMode.intValue;
|
||||
[self.touchModeSelector setSelectedSegmentIndex:touchModeSelectorIndex]; //Load old touchMode setting
|
||||
[self.touchModeSelector addTarget:self action:@selector(touchModeChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self touchModeChanged:self.touchModeSelector];
|
||||
// this part will enable/disable oscSelector & the asyncNativeTouchPriority selector
|
||||
uint8_t touchModeSelectorIndex = self->tempSettings.touchMode.intValue == NativeTouchOnly ? NativeTouch : self->tempSettings.touchMode.intValue;
|
||||
[self.touchModeSelector setSelectedSegmentIndex:touchModeSelectorIndex]; //Load old touchMode setting
|
||||
[self.touchModeSelector addTarget:self action:@selector(touchModeChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self touchModeChanged:self.touchModeSelector];
|
||||
|
||||
self.enableOswSwitchStack.hidden = !(tempSettings.touchMode.intValue == NativeTouch || tempSettings.touchMode.intValue == NativeTouchOnly); // do not use setHidden to stack wrapped by a settingStack
|
||||
|
||||
[self.enableOswForNativeTouchSwitch setOn:tempSettings.touchMode.intValue != NativeTouchOnly];
|
||||
[self.enableOswForNativeTouchSwitch addTarget:self action:@selector(enableOswForNativeTouchSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self enableOswForNativeTouchSwitchFlipped:self.enableOswForNativeTouchSwitch];
|
||||
self.enableOswSwitchStack.hidden = !(self->tempSettings.touchMode.intValue == NativeTouch || self->tempSettings.touchMode.intValue == NativeTouchOnly); // do not use setHidden to stack wrapped by a settingStack
|
||||
|
||||
[self.enableOswForNativeTouchSwitch setOn:self->tempSettings.touchMode.intValue != NativeTouchOnly];
|
||||
[self.enableOswForNativeTouchSwitch addTarget:self action:@selector(enableOswForNativeTouchSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self enableOswForNativeTouchSwitchFlipped:self.enableOswForNativeTouchSwitch];
|
||||
|
||||
[self.externalDisplayModeSelector setSelectedSegmentIndex:self->tempSettings.externalDisplayMode.integerValue];
|
||||
[self.localMousePointerModeSelector setSelectedSegmentIndex:self->tempSettings.localMousePointerMode.integerValue];
|
||||
|
||||
[self.sendDummyEventSwitch setOn:self->tempSettings.sendDummyEvent];// Load old setting
|
||||
|
||||
|
||||
self->motionControlSection.expandable = [self isCustomOswEnabled];
|
||||
__weak typeof(self) weakSelf = self;
|
||||
self->motionControlSection.lockedSectionHandler = ^{
|
||||
[CountdownAlertController showAlertIn:weakSelf
|
||||
title:[LocalizationHelper localizedStringForKey:@"Tips"]
|
||||
message:[LocalizationHelper localizedStringForKey:@"Tap 'OK' to set on-screen widget to 'Custom' and enable motion control."]
|
||||
withCancel:YES
|
||||
buttonTitle:[LocalizationHelper localizedStringForKey:@"OK"]
|
||||
countdown:0
|
||||
completion:^{
|
||||
if(!CountdownAlertController.actionCancelled){
|
||||
[weakSelf.onScreenWidgetSelector setSelectedSegmentIndex:OnScreenControlsLevelCustom];
|
||||
__strong typeof(weakSelf) strongSelf = weakSelf;
|
||||
if (!strongSelf) return;
|
||||
strongSelf->motionControlSection.expandable = true;
|
||||
[strongSelf->motionControlSection setExpanded:YES];
|
||||
}
|
||||
}];
|
||||
};
|
||||
[self.mapGyroToSelector addTarget:self action:@selector(mapGyroToChanged:) forControlEvents:UIControlEventValueChanged];
|
||||
[self.yawPitchToRightStickSwitch addTarget:self action:@selector(yawPitchToRightStickSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
[self.rollToLeftStickSwitch addTarget:self action:@selector(rollToLeftStickSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
[self.yawSensitivitySlider addTarget:self action:@selector(yawSensitivitySliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self.pitchSensitivitySlider addTarget:self action:@selector(pitchSensitivitySliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
[self.rollSensitivitySlider addTarget:self action:@selector(rollSensitivitySliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||
|
||||
//Motion control settings
|
||||
|
||||
self->settingsViewJustLoaded = false;
|
||||
}];
|
||||
|
||||
[self.externalDisplayModeSelector setSelectedSegmentIndex:tempSettings.externalDisplayMode.integerValue];
|
||||
[self.localMousePointerModeSelector setSelectedSegmentIndex:tempSettings.localMousePointerMode.integerValue];
|
||||
|
||||
[self.sendDummyEventSwitch setOn:tempSettings.sendDummyEvent];// Load old setting
|
||||
|
||||
settingsViewJustLoaded = false;
|
||||
}
|
||||
|
||||
- (void)slideToSettingsScreenEdgeChanged{
|
||||
@@ -1793,7 +1900,11 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
- (bool)isCustomOswEnabled{
|
||||
return [self isOswEnabled] && self.onScreenWidgetSelector.selectedSegmentIndex == OnScreenControlsLevelCustom;
|
||||
bool customOswEnabled = [self isOswEnabled] && self.onScreenWidgetSelector.selectedSegmentIndex == OnScreenControlsLevelCustom;
|
||||
motionControlSection.expandable = customOswEnabled;
|
||||
if(!settingsViewJustLoaded) [motionControlSection setExpanded:customOswEnabled];
|
||||
NSLog(@"isCustomOswEnabled %d, %f",customOswEnabled, CACurrentMediaTime());
|
||||
return customOswEnabled;
|
||||
}
|
||||
|
||||
- (bool)isNotNativeTouchOnly{
|
||||
@@ -1926,6 +2037,76 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mapGyroToChanged:(UISegmentedControl* )sender{
|
||||
[self setHidden:sender.selectedSegmentIndex != mapGyroToControllerStick forStack:_gyroToStickSwitchStack];
|
||||
bool mapGyroToMouseEnabled = sender.selectedSegmentIndex == mapGyroToMouse;
|
||||
bool mapGyroToControllerStickEnabled = sender.selectedSegmentIndex == mapGyroToControllerStick;
|
||||
if(mapGyroToMouseEnabled){
|
||||
[self setHidden:false forStack:_yawPitchSensitivityStack];
|
||||
[self setHidden:true forStack:_rollSensitivityStack];
|
||||
}
|
||||
if(mapGyroToControllerStickEnabled){
|
||||
[self yawPitchToRightStickSwitchFlipped:self.yawPitchToRightStickSwitch];
|
||||
[self rollToLeftStickSwitchFlipped:self.rollToLeftStickSwitch];
|
||||
}
|
||||
if(sender.selectedSegmentIndex == driftCorrection){
|
||||
|
||||
[CountdownAlertController showAlertIn:self
|
||||
title:[LocalizationHelper localizedStringForKey:@"Drift Correction"]
|
||||
message:[LocalizationHelper localizedStringForKey:@"Place the device flat on a surface and keep it still, then tap ‘Start’."]
|
||||
withCancel:YES
|
||||
buttonTitle:[LocalizationHelper localizedStringForKey:@"Start"]
|
||||
countdown:0
|
||||
completion:^{
|
||||
if(CountdownAlertController.actionCancelled){
|
||||
[self.mapGyroToSelector setSelectedSegmentIndex:self->oscProfile.mapGyroTo];
|
||||
NSLog(@"actionCancelled");
|
||||
}
|
||||
else{
|
||||
MotionHandler* motionHandler = [MotionHandler sharedInstance];
|
||||
[motionHandler calibrateGyroBiasWithDuration:5 completion:^{
|
||||
Settings* currentSettings = [self->dataMan retrieveSettings];
|
||||
currentSettings.gyroBiasX = [NSNumber numberWithDouble:motionHandler.gyroBiasX];
|
||||
currentSettings.gyroBiasY = [NSNumber numberWithDouble:motionHandler.gyroBiasY];
|
||||
currentSettings.gyroBiasZ = [NSNumber numberWithDouble:motionHandler.gyroBiasZ];
|
||||
[self->dataMan saveData];
|
||||
}];
|
||||
[CountdownAlertController showAlertIn:self
|
||||
title:[LocalizationHelper localizedStringForKey:@"Drift Correction"]
|
||||
message:[LocalizationHelper localizedStringForKey:@"Calibrating..."]
|
||||
withCancel:NO
|
||||
buttonTitle:[LocalizationHelper localizedStringForKey:@"Finished!"]
|
||||
countdown:6
|
||||
completion:^{
|
||||
[self.mapGyroToSelector setSelectedSegmentIndex:self->oscProfile.mapGyroTo];
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rollToLeftStickSwitchFlipped:(UISwitch* )sender{
|
||||
[self setHidden:!sender.isOn forStack:_rollSensitivityStack];
|
||||
}
|
||||
|
||||
- (void)yawPitchToRightStickSwitchFlipped:(UISwitch* )sender{
|
||||
[self setHidden:!sender.isOn forStack:_yawPitchSensitivityStack];
|
||||
}
|
||||
|
||||
- (void)yawSensitivitySliderMoved:(UISlider* )sender{
|
||||
[self findDynamicLabelFromStack:_yawSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (int16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]];
|
||||
[_pitchSensitivitySlider setValue:sender.value];
|
||||
[self pitchSensitivitySliderMoved:self.pitchSensitivitySlider];
|
||||
}
|
||||
|
||||
- (void)pitchSensitivitySliderMoved:(UISlider* )sender{
|
||||
[self findDynamicLabelFromStack:_pitchSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (int16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]];
|
||||
}
|
||||
|
||||
- (void)rollSensitivitySliderMoved:(UISlider* )sender{
|
||||
[self findDynamicLabelFromStack:_rollSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (int16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]];
|
||||
}
|
||||
|
||||
- (void)invokeOscLayout{
|
||||
// init CustomOSC stuff
|
||||
/* sets a reference to the correct 'LayoutOnScreenControlsViewController' depending on whether the user is on an iPhone or iPad */
|
||||
@@ -1950,7 +2131,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
- (void) touchPointerVelocityFactorSliderMoved:(UISlider* )sender {
|
||||
[self findDynamicLabelFromStack:self.pointerVelocityFactorStack].text = [NSString stringWithFormat:@" %d%% ", [self map_velocFactorDisplay_fromSliderValue:sender.value]]; // Update label display
|
||||
[self findDynamicLabelFromStack:self.pointerVelocityFactorStack].text = [NSString stringWithFormat:@" %d%% ", (uint16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]]; // Update label display
|
||||
}
|
||||
|
||||
- (void) gyroSensitivitySliderMoved:(UISlider* )sender {
|
||||
@@ -1977,10 +2158,10 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
|
||||
|
||||
// veloc factor upto 700%
|
||||
- (uint16_t) map_velocFactorDisplay_fromSliderValue:(CGFloat)sliderValue{
|
||||
uint16_t velocFactorDisplay = 0;
|
||||
- (CGFloat) map_velocFactorDisplay_fromSliderValue:(CGFloat)sliderValue{
|
||||
CGFloat velocFactorDisplay = 0;
|
||||
if(sliderValue > 200) velocFactorDisplay = 200 + ((uint16_t)sliderValue % 200) * 5;
|
||||
else velocFactorDisplay = (uint16_t) sliderValue;
|
||||
else velocFactorDisplay = sliderValue;
|
||||
return velocFactorDisplay;
|
||||
}
|
||||
|
||||
@@ -1994,7 +2175,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
- (void) mousePointerVelocityFactorSliderMoved:(UISlider* )sender {
|
||||
[self findDynamicLabelFromStack:_mousePointerVelocityStack].text = [NSString stringWithFormat:@" %d%% ",[self map_velocFactorDisplay_fromSliderValue:sender.value]];
|
||||
[self findDynamicLabelFromStack:_mousePointerVelocityStack].text = [NSString stringWithFormat:@" %d%% ",(uint16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]];
|
||||
}
|
||||
|
||||
- (uint32_t) getScreenEdgeFromSelector {
|
||||
@@ -2516,6 +2697,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
|
||||
if(![MicHandler permissionGranted]) [self.redirectMicSwitch setOn:false];
|
||||
|
||||
[self saveMotionControlConfigs];
|
||||
}
|
||||
|
||||
- (void) saveSettings {
|
||||
|
||||
Reference in New Issue
Block a user