From 715cb86ab90e77e5efe6b62a2453351e75ddefda Mon Sep 17 00:00:00 2001 From: TrueZhuangjia Date: Thu, 13 Feb 2025 21:55:45 +0800 Subject: [PATCH] - better alignment & resizing for on-screen widget view - stage manager --- .../Input/CustomOSC/LayoutOnScreenControls.m | 2 +- .../Input/CustomOSC/OSCProfilesManager.m | 4 +- .../Input/CustomOSC/OnScreenButtonState.h | 4 +- Limelight/Input/OnScreenControls.m | 2 +- Limelight/Input/OnScreenWidgetView.swift | 58 +++++++++++++------ Limelight/Input/StreamView.m | 2 +- Limelight/Limelight-Info.plist | 2 +- .../LayoutOnScreenControlsViewController.m | 2 +- 8 files changed, 50 insertions(+), 26 deletions(-) diff --git a/Limelight/Input/CustomOSC/LayoutOnScreenControls.m b/Limelight/Input/CustomOSC/LayoutOnScreenControls.m index 60741ae1..7b688e95 100644 --- a/Limelight/Input/CustomOSC/LayoutOnScreenControls.m +++ b/Limelight/Input/CustomOSC/LayoutOnScreenControls.m @@ -238,7 +238,7 @@ [[NSNotificationCenter defaultCenter] postNotificationName:@"ControllerCALayerSelected" object:layerBeingDragged]; // inform that a CALayer of onScreen controller has being selected /* save the name, position, and visibility of button being touched in array in case user wants to undo the change later */ - OnScreenButtonState *onScreenButtonState = [[OnScreenButtonState alloc] initWithButtonName:layerBeingDragged.name buttonType:GameControllerButton andPosition:layerBeingDragged.position]; + OnScreenButtonState *onScreenButtonState = [[OnScreenButtonState alloc] initWithButtonName:layerBeingDragged.name buttonType:LegacyOscButton andPosition:layerBeingDragged.position]; // add hidden attr here onScreenButtonState.isHidden = layerBeingDragged.isHidden; diff --git a/Limelight/Input/CustomOSC/OSCProfilesManager.m b/Limelight/Input/CustomOSC/OSCProfilesManager.m index 43c527b9..5274e82b 100644 --- a/Limelight/Input/CustomOSC/OSCProfilesManager.m +++ b/Limelight/Input/CustomOSC/OSCProfilesManager.m @@ -267,7 +267,7 @@ static NSMutableDictionary *OnScreenWidgetViewsDict; // save on-screen game controller buttons & sticks as buttonstate: for (CALayer *oscButtonLayer in oscButtonLayers) { - OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:oscButtonLayer.name buttonType:GameControllerButton andPosition:oscButtonLayer.position]; + OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:oscButtonLayer.name buttonType:LegacyOscButton andPosition:oscButtonLayer.position]; // add hidden attr here buttonState.isHidden = oscButtonLayer.isHidden; buttonState.oscLayerSizeFactor = [OnScreenControls getControllerLayerSizeFactor:oscButtonLayer]; @@ -284,7 +284,7 @@ static NSMutableDictionary *OnScreenWidgetViewsDict; // save on-screen widget views (keyboard & mouse command) as buttonstate: [OnScreenWidgetViewsDict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { // this dict is passed from the layout tool VC, as a static obj in this class. OnScreenWidgetView *widgetView = value; - OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.keyString buttonType:KeyboardOrMouseButton andPosition:widgetView.frame.origin]; + OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.keyString buttonType:CustomOnScreenWidget andPosition:widgetView.center]; buttonState.alias = widgetView.keyLabel; buttonState.timestamp = widgetView.timestamp; buttonState.widthFactor = widgetView.widthFactor; diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.h b/Limelight/Input/CustomOSC/OnScreenButtonState.h index 5fe3eb06..13b44d90 100644 --- a/Limelight/Input/CustomOSC/OnScreenButtonState.h +++ b/Limelight/Input/CustomOSC/OnScreenButtonState.h @@ -37,8 +37,8 @@ NS_ASSUME_NONNULL_BEGIN // @property (nonatomic, assign) BOOL hasValidPosition; typedef NS_ENUM(NSInteger, OnScreenButtonType) { - GameControllerButton, - KeyboardOrMouseButton + LegacyOscButton, + CustomOnScreenWidget }; - (id) initWithButtonName:(NSString*)name buttonType:(uint8_t)buttonType andPosition:(CGPoint)position; diff --git a/Limelight/Input/OnScreenControls.m b/Limelight/Input/OnScreenControls.m index 0ff5ff81..8853fc43 100644 --- a/Limelight/Input/OnScreenControls.m +++ b/Limelight/Input/OnScreenControls.m @@ -362,7 +362,7 @@ static float L3_Y; for (NSData *buttonStateEncoded in oscProfile.buttonStates) { OnScreenButtonState *buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil]; - if(!buttonState.isHidden && [validPositionButtonNames containsObject:buttonState.name] && (buttonState.buttonType == GameControllerButton || [profilesManager getIndexOfSelectedProfile] == 0 ) ){ + if(!buttonState.isHidden && [validPositionButtonNames containsObject:buttonState.name] && (buttonState.buttonType == LegacyOscButton || [profilesManager getIndexOfSelectedProfile] == 0 ) ){ [_activeCustomOscButtonPositionDict setObject:[NSValue valueWithCGPoint:buttonState.position] forKey:buttonState.name]; // we got a buttonname -> position dict here NSLog(@"_activeCustomOscButtonPositionDict update, button name:%@, position: %f, %f", buttonState.name, buttonState.position.x, buttonState.position.y); } diff --git a/Limelight/Input/OnScreenWidgetView.swift b/Limelight/Input/OnScreenWidgetView.swift index 0bdf5de2..c1d0c42f 100644 --- a/Limelight/Input/OnScreenWidgetView.swift +++ b/Limelight/Input/OnScreenWidgetView.swift @@ -86,7 +86,7 @@ import UIKit private var mousePointerMoved: Bool private var twoTouchesDetected: Bool - private var storedLocation: CGPoint = .zero // location from persisted data + private var storedCenter: CGPoint = .zero // location from persisted data private let minimumBorderAlpha: CGFloat = 0.19 private var defaultBorderColor: CGColor = UIColor(white: 0.2, alpha: 0.3).cgColor private let moonlightPurple: CGColor = UIColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 0.86).cgColor @@ -143,11 +143,14 @@ import UIKit } @objc public func setLocation(xOffset:CGFloat, yOffset:CGFloat) { + /* NSLayoutConstraint.activate([ - self.leadingAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: xOffset), - self.topAnchor.constraint(equalTo: self.superview!.topAnchor, constant: yOffset), + self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: xOffset), + self.centerYAnchor.constraint(equalTo: self.superview!.topAnchor, constant: yOffset), ]) - storedLocation = CGPointMake(xOffset, yOffset) + */ + storedCenter = CGPointMake(xOffset, yOffset) + center = storedCenter } @objc public func enableRelocationMode(enabled: Bool){ @@ -181,13 +184,20 @@ import UIKit // To resize the button, we must set this to false temporarily translatesAutoresizingMaskIntoConstraints = false - + // replace invalid factor values if self.widthFactor == 0 {self.widthFactor = 1.0} if self.heightFactor == 0 {self.heightFactor = 1.0} - // Constraints for resizing + + /* + NSLayoutConstraint.activate([ + self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: storedLocation.x), + self.centerYAnchor.constraint(equalTo: self.superview!.topAnchor, constant: storedLocation.y)]) + */ + + // Constraints for resizing self.changeAndActivateContraints() // Trigger layout update @@ -215,10 +225,13 @@ import UIKit } private func changeAndActivateContraints(){ - if CommandManager.oscButtonMappings.keys.contains(self.keyString) && !CommandManager.oscRectangleButtonCmds.contains(self.keyString){ // we'll make custom osc buttons round & smaller + if CommandManager.oscButtonMappings.keys.contains(self.keyString) && !CommandManager.oscRectangleButtonCmds.contains(self.keyString){ // we'll make custom osc buttons round & smaller + NSLayoutConstraint.activate([ self.widthAnchor.constraint(equalToConstant: 60 * self.widthFactor), self.heightAnchor.constraint(equalToConstant: 60 * self.heightFactor),]) + + // self.frame = CGRectMake(0, 0, 60*self.widthFactor, 60*self.heightFactor) } else if CommandManager.touchPadCmds.contains(self.keyString) { // make touchPads larger NSLayoutConstraint.activate([ @@ -230,6 +243,7 @@ import UIKit self.widthAnchor.constraint(equalToConstant: 70 * self.widthFactor), self.heightAnchor.constraint(equalToConstant: 65 * self.heightFactor),]) } + NSLayoutConstraint.activate([ label.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10), // set up label size contrain within UIView label.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10), @@ -286,6 +300,8 @@ import UIKit self.changeAndActivateContraints() + center = storedCenter //anchor the center while resizing self + setupButtonDownVisualEffectLayer(); } @@ -322,7 +338,7 @@ import UIKit // create stick indicator: the crossMark & stickBall: @objc public func showStickIndicator(){ // tell if the self button is located on the left or right - self.selfViewOnTheRight = (self.storedLocation.x > self.appWindow.frame.width*0.5) + self.selfViewOnTheRight = (self.storedCenter.x > self.appWindow.frame.width*0.5) let offsetSign = selfViewOnTheRight ? -1 : 1 let stickMarkerRelativeLocation:CGPoint if !OnScreenWidgetView.editMode { @@ -644,7 +660,10 @@ import UIKit private func setupButtonDownVisualEffectLayer() { self.buttonDownVisualEffectWidth = 8.6 - if CommandManager.oscButtonMappings.keys.contains(self.keyString) && !CommandManager.oscRectangleButtonCmds.contains(self.keyString) {self.buttonDownVisualEffectWidth = 15.3} // wider visual effect for osc buttons + if CommandManager.oscButtonMappings.keys.contains(self.keyString) && !CommandManager.oscRectangleButtonCmds.contains(self.keyString){ + if widthFactor < 1.3 {self.buttonDownVisualEffectWidth = 15.3} // wider visual effect for osc buttons + else {self.buttonDownVisualEffectWidth = 9} + } // Set the frame to be larger than the view to expand outward buttonDownVisualEffectLayer.borderWidth = 0 // set this 0 to hide the visual effect first @@ -707,7 +726,8 @@ import UIKit quickDoubleTapDetected = touchTapTimeInterval < QUICK_TAP_TIME_INTERVAL let touch = touches.first - self.touchBeganLocation = touch!.location(in: self) + if OnScreenWidgetView.editMode {self.touchBeganLocation = touch!.location(in: superview)} + else {self.touchBeganLocation = touch!.location(in: self)} self.latestTouchLocation = touchBeganLocation } @@ -783,20 +803,24 @@ import UIKit NotificationCenter.default.post(name: Notification.Name("OnScreenWidgetViewSelected"),object: self) // inform layout tool controller to fetch button size factors. self will be passed as the object of the notification if let touch = touches.first { let touchLocation = touch.location(in: superview) - storedLocation = touchLocation + storedCenter = touchLocation } } } private func moveByTouch(touch: UITouch){ - let currentLocation = touch.location(in: superview) - // let offsetX = currentLocation.x - storedLocation.x - // let offsetY = currentLocation.y - storedLocation.y - // center = CGPoint(x: center.x + offsetX, y: center.y + offsetY) - center = currentLocation; + let currentLocation: CGPoint + if OnScreenWidgetView.editMode {currentLocation = touch.location(in: superview)} + else {currentLocation = touch.location(in: self)} + + let offsetX = currentLocation.x - latestTouchLocation.x + let offsetY = currentLocation.y - latestTouchLocation.y + center = CGPoint(x: center.x + offsetX, y: center.y + offsetY) + latestTouchLocation = currentLocation + // center = currentLocation; //NSLog("x coord: %f, y coord: %f", self.frame.origin.x, self.frame.origin.y) - storedLocation = currentLocation // Update initial center for next movement + storedCenter = center // Update initial center for next movement if OnScreenWidgetView.editMode { NotificationCenter.default.post(name: Notification.Name("OnScreenWidgetMovedByTouch"), object:self) // inform the layoutOnScreenControl to update guideLines for this widget view } diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 0b211d9f..430e082a 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -392,7 +392,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; if(!OnScreenWidgetView.editMode){ // in edit mode, keyboard widget view will be updated within layoutool view controller. for (NSData *buttonStateEncoded in oscProfile.buttonStates) { OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil]; - if(buttonState.buttonType == KeyboardOrMouseButton){ + if(buttonState.buttonType == CustomOnScreenWidget){ OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias]; //reconstruct widgetView //-------------------------------------------------- onScreenControls.delegate = widgetView; // connecting onScreenControls to OnScreenWidgetView, sending the active instance for touchPad stick control diff --git a/Limelight/Limelight-Info.plist b/Limelight/Limelight-Info.plist index f29ea4d0..541e31d5 100644 --- a/Limelight/Limelight-Info.plist +++ b/Limelight/Limelight-Info.plist @@ -74,7 +74,7 @@ armv7 UIRequiresFullScreen - + UIStatusBarHidden UISupportedInterfaceOrientations diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 9f270401..cb4724c1 100644 --- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -73,7 +73,7 @@ OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile for (NSData *buttonStateEncoded in oscProfile.buttonStates) { OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil]; - if(buttonState.buttonType == KeyboardOrMouseButton){ + if(buttonState.buttonType == CustomOnScreenWidget){ OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias]; //reconstruct widgetView widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place widgetView.timestamp = buttonState.timestamp; // will be set as key in in the dict.