- tool box menu improvements
- autoDock improvements - live gamepad overlay close button
This commit is contained in:
@@ -9,6 +9,12 @@
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
@objc
|
||||
protocol AbstractGamepadOverlayCloseButtonDelegate: AnyObject {
|
||||
@objc(toggleGamepadOverlayWithOverlayEnabled:)
|
||||
func toggleGamepadOverlay(withOverlayEnabled overlayEnabled: Bool)
|
||||
}
|
||||
|
||||
private enum AbstractGamepadOverlayPersistence {
|
||||
private static let defaults = UserDefaults.standard
|
||||
|
||||
@@ -126,6 +132,14 @@ private struct AbstractGamepadOverlayBridgeView: View {
|
||||
@available(iOS 13.0, *)
|
||||
@objc
|
||||
final class AbstractGamepadOverlayView: UIView {
|
||||
private enum CloseButtonMetrics {
|
||||
static let size: CGFloat = 40
|
||||
static let topInset: CGFloat = -10
|
||||
static let trailingInset: CGFloat = 0
|
||||
static let symbolPointSize: CGFloat = 16
|
||||
static let hideDelay: TimeInterval = 3
|
||||
}
|
||||
|
||||
private enum OverlayMaskMetrics {
|
||||
static let widthRatio: CGFloat = 0.85
|
||||
static let heightRatio: CGFloat = 1.03
|
||||
@@ -149,9 +163,12 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
private var panStartCenter: CGPoint = .zero
|
||||
private var activeGestureCount = 0
|
||||
private var didRestorePersistedState = false
|
||||
private var hideCloseButtonWorkItem: DispatchWorkItem?
|
||||
private let minWidth: CGFloat = 70
|
||||
private let maxWidth: CGFloat = 520
|
||||
private let doubleTapWidths: [CGFloat] = [GenericUtils.isIPhone() ? 90 : 130, GenericUtils.isIPhone() ? 165 : 200]
|
||||
private lazy var closeButton: UIButton = makeCloseButton()
|
||||
@objc weak var closeButtonDelegate: AbstractGamepadOverlayCloseButtonDelegate?
|
||||
|
||||
@objc init(frame: CGRect, usesPlayStationFaceButtons: Bool) {
|
||||
self.usesPlayStationFaceButtons = usesPlayStationFaceButtons
|
||||
@@ -189,16 +206,17 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
backgroundColor = .clear
|
||||
clipsToBounds = false
|
||||
isMultipleTouchEnabled = true
|
||||
layer.mask = visualMaskLayer
|
||||
applyScale(forTargetWidth: initialDisplayWidth)
|
||||
|
||||
addSubview(hostingController.view)
|
||||
addSubview(closeButton)
|
||||
installGesturesIfNeeded()
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
hostedView?.frame = bounds
|
||||
layoutCloseButton()
|
||||
updateVisualMask()
|
||||
restorePersistedStateIfNeeded()
|
||||
}
|
||||
@@ -237,17 +255,21 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
|
||||
@objc private func handleSingleTap(_ recognizer: UITapGestureRecognizer) {
|
||||
guard recognizer.state == .ended else { return }
|
||||
registerUserInteraction()
|
||||
presentFirstTouchTipIfNeeded()
|
||||
scheduleCloseButtonHideIfNeeded()
|
||||
}
|
||||
|
||||
@objc private func handlePan(_ recognizer: UIPanGestureRecognizer) {
|
||||
guard let superview else { return }
|
||||
switch recognizer.state {
|
||||
case .began:
|
||||
registerUserInteraction()
|
||||
presentFirstTouchTipIfNeeded()
|
||||
beginGestureSession()
|
||||
panStartCenter = center
|
||||
case .changed, .ended:
|
||||
registerUserInteraction()
|
||||
let translation = recognizer.translation(in: superview)
|
||||
center = CGPoint(x: panStartCenter.x + translation.x, y: panStartCenter.y + translation.y)
|
||||
if recognizer.state == .ended {
|
||||
@@ -263,10 +285,12 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
@objc private func handlePinch(_ recognizer: UIPinchGestureRecognizer) {
|
||||
switch recognizer.state {
|
||||
case .began:
|
||||
registerUserInteraction()
|
||||
presentFirstTouchTipIfNeeded()
|
||||
beginGestureSession()
|
||||
pinchBaseWidth = frame.width
|
||||
case .changed, .ended:
|
||||
registerUserInteraction()
|
||||
let nextWidth = max(minWidth, min(maxWidth, pinchBaseWidth * recognizer.scale))
|
||||
applyScale(forTargetWidth: nextWidth)
|
||||
if recognizer.state == .ended {
|
||||
@@ -281,14 +305,17 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
|
||||
@objc private func handleDoubleTap(_ recognizer: UITapGestureRecognizer) {
|
||||
guard recognizer.state == .ended else { return }
|
||||
registerUserInteraction()
|
||||
presentFirstTouchTipIfNeeded()
|
||||
applyScale(forTargetWidth: nextDoubleTapWidth())
|
||||
persistState()
|
||||
scheduleCloseButtonHideIfNeeded()
|
||||
}
|
||||
|
||||
private func updateVisualMask() {
|
||||
guard bounds.width > 1, bounds.height > 1 else {
|
||||
visualMaskLayer.path = nil
|
||||
hostedView?.layer.mask = nil
|
||||
return
|
||||
}
|
||||
|
||||
@@ -325,16 +352,32 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
)
|
||||
)
|
||||
visualMaskLayer.path = path.cgPath
|
||||
hostedView?.layer.mask = visualMaskLayer
|
||||
}
|
||||
|
||||
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||
bounds.contains(point)
|
||||
}
|
||||
|
||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {}
|
||||
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {}
|
||||
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {}
|
||||
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {}
|
||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesBegan(touches, with: event)
|
||||
registerUserInteraction()
|
||||
}
|
||||
|
||||
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesMoved(touches, with: event)
|
||||
registerUserInteraction()
|
||||
}
|
||||
|
||||
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesEnded(touches, with: event)
|
||||
scheduleCloseButtonHideIfNeeded()
|
||||
}
|
||||
|
||||
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesCancelled(touches, with: event)
|
||||
scheduleCloseButtonHideIfNeeded()
|
||||
}
|
||||
|
||||
private func restorePersistedStateIfNeeded() {
|
||||
guard !didRestorePersistedState,
|
||||
@@ -354,6 +397,11 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
activeGestureCount += 1
|
||||
}
|
||||
|
||||
@objc func registerUserInteraction() {
|
||||
showCloseButton()
|
||||
cancelPendingCloseButtonHide()
|
||||
}
|
||||
|
||||
private func presentFirstTouchTipIfNeeded() {
|
||||
guard GenericUtils.isFirstLaunchGamepadOverlayFeature() else { return }
|
||||
guard let presentingViewController = nearestViewController() else { return }
|
||||
@@ -383,6 +431,7 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
activeGestureCount = max(0, activeGestureCount - 1)
|
||||
guard activeGestureCount == 0 else { return }
|
||||
persistState()
|
||||
scheduleCloseButtonHideIfNeeded()
|
||||
}
|
||||
|
||||
private func persistState() {
|
||||
@@ -407,6 +456,79 @@ final class AbstractGamepadOverlayView: UIView {
|
||||
let targetScale = clampedWidth / baseRenderWidth
|
||||
transform = CGAffineTransform(scaleX: targetScale, y: targetScale)
|
||||
}
|
||||
|
||||
private func makeCloseButton() -> UIButton {
|
||||
let button = UIButton(type: .system)
|
||||
button.tintColor = UIColor.black.withAlphaComponent(0.66)
|
||||
button.backgroundColor = UIColor.white.withAlphaComponent(0.78)
|
||||
button.layer.borderWidth = 1
|
||||
button.layer.borderColor = UIColor.white.withAlphaComponent(0.9).cgColor
|
||||
button.layer.shadowColor = UIColor.black.withAlphaComponent(0.05).cgColor
|
||||
button.layer.shadowOpacity = 1
|
||||
button.layer.shadowRadius = 4
|
||||
button.layer.shadowOffset = CGSize(width: 0, height: 2)
|
||||
button.alpha = 0
|
||||
button.isHidden = true
|
||||
button.adjustsImageWhenHighlighted = false
|
||||
button.addTarget(self, action: #selector(handleCloseButtonTap), for: .touchUpInside)
|
||||
|
||||
let configuration = UIImage.SymbolConfiguration(pointSize: CloseButtonMetrics.symbolPointSize, weight: .bold)
|
||||
button.setImage(UIImage(systemName: "xmark", withConfiguration: configuration), for: .normal)
|
||||
return button
|
||||
}
|
||||
|
||||
private func layoutCloseButton() {
|
||||
let size = CGFloat(Int(CloseButtonMetrics.size/2))*2
|
||||
closeButton.frame = CGRect(
|
||||
x: bounds.width - CloseButtonMetrics.trailingInset - size,
|
||||
y: CloseButtonMetrics.topInset,
|
||||
width: size,
|
||||
height: size
|
||||
)
|
||||
closeButton.layer.cornerRadius = size * 0.5
|
||||
}
|
||||
|
||||
private func showCloseButton() {
|
||||
closeButton.isHidden = false
|
||||
guard closeButton.alpha < 1 else { return }
|
||||
UIView.animate(withDuration: 0.18) {
|
||||
self.closeButton.alpha = 1
|
||||
}
|
||||
}
|
||||
|
||||
private func hideCloseButton() {
|
||||
guard !closeButton.isHidden else { return }
|
||||
UIView.animate(
|
||||
withDuration: 0.18,
|
||||
animations: {
|
||||
self.closeButton.alpha = 0
|
||||
},
|
||||
completion: { _ in
|
||||
self.closeButton.isHidden = true
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private func cancelPendingCloseButtonHide() {
|
||||
hideCloseButtonWorkItem?.cancel()
|
||||
hideCloseButtonWorkItem = nil
|
||||
}
|
||||
|
||||
@objc func scheduleCloseButtonHideIfNeeded() {
|
||||
guard activeGestureCount == 0 else { return }
|
||||
cancelPendingCloseButtonHide()
|
||||
let workItem = DispatchWorkItem { [weak self] in
|
||||
self?.hideCloseButton()
|
||||
self?.hideCloseButtonWorkItem = nil
|
||||
}
|
||||
hideCloseButtonWorkItem = workItem
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + CloseButtonMetrics.hideDelay, execute: workItem)
|
||||
}
|
||||
|
||||
@objc private func handleCloseButtonTap() {
|
||||
cancelPendingCloseButtonHide()
|
||||
closeButtonDelegate?.toggleGamepadOverlay(withOverlayEnabled: false)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
@@ -415,4 +537,9 @@ extension AbstractGamepadOverlayView: UIGestureRecognizerDelegate {
|
||||
(gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UIPinchGestureRecognizer)
|
||||
|| (gestureRecognizer is UIPinchGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer)
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||
guard let touchedView = touch.view else { return true }
|
||||
return touchedView !== closeButton && !touchedView.isDescendant(of: closeButton)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
self.reverseGyroHoldButton = [decoder containsValueForKey:@"reverseGyroHoldButton"] ? [decoder decodeBoolForKey:@"reverseGyroHoldButton"] : false;
|
||||
self.controllerGyroSwitchHold = [decoder containsValueForKey:@"controllerGyroSwitchHold"] ? [decoder decodeIntForKey:@"controllerGyroSwitchHold"] : ControllerButtonNull;
|
||||
self.controllerGyroSwitchToggle = [decoder containsValueForKey:@"controllerGyroSwitchToggle"] ? [decoder decodeIntForKey:@"controllerGyroSwitchToggle"] : ControllerButtonNull;
|
||||
self.gamepadOverlayEnabled = [decoder containsValueForKey:@"gamepadOverlayEnabled"] ? [decoder decodeBoolForKey:@"gamepadOverlayEnabled"] : true;
|
||||
self.gamepadOverlayEnabled = [decoder containsValueForKey:@"gamepadOverlayEnabled"] ? [decoder decodeBoolForKey:@"gamepadOverlayEnabled"] : false;
|
||||
|
||||
self.pressureCurvePoints =
|
||||
[decoder containsValueForKey:@"pressureCurvePoints"]
|
||||
|
||||
@@ -143,6 +143,7 @@ import ObjectiveC.runtime
|
||||
|
||||
// for movable buttons during streaming
|
||||
@objc public var relocatedDuringStreaming: Bool = false
|
||||
@objc static var relocatedDuringStreaming: Bool = false
|
||||
|
||||
// for all touchPad or buttons hybrid with touchPads
|
||||
@objc public var hasMinStickOffset: Bool = false
|
||||
@@ -847,7 +848,7 @@ import ObjectiveC.runtime
|
||||
case "DISABLETOUCH":
|
||||
self.nonEditableWidgetLabel = SwiftLocalizationHelper.localizedString(forKey: touchDisabledFLag ? "=EnableTouch" : "=DisableTouch" )
|
||||
case "GAMEPADOVERLAY":
|
||||
self.nonEditableWidgetLabel = SwiftLocalizationHelper.localizedString(forKey: gamepadOverlayFLag ? "=GamepadOverlayOn" : "=GamepadOverlayOff" )
|
||||
self.nonEditableWidgetLabel = SwiftLocalizationHelper.localizedString(forKey: OnScreenWidgetView.gamepadOverlayFLag ? "=GamepadOverlayOn" : "=GamepadOverlayOff" )
|
||||
default:
|
||||
nonEditableWidgetLabel = ""
|
||||
}
|
||||
@@ -2715,13 +2716,13 @@ import ObjectiveC.runtime
|
||||
self.functionalButtonDelegate?.toggleTouch(disabled: touchDisabledFLag)
|
||||
}
|
||||
|
||||
@objc var gamepadOverlayFLag:Bool = false
|
||||
@objc static var gamepadOverlayFLag:Bool = false
|
||||
private func gamepadOverlayButtonUp(){
|
||||
self.relocatedDuringStreaming = true
|
||||
gamepadOverlayFLag = !gamepadOverlayFLag
|
||||
OnScreenWidgetView.gamepadOverlayFLag = !OnScreenWidgetView.gamepadOverlayFLag
|
||||
self.setupAtrributedText()
|
||||
if #available(iOS 13.0, *) {
|
||||
self.functionalButtonDelegate?.toggleGamepadOverlay(overlayEnabled: gamepadOverlayFLag)
|
||||
self.functionalButtonDelegate?.toggleGamepadOverlay(overlayEnabled: OnScreenWidgetView.gamepadOverlayFLag)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3093,6 +3094,7 @@ import ObjectiveC.runtime
|
||||
private static let autoDockExposedThickness: CGFloat = 22
|
||||
private static let autoDockVerticalInset: CGFloat = 12
|
||||
@objc var autoDockIdleDuration: TimeInterval = 0
|
||||
@objc var storedAutoDockIdleDuration: TimeInterval = 0
|
||||
private static let autoDockInitialAlpha: CGFloat = 0.8
|
||||
@objc var autoDockSettledAlpha: CGFloat = 0.2
|
||||
private static let autoDockSettledAlphaDelay: TimeInterval = 2
|
||||
@@ -3123,8 +3125,8 @@ import ObjectiveC.runtime
|
||||
private var autoDockDockedCenter: CGPoint?
|
||||
private var autoDockDockedToBottomEdge: Bool = false
|
||||
private var autoDockDistance: CGFloat = 3
|
||||
private var autoDockIsDocked: Bool = false
|
||||
private var autoDockEnabled: Bool = false
|
||||
@objc var autoDockIsDocked: Bool = false
|
||||
@objc var autoDockEnabled: Bool = false
|
||||
private var autoDockSettledAlphaTimer: Timer?
|
||||
private var autoDockOriginalBoundsSize: CGSize = .zero
|
||||
|
||||
@@ -3174,7 +3176,7 @@ import ObjectiveC.runtime
|
||||
autoDockRestartCountdownIfNeeded()
|
||||
}
|
||||
|
||||
@objc public func setAutoDockEnabled(_ enabled: Bool) {
|
||||
@objc public func setAutoDock(enabled: Bool) {
|
||||
autoDockEnabled = enabled
|
||||
if enabled {
|
||||
OnScreenWidgetView.installAutoDockIfNeeded()
|
||||
@@ -3212,7 +3214,7 @@ import ObjectiveC.runtime
|
||||
autoDockRestoreWidget(animated: animated)
|
||||
}
|
||||
|
||||
private func autoDockStopCountdown() {
|
||||
@objc func autoDockStopCountdown() {
|
||||
autoDockTimer?.invalidate()
|
||||
autoDockTimer = nil
|
||||
}
|
||||
@@ -3285,6 +3287,8 @@ import ObjectiveC.runtime
|
||||
private func autoDockWidgetToNearestEdge() {
|
||||
guard autoDockEnabled else {return}
|
||||
|
||||
autoDockIdleDuration = storedAutoDockIdleDuration
|
||||
|
||||
if !folded {
|
||||
restartAutoDockCountdown()
|
||||
return
|
||||
@@ -3342,7 +3346,10 @@ import ObjectiveC.runtime
|
||||
}
|
||||
|
||||
private func autoDockRestoreWidget(animated: Bool) {
|
||||
guard autoDockIsDocked else { return }
|
||||
guard autoDockIsDocked else {
|
||||
restartAutoDockCountdown()
|
||||
return
|
||||
}
|
||||
let restoreCenter = storedCenter
|
||||
OnScreenWidgetView.hasRestoredFromAutoDock = true
|
||||
autoDockStopCountdown()
|
||||
@@ -3475,6 +3482,7 @@ import ObjectiveC.runtime
|
||||
|| abs(widget.backgroundAlpha) < 0.1){
|
||||
widget.highlightBorder(highlighted: false)
|
||||
}
|
||||
if widget.hasNonEditableLabel {widget.setupAtrributedText()}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,7 +603,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
if(!hasFolderStateChanged) hasFolderStateChanged = widget.folded != widget.persistedFolded;
|
||||
}
|
||||
|
||||
if(relocatedWidgetSequences.count == 0 && !hasFolderStateChanged) return;
|
||||
if(relocatedWidgetSequences.count == 0 && !hasFolderStateChanged && !OnScreenWidgetView.relocatedDuringStreaming) return;
|
||||
NSLog(@"relocatedWidgetSequences.count %lu, hasFolderStateChanged %d %F", relocatedWidgetSequences.count, hasFolderStateChanged, CACurrentMediaTime());
|
||||
|
||||
oscProfileMan = [OSCProfilesManager sharedManager:self->_streamFrameTopLayerView.bounds];
|
||||
@@ -651,7 +651,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
if(![self isOnScreenWidgetEnabled]) return;
|
||||
|
||||
OnScreenWidgetView.buttonVisualFeedbackEnabled = self->settings.buttonVisualFeedback;
|
||||
|
||||
OnScreenWidgetView.gamepadOverlayFLag = oscProfile.gamepadOverlayEnabled;
|
||||
OnScreenWidgetView.relocatedDuringStreaming = false;
|
||||
|
||||
bool hasLegacyWidget = false;
|
||||
if(reload && !OnScreenWidgetView.editMode){
|
||||
// remove all keyboard widget views first
|
||||
@@ -675,6 +677,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
widgetView.sequenceSet = buttonState.sequenceSet;
|
||||
widgetView.parentSequence = buttonState.parentSequence;
|
||||
widgetView.autoDockIdleDuration = buttonState.autoDockTimer;
|
||||
widgetView.storedAutoDockIdleDuration = widgetView.autoDockIdleDuration;
|
||||
widgetView.autoDockSettledAlpha = buttonState.dockedAlpha;
|
||||
widgetView.folded = buttonState.folded;
|
||||
widgetView.persistedFolded = buttonState.folded;
|
||||
@@ -723,10 +726,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
[widgetView setupAutoTapTimer];
|
||||
[widgetView setupInertialScrollerWithFps:self->settings.framerate.intValue];
|
||||
|
||||
widgetView.gamepadOverlayFLag = oscProfile.gamepadOverlayEnabled;
|
||||
[widgetView setupAtrributedText];
|
||||
|
||||
if(widgetView.isFolder && widgetView.parentSequence<0 && widgetView.autoDockIdleDuration>0) [widgetView setAutoDockEnabled:true];
|
||||
if(widgetView.isFolder && widgetView.parentSequence<0 && widgetView.autoDockIdleDuration>0) [widgetView setAutoDockWithEnabled:true];
|
||||
|
||||
if(sequenceGenerated){
|
||||
// NSLog(@"widgetView.sequence %d %f", widgetView.sequence, CACurrentMediaTime());
|
||||
|
||||
@@ -213,16 +213,20 @@ import Foundation
|
||||
return CGFloat(Double(str) ?? 0)
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
@objc static func isLandscape() -> Bool {
|
||||
guard let windowScene = UIApplication.shared.connectedScenes
|
||||
.compactMap({ $0 as? UIWindowScene })
|
||||
.first(where: { $0.activationState == .foregroundActive })
|
||||
else {
|
||||
return false
|
||||
if #available(iOS 13.0, *) {
|
||||
guard let windowScene = UIApplication.shared.connectedScenes
|
||||
.compactMap({ $0 as? UIWindowScene })
|
||||
.first(where: { $0.activationState == .foregroundActive })
|
||||
else {return false}
|
||||
return windowScene.interfaceOrientation.isLandscape
|
||||
}
|
||||
|
||||
return windowScene.interfaceOrientation.isLandscape
|
||||
else {return GenericUtils.screenWidth > GenericUtils.screenHeight}
|
||||
}
|
||||
|
||||
@objc static func viewIsLandscape(_ view: UIView?) -> Bool {
|
||||
guard let view else {return false}
|
||||
return view.bounds.width > view.bounds.height
|
||||
}
|
||||
|
||||
@objc static var screenWidth: CGFloat {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
@interface StreamFrameViewController : GCEventViewController <ConnectionCallbacks, ControllerSupportDelegate, UserInteractionDelegate, UIScrollViewDelegate, AVPictureInPictureControllerDelegate>
|
||||
#else
|
||||
@interface StreamFrameViewController : UIViewController <ConnectionCallbacks, ControllerSupportDelegate, UserInteractionDelegate, UIScrollViewDelegate, ToolboxSpecialEntryDelegate, AVPictureInPictureControllerDelegate, OnScreenFunctionalButtonDelegate>
|
||||
@interface StreamFrameViewController : UIViewController <ConnectionCallbacks, ControllerSupportDelegate, UserInteractionDelegate, UIScrollViewDelegate, ToolboxSpecialEntryDelegate, AVPictureInPictureControllerDelegate, OnScreenFunctionalButtonDelegate, AbstractGamepadOverlayCloseButtonDelegate>
|
||||
|
||||
#endif
|
||||
@property (nonatomic, strong) StreamManager* streamMan;
|
||||
@@ -48,6 +48,7 @@
|
||||
- (void)setUserInteractionEnabledForStreamView:(bool)enabled;
|
||||
- (bool)shallDisableGyroHotSwitch;
|
||||
- (void)loadGameProfileConfigs:(OSCProfile* )profile;
|
||||
- (void)toggleGamepadOverlayWithOverlayEnabled:(BOOL)overlayEnabled API_AVAILABLE(ios(13.0));
|
||||
- (void)loadAbstractGamepadOverlayIfNeeded API_AVAILABLE(ios(13.0));
|
||||
|
||||
@end
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
- (id)initWithRefreshRate:(float)arg1 videoDynamicRange:(int)arg2;
|
||||
@end
|
||||
|
||||
|
||||
@implementation StreamFrameViewController {
|
||||
ControllerSupport *_controllerSupport;
|
||||
TemporarySettings *_settings;
|
||||
@@ -1750,6 +1751,16 @@
|
||||
for(OnScreenWidgetView* widget in OnScreenWidgetView.mapping.allValues){
|
||||
CGPoint oldCenter = widget.center;
|
||||
CGPoint oldStoredCenter = widget.storedCenter;
|
||||
|
||||
if(widget.autoDockEnabled){
|
||||
widget.autoDockIdleDuration = fmax(widget.autoDockIdleDuration, 2.0);
|
||||
[widget autoDockStopCountdown];
|
||||
}
|
||||
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC));
|
||||
dispatch_after(delayTime, dispatch_get_main_queue(), ^{
|
||||
if(widget.autoDockEnabled) [widget restoreFromAutoDockWithAnimated:true];
|
||||
});
|
||||
|
||||
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
|
||||
widget.center = CGPointMake(oldCenter.x * scaleX,oldCenter.y * scaleY);
|
||||
widget.storedCenter = CGPointMake(oldStoredCenter.x * scaleX,oldStoredCenter.y * scaleY);
|
||||
@@ -1793,6 +1804,9 @@
|
||||
}
|
||||
|
||||
- (void)toggleGamepadOverlayWithOverlayEnabled:(BOOL)overlayEnabled API_AVAILABLE(ios(13.0)){
|
||||
OnScreenWidgetView.gamepadOverlayFLag = overlayEnabled;
|
||||
OnScreenWidgetView.relocatedDuringStreaming = true;
|
||||
|
||||
if(overlayEnabled) [self loadAbstractGamepadOverlayIfNeeded];
|
||||
else {
|
||||
[_virtualGamepadOverlay removeFromSuperview];
|
||||
@@ -1819,9 +1833,12 @@
|
||||
CGRect overlayFrame = CGRectMake(0, 0, standardWidth, standardhHeight);
|
||||
|
||||
AbstractGamepadOverlayView *overlayView = [[AbstractGamepadOverlayView alloc] initWithFrame:overlayFrame usesPlayStationFaceButtons:!usesXboxFaceButtons];
|
||||
overlayView.closeButtonDelegate = self;
|
||||
overlayView.center = CGPointMake(self.view.bounds.size.width-standardWidth/2-20, self.view.bounds.size.height-standardhHeight/2-20);
|
||||
overlayView.userInteractionEnabled = YES;
|
||||
[self.view addSubview:overlayView];
|
||||
[overlayView registerUserInteraction];
|
||||
[overlayView scheduleCloseButtonHideIfNeeded];
|
||||
|
||||
self->_virtualGamepadOverlay = overlayView;
|
||||
});
|
||||
|
||||
@@ -83,6 +83,19 @@ import UIKit
|
||||
//setupConstraints()
|
||||
}
|
||||
|
||||
public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+0.2) {
|
||||
self.pinButton.isHidden = !GenericUtils.viewIsLandscape(self.view) && GenericUtils.isIPhone()
|
||||
}
|
||||
|
||||
view.setNeedsUpdateConstraints()
|
||||
coordinator.animate(alongsideTransition: { _ in
|
||||
self.view.layoutIfNeeded()
|
||||
})
|
||||
}
|
||||
|
||||
private func setupViews() {
|
||||
contentView = UIView(frame: self.view.frame)
|
||||
|
||||
@@ -129,6 +142,7 @@ import UIKit
|
||||
contentView.addSubview(editButton)
|
||||
// contentView.addSubview(exitButton)
|
||||
contentView.addSubview(pinButton)
|
||||
pinButton.isHidden = !GenericUtils.isLandscape()
|
||||
|
||||
self.view.addSubview(contentView)
|
||||
|
||||
@@ -149,6 +163,18 @@ import UIKit
|
||||
private func isIPhone()->Bool {
|
||||
return UIDevice.current.userInterfaceIdiom == .phone
|
||||
}
|
||||
|
||||
private func contentWidthMultiplier() -> CGFloat {
|
||||
/*
|
||||
if isIPhone() && GenericUtils.viewIsLandscape(self.view) {
|
||||
return 0.85
|
||||
}*/
|
||||
|
||||
return isIPhone()
|
||||
? (GenericUtils.viewIsLandscape(self.view) ? 0.6 : 0.85)
|
||||
: (GenericUtils.viewIsLandscape(self.view) ? 0.6 : 0.85)
|
||||
}
|
||||
|
||||
|
||||
@objc public func setupConstraints() {
|
||||
|
||||
@@ -167,7 +193,7 @@ import UIKit
|
||||
NSLayoutConstraint.activate([
|
||||
|
||||
// Set the width and height of the view
|
||||
contentView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: isIPhone() ? 0.6 : 0.52),
|
||||
contentView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: contentWidthMultiplier()),
|
||||
contentView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.93),
|
||||
// Set the width and height of the view
|
||||
//view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 60),
|
||||
|
||||
Reference in New Issue
Block a user