From 233a23c6c84e5fee0e642f4934df97b7ebb91e14 Mon Sep 17 00:00:00 2001 From: True Zhuanjia Date: Wed, 29 Apr 2026 22:01:18 +0800 Subject: [PATCH] refactor touchMode to game profile --- VoidLink/Input/CustomOSC/OSCProfile.h | 1 + VoidLink/Input/CustomOSC/OSCProfile.m | 3 + VoidLink/Input/StreamView.m | 61 ++++++++++--------- ...LayoutOnScreenControlsViewController.swift | 6 +- .../OSCProfilesTableViewController.swift | 7 +++ .../ViewControllers/MainFrameViewController.m | 6 +- .../ViewControllers/SettingsViewController.m | 33 +++++----- 7 files changed, 70 insertions(+), 47 deletions(-) diff --git a/VoidLink/Input/CustomOSC/OSCProfile.h b/VoidLink/Input/CustomOSC/OSCProfile.h index 1317424f..90939236 100644 --- a/VoidLink/Input/CustomOSC/OSCProfile.h +++ b/VoidLink/Input/CustomOSC/OSCProfile.h @@ -60,6 +60,7 @@ typedef NS_ENUM(NSInteger, PencilHoverMode) { @property (nonatomic, assign) bool reverseGyroHoldButton; @property (nonatomic, assign) int controllerGyroSwitchHold; @property (nonatomic, assign) int controllerGyroSwitchToggle; +@property (nonatomic, assign) int touchMode; @property (nonatomic, assign) CGFloat pointerVelocityModeDivider; @property (nonatomic, assign) CGFloat touchPointerVelocityFactor; @property (nonatomic, assign) CGPoint normalizedStreamViewOffset; diff --git a/VoidLink/Input/CustomOSC/OSCProfile.m b/VoidLink/Input/CustomOSC/OSCProfile.m index 7d251cdb..47bc0ade 100644 --- a/VoidLink/Input/CustomOSC/OSCProfile.m +++ b/VoidLink/Input/CustomOSC/OSCProfile.m @@ -54,6 +54,7 @@ [encoder encodeInt:self.controllerGyroSwitchHold forKey:@"controllerGyroSwitchHold"]; [encoder encodeInt:self.controllerGyroSwitchToggle forKey:@"controllerGyroSwitchToggle"]; [encoder encodeFloat:self.pointerVelocityModeDivider forKey:@"pointerVelocityModeDivider"]; + [encoder encodeInt:self.touchMode forKey:@"touchMode"]; [encoder encodeFloat:self.touchPointerVelocityFactor forKey:@"touchPointerVelocityFactor"]; [encoder encodeCGPoint:self.normalizedStreamViewOffset forKey:@"normalizedStreamViewOffset"]; [encoder encodeFloat:self.streamViewScale forKey:@"streamViewScale"]; @@ -122,6 +123,7 @@ self.controllerGyroSwitchHold = [decoder containsValueForKey:@"controllerGyroSwitchHold"] ? [decoder decodeIntForKey:@"controllerGyroSwitchHold"] : ControllerButtonNull; self.controllerGyroSwitchToggle = [decoder containsValueForKey:@"controllerGyroSwitchToggle"] ? [decoder decodeIntForKey:@"controllerGyroSwitchToggle"] : ControllerButtonNull; + self.touchMode = [decoder containsValueForKey:@"touchMode"] ? [decoder decodeIntForKey:@"touchMode"] : NativeTouch; self.pointerVelocityModeDivider = [decoder containsValueForKey:@"pointerVelocityModeDivider"] ? [decoder decodeFloatForKey:@"pointerVelocityModeDivider"] : 0.5; self.touchPointerVelocityFactor = [decoder containsValueForKey:@"touchPointerVelocityFactor"] ? [decoder decodeFloatForKey:@"touchPointerVelocityFactor"] : 1.0; @@ -229,6 +231,7 @@ copy.reverseGyroHoldButton = self.reverseGyroHoldButton; copy.controllerGyroSwitchHold = self.controllerGyroSwitchHold; copy.controllerGyroSwitchToggle = self.controllerGyroSwitchToggle; + copy.touchMode = self.touchMode; copy.pointerVelocityModeDivider = self.pointerVelocityModeDivider; copy.touchPointerVelocityFactor = self.touchPointerVelocityFactor; copy.normalizedStreamViewOffset = self.normalizedStreamViewOffset; diff --git a/VoidLink/Input/StreamView.m b/VoidLink/Input/StreamView.m index d906862c..8232ae74 100644 --- a/VoidLink/Input/StreamView.m +++ b/VoidLink/Input/StreamView.m @@ -141,34 +141,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; _pencilHandler = PencilHandler.shared; // iOS uses touch Mode depending on user preference - touchMode = settings.touchMode.intValue; - switch (touchMode) { - case NativeTouch: - keyboardToggleRecognizer.immediateTriggering = false; - self->touchHandler = [[NativeTouchHandler alloc] initWithView:self settings:settings profile:profile]; - break; - case NativeTouchOnly: - keyboardToggleRecognizer.immediateTriggering = false; - self->touchHandler = [[PureNativeTouchHandler alloc] initWithView:self settings:settings profile:profile]; - break; - case RelativeTouch: - self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self andSettings:settings]; - keyboardToggleRecognizer.immediateTriggering = false; - // if(settings.onscreenControls.intValue == OnScreenControlsLevelCustom) keyboardToggleRecognizer.numberOfTouchesRequired = 3; //deprecated: fixing keyboard taps to 3, in order to invoke OSC rebase in stream view by 4-finger tap. - break; - case AbsoluteTouch: - self->touchHandler = [[AbsoluteTouchHandler alloc] initWithView:self andSettings:settings]; - keyboardToggleRecognizer.immediateTriggering = true; //triggers signal in touchesBegan callback stage - break; - case TouchDisabled: - self->touchHandler = nil; - keyboardToggleRecognizer.immediateTriggering = false; - break; - - default: - break; - } - sessionTouchHandler = touchHandler; + [self updateTouchHandlerWithProfile:profile]; // we'll render on-screen controls on the toplayer too: _onScreenControls = [[OnScreenControls alloc] initWithView:self->_streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig]; // don't delete, this is mandatory @@ -248,6 +221,37 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; [self becomeFirstResponder]; } +- (void)updateTouchHandlerWithProfile:(OSCProfile* )profile{ + touchMode = profile.touchMode; + switch (touchMode) { + case NativeTouch: + keyboardToggleRecognizer.immediateTriggering = false; + self->touchHandler = [[NativeTouchHandler alloc] initWithView:self settings:settings profile:profile]; + break; + case NativeTouchOnly: + keyboardToggleRecognizer.immediateTriggering = false; + self->touchHandler = [[PureNativeTouchHandler alloc] initWithView:self settings:settings profile:profile]; + break; + case RelativeTouch: + self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self andSettings:settings]; + keyboardToggleRecognizer.immediateTriggering = false; + // if(settings.onscreenControls.intValue == OnScreenControlsLevelCustom) keyboardToggleRecognizer.numberOfTouchesRequired = 3; //deprecated: fixing keyboard taps to 3, in order to invoke OSC rebase in stream view by 4-finger tap. + break; + case AbsoluteTouch: + self->touchHandler = [[AbsoluteTouchHandler alloc] initWithView:self andSettings:settings]; + keyboardToggleRecognizer.immediateTriggering = true; //triggers signal in touchesBegan callback stage + break; + case TouchDisabled: + self->touchHandler = nil; + keyboardToggleRecognizer.immediateTriggering = false; + break; + + default: + break; + } + sessionTouchHandler = touchHandler; +} + - (void)refreshKeyboardToggleRecognizer:(uint8_t)numberOfTouches{ [self->_streamFrameTopLayerView removeGestureRecognizer:keyboardToggleRecognizer]; keyboardToggleRecognizer = [[CustomTapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleKeyboard)]; @@ -834,6 +838,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; } [(StreamFrameViewController* )self->_streamFrameVC restorePersistedStreamViewOffsetAndScaleWithProfile:profile]; + [self updateTouchHandlerWithProfile:profile]; }); } diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift index 502ef5aa..06c53aba 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.swift @@ -281,7 +281,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector: #selector(legacyOscLayerTapped(_:)), name: Notification.Name("LegacyOscCALayerSelectedNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleProfileTablViewDismiss), name: Notification.Name("OscLayoutTableViewCloseNotification"), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(dummytest), name: Notification.Name("GameProfileSelectedNotification"), object: nil) + // NotificationCenter.default.addObserver(self, selector: #selector(dummytest), name: Notification.Name("GameProfileSelectedNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(widgetViewTapped(_:)), name: Notification.Name("OnScreenWidgetViewSelected"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(OSCLayoutChanged), name: Notification.Name("OSCLayoutChanged"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleReturnToForeground), name: UIApplication.didBecomeActiveNotification, object: nil) @@ -360,7 +360,9 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg guard let oscProfile = self.profilesManager?.getSelectedProfile() else { return } - NotificationCenter.default.post(name: Notification.Name("GameProfileSelectedNotification"), object: oscProfile) + if self.profileTableLoadingMode == .selectProfileFromStreamView { + NotificationCenter.default.post(name: Notification.Name("GameProfileSelectedNotification"), object: oscProfile) + } self.loadWidgets(from: oscProfile) diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/Table/OSCProfilesTableViewController.swift b/VoidLink/ViewControllers/CustomOSCViewControl/Table/OSCProfilesTableViewController.swift index aade57d3..097a274d 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/Table/OSCProfilesTableViewController.swift +++ b/VoidLink/ViewControllers/CustomOSCViewControl/Table/OSCProfilesTableViewController.swift @@ -254,6 +254,13 @@ final class OSCProfilesTableViewController: UIViewController, UITableViewDelegat func profileViewRefresh() { tableView.reloadData() needToUpdateOscLayoutTVC?() + if loadingMode != .selectProfileFromStreamView + && loadingMode != .pickProfile + && loadingMode != .pickProfileData + && loadingMode != .selectProfile + { + NotificationCenter.default.post(name: Notification.Name("GameProfileSelectedNotification"), object: self) + } } @IBAction func deleteTapped(_ sender: Any?) { diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index 3e6f2e65..cc4ffc6b 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1262,8 +1262,8 @@ static NSMutableSet* hostList; [settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.optimizeGamesStack]; [settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.audioOnPcStack]; [settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.sdrPerformanceWorkaroundStack]; - [settingsViewController.touchModeSelector1 setEnabled:!_settingsExpandedInStreamView || !(settingsViewController.touchModeSelector1.selectedSegmentIndex == AbsoluteTouch && !settingsViewController.passthroughGesturesSwitch.isOn)]; - [settingsViewController.touchModeSelector2 setEnabled:settingsViewController.touchModeSelector1.enabled]; + // [settingsViewController.touchModeSelector1 setEnabled:!_settingsExpandedInStreamView || !(settingsViewController.touchModeSelector1.selectedSegmentIndex == AbsoluteTouch && !settingsViewController.passthroughGesturesSwitch.isOn)]; + // [settingsViewController.touchModeSelector2 setEnabled:settingsViewController.touchModeSelector1.enabled]; [settingsViewController.codecSelector setEnabled:!_settingsExpandedInStreamView]; if(_settingsExpandedInStreamView){ @@ -1311,7 +1311,7 @@ static NSMutableSet* hostList; if(_settingsExpandedInStreamView && !streamFrameViewController.micStreamInitialized) [settingsViewController.redirectMicSwitch setOn:false]; [settingsViewController setHidden:!settingsViewController.redirectMicSwitch.isOn forStack:settingsViewController.useBuiltinMicStack]; [settingsViewController.useBuiltinMicSwitch setEnabled:!_settingsExpandedInStreamView]; - [settingsViewController.passthroughGesturesSwitch setEnabled:!_settingsExpandedInStreamView]; + // [settingsViewController.passthroughGesturesSwitch setEnabled:!_settingsExpandedInStreamView]; } - (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position { diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index c00c4160..67ecf2d3 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -355,6 +355,18 @@ BOOL isCustomResolution(int resolutionSelected) { - (void)reloadGameProfileConfigs{ oscProfile = [oscProfileMan getSelectedProfile]; + // this part will enable/disable oscSelector & the asyncNativeTouchPriority selector + uint8_t touchModeSelectorIndex = oscProfile.touchMode == NativeTouchOnly ? NativeTouch : oscProfile.touchMode; + [self.touchModeSelector1 setSelectedSegmentIndex:touchModeSelectorIndex]; //Load old touchMode setting + [self touchModeChanged:self.touchModeSelector1]; + + [self.touchModeSelector2 addTarget:self action:@selector(touchMode2Changed:) forControlEvents:UIControlEventValueChanged]; + self.touchModeSelector2.selectedSegmentIndex = self.touchModeSelector1.selectedSegmentIndex; + + [self.enableOswForNativeTouchSwitch setOn:oscProfile.touchMode != NativeTouchOnly]; + [self enableOswForNativeTouchSwitchFlipped:self.enableOswForNativeTouchSwitch]; + + [self.pointerVelocityModeDividerSlider setValue: (uint8_t)(oscProfile.pointerVelocityModeDivider * 100) animated:NO]; // Load old setting. [self pointerVelocityModeDividerSliderMoved:self.pointerVelocityModeDividerSlider]; @@ -416,9 +428,11 @@ BOOL isCustomResolution(int resolutionSelected) { 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]; + TouchMode touchMode = [self isNotNativeTouchOnly] ? self.touchModeSelector1.selectedSegmentIndex : NativeTouchOnly; bool configNotChanged = ( - (int16_t)(oscProfile.pointerVelocityModeDivider*100) == (int16_t)(self.pointerVelocityModeDividerSlider.value) + (int)oscProfile.touchMode == touchMode + && (int16_t)(oscProfile.pointerVelocityModeDivider*100) == (int16_t)(self.pointerVelocityModeDividerSlider.value) && (int16_t)(oscProfile.touchPointerVelocityFactor*100) == (int16_t)touchPointerVelocityFactorPercent && oscProfile.useBuiltinGyro == self.gyroSourceSelector.selectedSegmentIndex == 0 && oscProfile.swapYawAndRoll == self.swapYawAndRollSwitch.isOn @@ -446,6 +460,7 @@ BOOL isCustomResolution(int resolutionSelected) { if(!configNotChanged){ oscProfile = [oscProfileMan getSelectedProfile]; + oscProfile.touchMode = (int)touchMode; oscProfile.pointerVelocityModeDivider = self.pointerVelocityModeDividerSlider.value/100; oscProfile.touchPointerVelocityFactor = touchPointerVelocityFactorPercent/100; oscProfile.useBuiltinGyro = self.gyroSourceSelector.selectedSegmentIndex == 0; @@ -863,6 +878,7 @@ BOOL isCustomResolution(int resolutionSelected) { } self.touchModeStack.hasInfoTag = YES; + self.touchModeStack.isGameProfileSetting = YES; [self addSetting:self.touchModeStack ofId:@"touchModeStack" to:touchControlSection]; self.mousePointerVelocityStack.hasDynamicLabel = YES; @@ -2396,21 +2412,10 @@ BOOL isCustomResolution(int resolutionSelected) { [self.leftClickDelaySlider addTarget:self action:@selector(leftClickDelaySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved. [self leftClickDelaySliderMoved:self.leftClickDelaySlider]; */ - - // this part will enable/disable oscSelector & the asyncNativeTouchPriority selector - uint8_t touchModeSelectorIndex = self->tempSettings.touchMode.intValue == NativeTouchOnly ? NativeTouch : self->tempSettings.touchMode.intValue; - [self.touchModeSelector1 setSelectedSegmentIndex:touchModeSelectorIndex]; //Load old touchMode setting + + // touchMode refactored to game profile system [self.touchModeSelector1 addTarget:self action:@selector(touchMode1Changed:) forControlEvents:UIControlEventValueChanged]; - [self touchModeChanged:self.touchModeSelector1]; - - [self.touchModeSelector2 addTarget:self action:@selector(touchMode2Changed:) forControlEvents:UIControlEventValueChanged]; - self.touchModeSelector2.selectedSegmentIndex = self.touchModeSelector1.selectedSegmentIndex; - - // 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];