diff --git a/VoidLink/Input/ControllerNavigator.swift b/VoidLink/Input/ControllerNavigator.swift index 03f42703..5eea5ddd 100644 --- a/VoidLink/Input/ControllerNavigator.swift +++ b/VoidLink/Input/ControllerNavigator.swift @@ -33,13 +33,6 @@ private let settingsExcludedControllerNavigationSectionIdentifiers: Set "SettingsSectionPencil" ] -@available(iOS 13.0, *) -private final class ControllerMouseDisplayLinkTarget: NSObject { - @objc func displayLinkDidFire() { - ControllerNavigator.controllerMouseDisplayLinkDidFire() - } -} - @available(iOS 13.0, *) private final class ControllerMouseCurvePreviewView: UIView { var expo: CGFloat = 1.0 { @@ -256,8 +249,7 @@ final class ControllerNavigator: NSObject { @objc static var customPositionForStreamingRadialMenuButton: ControllerElementPosition = .left @objc static var streamingRadialMenuDelay: TimeInterval = 0 - private static let controllerMouseDisplayLinkTarget = ControllerMouseDisplayLinkTarget() - private static var controllerMouseDisplayLink: CADisplayLink? + private static var controllerMouseTimer: SafeTimer? @objc static var controllerMouseStick: ControllerElement = .rightStick @objc static var controllerMouseLeftButton: ControllerElement = .dpadRight @objc static var controllerMouseRightButton: ControllerElement = .dpadDown @@ -386,7 +378,7 @@ final class ControllerNavigator: NSObject { @objc static func startControllerMouse() { controllerMouseInputX = 0 controllerMouseInputY = 0 - startControllerMouseDisplayLink(frameRate: controllerMouseFrameRate) + startControllerMouseTimer(frameRate: controllerMouseFrameRate) ControllerUtil.stopListeningPrimaryController() listenToControllerMouse() DispatchQueue.main.async { @@ -410,87 +402,46 @@ final class ControllerNavigator: NSObject { ) } - /* - @objc static func stopControllerMouse() { - controllerMouseEnabledFlag = false - stopControllerMouseDisplayLink() - } - - @objc static func setControllerMouseEnabled(_ enabled: Bool) { - controllerMouseEnabledFlag = mapControllerToMouse && enabled - if !controllerMouseEnabledFlag { - } - } - - @objc static func isControllerMouseEnabled() -> Bool { - return controllerMouseEnabledFlag - } - */ - - - fileprivate static func controllerMouseDisplayLinkDidFire() { - guard radialMenuState == .mouseModeEnabled, - let displayLink = controllerMouseDisplayLink else { + private static func startControllerMouseTimer(frameRate: Int) { + guard radialMenuState == .mouseModeEnabled else { return } - // print("controllerMouseDisplayLinkDidFire \(CACurrentMediaTime())") - - let delay = 0.5 / Double(max(displayLink.preferredFramesPerSecond, 1)) - DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + delay) { - guard radialMenuState == .mouseModeEnabled else { return } - let moveVector = PublicUtils.controllerMouseMoveVector( - stickX: controllerMouseInputX, - stickY: controllerMouseInputY, - velocity: controllerMouseVelocity, - expo: controllerMouseExpo - ) - if moveVector.dx != 0 || moveVector.dy != 0 { + controllerMouseTimer = SafeTimer(interval: 1/TimeInterval(frameRate)) { + DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + 0.002) { + guard radialMenuState == .mouseModeEnabled else { return } + let moveVector = PublicUtils.controllerMouseMoveVector( + stickX: controllerMouseInputX, + stickY: controllerMouseInputY, + velocity: controllerMouseVelocity, + expo: controllerMouseExpo + ) + LiSendMouseMoveEvent(clampedInt16(moveVector.dx), clampedInt16(moveVector.dy)) - } - let scrollVector = PublicUtils.controllerMouseScrollVector( - stickX: controllerMouseWheelInputX, - stickY: controllerMouseWheelInputY, - multiplier: 15 - ) - if abs(scrollVector.dy) > abs(scrollVector.dx) { - LiSendHighResScrollEvent(clampedInt16(scrollVector.dy)) - } - else { - LiSendHighResHScrollEvent(clampedInt16(scrollVector.dx)) + let scrollVector = PublicUtils.controllerMouseScrollVector( + stickX: controllerMouseWheelInputX, + stickY: controllerMouseWheelInputY, + multiplier: 15 + ) + if abs(scrollVector.dy) > abs(scrollVector.dx) { + LiSendHighResScrollEvent(clampedInt16(scrollVector.dy)) + } + else { + LiSendHighResHScrollEvent(clampedInt16(scrollVector.dx)) + } } } + + controllerMouseTimer?.restart() } - private static func startControllerMouseDisplayLink(frameRate: Int) { - stopControllerMouseDisplayLink() - - let displayLink = CADisplayLink( - target: controllerMouseDisplayLinkTarget, - selector: #selector(ControllerMouseDisplayLinkTarget.displayLinkDidFire) - ) - if #available(iOS 15.0, tvOS 15.0, *) { - displayLink.preferredFrameRateRange = CAFrameRateRange( - minimum: Float(frameRate), - maximum: Float(frameRate), - preferred: Float(frameRate) - ) - } else { - displayLink.preferredFramesPerSecond = frameRate - } - displayLink.add(to: .main, forMode: .common) - controllerMouseDisplayLink = displayLink - } - - private static func stopControllerMouseDisplayLink() { + private static func stopControllerMouseTimer() { controllerMouseInputX = 0 controllerMouseInputY = 0 - controllerMouseDisplayLink?.invalidate() - controllerMouseDisplayLink = nil + controllerMouseTimer?.clean() } - private static func swappedFaceButtonIfNeeded(_ button: ControllerElement, swapABXY: Bool) -> ControllerElement { guard swapABXY else { return button } switch button { @@ -602,7 +553,7 @@ final class ControllerNavigator: NSObject { updateRadialMenu() } else { - stopControllerMouseDisplayLink() + stopControllerMouseTimer() radialMenuState = .main updateRadialMenu() } @@ -737,7 +688,7 @@ final class ControllerNavigator: NSObject { private static var radialMenuButtonPressed: Bool = false private static var radialMenuDelayTimer: SafeTimer? private static var radialMenuState: RadialMenuState = .main - private static func listenToRadialMenuButton() { + @objc static func listenToRadialMenuButton() { guard enabled else {return} guard let mainFrameVC = radialMenuDelegate as? MainFrameViewController else {return} radialMenuState = .main diff --git a/VoidLink/Input/ControllerSupport.m b/VoidLink/Input/ControllerSupport.m index c89dde30..5f426a5c 100644 --- a/VoidLink/Input/ControllerSupport.m +++ b/VoidLink/Input/ControllerSupport.m @@ -1211,7 +1211,8 @@ double rc_expo(double x, double expo) { if(![StreamFrameViewController sharedInstance]) return; MainFrameViewController* mainFrameVC =(MainFrameViewController* )ControllerUtil.delegate; if(mainFrameVC.settingsExpandedInStreamView) return; - [ControllerUtil stopListeningPrimaryControllerWithStopListenToRadialMenuButton:false]; + [ControllerUtil stopListeningPrimaryControllerWithStopListenToRadialMenuButton:true]; + if (@available(iOS 13.0, *)) [ControllerNavigator listenToRadialMenuButton]; [self listenToGCController: ControllerUtil.primaryGCController]; if (@available(iOS 13.0, *)){ NSLog(@"ControllerUtil setUINavigationDelegate %f",CACurrentMediaTime()); diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents index 50b4fb3f..083893b0 100644 --- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents +++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents @@ -40,9 +40,9 @@ - + - + diff --git a/VoidLink/Utility/GenericUtils.swift b/VoidLink/Utility/GenericUtils.swift index f68179ed..26f609d9 100644 --- a/VoidLink/Utility/GenericUtils.swift +++ b/VoidLink/Utility/GenericUtils.swift @@ -109,7 +109,7 @@ import UIKit } @objc public static func isFirstTappingGameProfileSelectorFromMainFrame() -> Bool { - let key = "hasTappedGameProfileSelectorFromMainFrame-202600801" + let key = "hasTappedGameProfileSelectorFromMainFrame-202600801-2" let defaults = UserDefaults.standard let launchedBefore = defaults.bool(forKey: key) if !launchedBefore { diff --git a/VoidLink/Utility/PublicExtensions.swift b/VoidLink/Utility/PublicExtensions.swift index 689ea133..1532038f 100644 --- a/VoidLink/Utility/PublicExtensions.swift +++ b/VoidLink/Utility/PublicExtensions.swift @@ -35,6 +35,12 @@ public extension CGPoint { } } +public extension CGVector { + var isNotZero: Bool { + dx != 0 && dx != 0 + } +} + public extension Array where Element: Equatable { @discardableResult mutating func appendIfNotContains(_ newElement: Element) -> Bool { diff --git a/VoidLink/Utility/PublicUtils.swift b/VoidLink/Utility/PublicUtils.swift index 5f3be14e..a59952ff 100644 --- a/VoidLink/Utility/PublicUtils.swift +++ b/VoidLink/Utility/PublicUtils.swift @@ -229,9 +229,14 @@ import UIKit } @objc public static func controllerMouseMoveVector(stickX: CGFloat, stickY: CGFloat, velocity: CGFloat, expo: CGFloat) -> CGVector { + let hypot = hypot(stickX, stickY) + guard hypot > 0 else {return CGVector(dx: 0, dy: 0)} + let targetHypot = controllerMouseExpoMappedOffset(hypot, expo: expo) + let targetX = targetHypot * (stickX/hypot) + let targetY = targetHypot * (stickY/hypot) return CGVector( - dx: velocity * controllerMouseExpoMappedOffset(stickX, expo: expo), - dy: -velocity * controllerMouseExpoMappedOffset(stickY, expo: expo) + dx: targetX * velocity, + dy: -targetY * velocity ) } diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index dee8518c..99e6e7a4 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1908,6 +1908,8 @@ static NSMutableSet* hostList; settings.controllerMouseStick = @(ControllerElementRightStick); settings.controllerMouseLeftButton = @(ControllerElementDpadRight); settings.controllerMouseRightButton = @(ControllerElementDpadUp); + settings.controllerMouseExpo = @(1.8); + settings.controllerMousePointerVelocity = @(15.0); if (@available(iOS 14.0, tvOS 14.0, *)) nil; else settings.appTheme = @(UIUserInterfaceStyleDark); @@ -2809,12 +2811,12 @@ static NSMutableSet* hostList; countdown:6 action:^{} completion:^{ - if(!self.gameProfileSelectorVC && !self.settingsViewController.layoutOnScreenControlsVC) [self openGameProfileSeletorWithAnimated:true]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self openGameProfileSeletorWithAnimated:false]; + }); }]; } - else if(!self.gameProfileSelectorVC && !self.settingsViewController.layoutOnScreenControlsVC) [self openGameProfileSeletorWithAnimated:true]; - else if (self.gameProfileSelectorVC) [self.gameProfileSelectorVC.profileSelectorViewController dismissViewControllerAnimated:true completion:^{}]; - else if (self.settingsViewController.layoutOnScreenControlsVC) [self.settingsViewController.layoutOnScreenControlsVC.profileSelectorViewController dismissViewControllerAnimated:true completion:^{}]; + else [self openGameProfileSeletorWithAnimated:true]; break; case RadialMenuItemHostView: [self switchToHostView]; diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index a83055b8..d63e7144 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -3236,15 +3236,17 @@ BOOL isCustomResolution(int resolutionSelected) { return; } + // self.layoutOnScreenControlsVC.view.backgroundColor = [UIColor colorWithWhite:0.55 alpha:1.0]; + self.layoutOnScreenControlsVC.view.backgroundColor = UIColor.clearColor; self.layoutOnScreenControlsVC.modalPresentationStyle = UIModalPresentationOverCurrentContext; self.layoutOnScreenControlsVC.profileSelectorLoadingMode = ProfileSelectorLoadingModeSelectProfileFromMainFrame; [self presentViewController:self.layoutOnScreenControlsVC animated:NO completion:^{ [self->_layoutOnScreenControlsVC presentProfileSelectorWith:ProfileSelectorLoadingModeSelectProfileFromMainFrame animated:animated]; }]; - _layoutOnScreenControlsVC.toolbarStackView.hidden = true; - _layoutOnScreenControlsVC.toolbarRootView.hidden = true; + self->_layoutOnScreenControlsVC.toolbarStackView.hidden = true; + self->_layoutOnScreenControlsVC.toolbarRootView.hidden = true; } - (LayoutOnScreenControlsViewController *)instantiateOscLayoutViewController {