- on-screen button & on-screen controller resize test

This commit is contained in:
TrueZhuangjia committed 2024-09-21 22:48:16 +08:00
1 parent e05b626d51
commit 39b8429998
12 files changed
+317 -34

No files matched your search

@@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport
streamConfig:(StreamConfiguration*)streamConfig oscLevel:(int)oscLevel;
- (CALayer*) buttonLayerFromName:(NSString*)name;
- (CALayer*) controllerLayerFromName:(NSString*)name;
- (BOOL) isLayer:(CALayer*)layer hoveringOverButton:(UIButton*)button;
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@@ -113,7 +113,7 @@
}
/* returns reference to button layer object given the button's name*/
- (CALayer*)buttonLayerFromName: (NSString*)name {
- (CALayer*)controllerLayerFromName: (NSString*)name {
for (CALayer *buttonLayer in self.OSCButtonLayers) {
if ([buttonLayer.name isEqualToString:name]) {
@@ -159,10 +159,21 @@
else if (layer == self._leftStick) { // only let user drag left stick's background, not the inner analog stick itself
layerBeingDragged = self._leftStickBackground;
}
else { // let user drag whatever other valid button they're touching
else if(layer == self._aButton ||
layer == self._bButton ||
layer == self._xButton ||
layer == self._yButton ||
layer == self._l1Button ||
layer == self._l2Button ||
layer == self._r1Button ||
layer == self._r2Button ||
layer == self._selectButton ||
layer == self._startButton){ // we must iterates all the controller button layers manually here, to prevent other widgets being dragged accidently
layerBeingDragged = layer;
}
[[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];
// add hidden attr here
@@ -241,4 +252,5 @@
@end
@@ -200,7 +200,7 @@ static NSMutableDictionary *onScreenButtonViewsDict;
- (bool) updateSelectedProfile:(NSMutableArray *) oscButtonLayers {
NSMutableArray* buttonStatesEncoded = [self convertOnscreenButtonsToButtonStates:oscButtonLayers];
NSMutableArray* buttonStatesEncoded = [self convertOnScreenControllerAndButtonsToButtonStates:oscButtonLayers];
if([self getIndexOfSelectedProfile]==0) return false;
OSCProfile *newProfile = [[OSCProfile alloc] initWithName:[self getSelectedProfile].name
buttonStates:buttonStatesEncoded isSelected:YES]; // create a new 'OSCProfile'. Set the array of encoded button states created above to the 'buttonStates' property of the new profile, along with a 'name'. Set 'isSelected' argument to YES which will set this saved profile as the one that will show up in the game stream view
@@ -217,7 +217,7 @@ static NSMutableDictionary *onScreenButtonViewsDict;
- (void) saveProfileWithName:(NSString*)name andButtonLayers:(NSMutableArray *)oscButtonLayers {
NSMutableArray* buttonStatesEncoded = [self convertOnscreenButtonsToButtonStates:oscButtonLayers];
NSMutableArray* buttonStatesEncoded = [self convertOnScreenControllerAndButtonsToButtonStates:oscButtonLayers];
OSCProfile *newProfile = [[OSCProfile alloc] initWithName:name
buttonStates:buttonStatesEncoded isSelected:YES]; // create a new 'OSCProfile'. Set the array of encoded button states created above to the 'buttonStates' property of the new profile, along with a 'name'. Set 'isSelected' argument to YES which will set this saved profile as the one that will show up in the game stream view
/* set all saved OSCProfiles 'isSelected' property to NO since the new profile you're adding will be set as the selected profile */
@@ -243,7 +243,7 @@ static NSMutableDictionary *onScreenButtonViewsDict;
}
- (NSMutableArray* ) convertOnscreenButtonsToButtonStates:(NSMutableArray *) oscButtonLayers {
- (NSMutableArray* ) convertOnScreenControllerAndButtonsToButtonStates:(NSMutableArray *) oscButtonLayers {
/* iterate through each OSC button the user sees on screen, create an 'OnScreenButtonState' object from each button, encode each object, and then add each object to an array */
/*
NSSet *validPositionButtonNames = [NSSet setWithObjects:
@@ -262,6 +262,8 @@ static NSMutableDictionary *onScreenButtonViewsDict;
@"startButton",
nil]; */
NSMutableArray *buttonStatesEncoded = [[NSMutableArray alloc] init];
// 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];
@@ -271,12 +273,14 @@ static NSMutableDictionary *onScreenButtonViewsDict;
[buttonStatesEncoded addObject: buttonStateEncoded];
}
// save keyboard button as buttonstate, this is for the new onscreen keyboard buttons:
// save on-screen button views (keyboard & mouse command) as buttonstate:
[onScreenButtonViewsDict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { // this dict is passed from the layout tool VC, as a static obj in this class.
OnScreenButtonView *buttonView = value;
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:buttonView.keyString buttonType:KeyboardOrMouseButton andPosition:buttonView.frame.origin];
buttonState.alias = buttonView.keyLabel;
buttonState.timestamp = buttonView.timestamp;
buttonState.widthFactor = buttonView.widthFactor;
buttonState.heightFactor = buttonView.heightFactor;
NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
[buttonStatesEncoded addObject: buttonStateEncoded];
}];
@@ -25,6 +25,9 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) BOOL isHidden;
@property (nonatomic, assign) uint8_t buttonType;
@property (nonatomic, assign) NSTimeInterval timestamp;
@property (nonatomic, assign) CGFloat widthFactor; // for OnScreenButtonView
@property (nonatomic, assign) CGFloat heightFactor; // for OnScreenButtonView
// @property (nonatomic, assign) BOOL hasValidPosition;
typedef NS_ENUM(NSInteger, OnScreenButtonType) {
@@ -33,6 +33,8 @@
[encoder encodeInt:self.buttonType forKey:@"buttonType"];
[encoder encodeCGPoint:self.position forKey:@"position"];
[encoder encodeBool:self.isHidden forKey:@"isHidden"];
[encoder encodeFloat:self.widthFactor forKey:@"widthFactor"];
[encoder encodeFloat:self.heightFactor forKey:@"heightFactor"];
}
- (id) initWithCoder:(NSCoder*)decoder {
@@ -43,6 +45,8 @@
self.buttonType = [decoder decodeIntForKey:@"buttonType"];
self.position = [decoder decodeCGPointForKey:@"position"];
self.isHidden = [decoder decodeBoolForKey:@"isHidden"];
self.widthFactor = [decoder decodeFloatForKey:@"widthFactor"];
self.heightFactor = [decoder decodeFloatForKey:@"heightFactor"];
}
return self;
+42 -6
View File
@@ -16,8 +16,9 @@ import UIKit
@objc public var keyString: String
@objc public var timestamp: TimeInterval
@objc public var pressed: Bool
@objc public var widthFactor: CGFloat
@objc public var heightFactor: CGFloat
private let label: UILabel
private let originalBackgroundColor: UIColor
private var storedLocation: CGPoint = .zero
@@ -30,6 +31,8 @@ import UIKit
self.originalBackgroundColor = UIColor(white: 0.2, alpha: 0.7)
self.timestamp = 0
self.pressed = false
self.widthFactor = 1.0
self.heightFactor = 1.0
super.init(frame: .zero)
setupView()
}
@@ -38,7 +41,7 @@ import UIKit
fatalError("init(coder:) has not been implemented")
}
@objc public func setKeyLocation(xOffset:CGFloat, yOffset:CGFloat) {
@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),
@@ -49,7 +52,38 @@ import UIKit
OnScreenButtonView.editMode = enabled
}
private func setupView() {
@objc public func resizeButtonView(){
guard let superview = superview else { return }
// Deactivate existing constraints if necessary
NSLayoutConstraint.deactivate(self.constraints)
// 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
let newWidthConstraint = self.widthAnchor.constraint(equalToConstant: 70 * self.widthFactor)
let newHeightConstraint = self.heightAnchor.constraint(equalToConstant: 65 * self.heightFactor)
NSLayoutConstraint.activate([
self.widthAnchor.constraint(equalToConstant: 70 * self.widthFactor),
self.heightAnchor.constraint(equalToConstant: 65 * self.heightFactor),
])
// Trigger layout update
superview.layoutIfNeeded()
// Re-setup buttonView style
setupView()
}
@objc public func setupView() {
label.text = self.keyLabel
label.font = UIFont.boldSystemFont(ofSize: 19)
label.translatesAutoresizingMaskIntoConstraints = false
@@ -77,8 +111,8 @@ import UIKit
NSLayoutConstraint.activate([
//self.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.088),
//self.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height * 0.1),
self.widthAnchor.constraint(equalToConstant: 70),
self.heightAnchor.constraint(equalToConstant: 65),
self.widthAnchor.constraint(equalToConstant: 70 * self.widthFactor),
self.heightAnchor.constraint(equalToConstant: 65 * self.widthFactor),
])
NSLayoutConstraint.activate([
@@ -135,7 +169,9 @@ import UIKit
}
}
}
else {
// here is in edit mode:
else{
NotificationCenter.default.post(name: Notification.Name("OnScreenButtonViewSelected"),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
+20 -1
View File
@@ -36,10 +36,28 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
// @property (nonatomic, assign) CustomTapGestureRecognizer* mouseRightClickTapRecognizer; // this object will be passed to onscreencontrols class for areVirtualControllerTaps flag setting
@property (nonatomic, assign) bool isLayingOut;
//@property (nonatomic) NSMutableSet<UITouch* >* touchesCapturedByOnScreenButtons;
@property (nonatomic, assign) CGRect standardRoundButtonBounds;
@property (nonatomic, assign) CGRect standardRectangleButtonBounds;
@property (nonatomic, assign) CGRect standardStickBounds;
@property (nonatomic, assign) CGRect standardStickBackgroundBounds;
@property (nonatomic, assign) CGRect standardUpDownButtonBounds;
@property (nonatomic, assign) CGRect standardLeftRightButtonBounds;
@property (nonatomic, assign) CGPoint leftStickCenter;
@property (nonatomic, assign) CGPoint rightStickCenter;
@property CALayer* _aButton;
@property (nonatomic, assign) CGFloat aButtonSizeFactor;
@property CALayer* _bButton;
@property (nonatomic, assign) CGFloat bButtonSizeFactor;
@property CALayer* _xButton;
@property (nonatomic, assign) CGFloat xButtonSizeFactor;
@property CALayer* _yButton;
@property (nonatomic, assign) CGFloat yButtonSizeFactor;
@property CALayer* _startButton;
@property CALayer* _selectButton;
@property CALayer* _r1Button;
@@ -56,7 +74,7 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
@property CALayer* _leftStick;
@property CALayer* _rightStickBackground;
@property CALayer* _rightStick;
@property CALayer *_dPadBackground; // parent layer that contains each individual dPad button so user can drag them around the screen together
@property CALayer* _dPadBackground; // parent layer that contains each individual dPad button so user can drag them around the screen together
@property float D_PAD_CENTER_X;
@property float D_PAD_CENTER_Y;
@@ -81,5 +99,6 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
- (void) setDPadCenter;
- (void) setAnalogStickPositions;
- (void) positionOSCButtons;
- (void) resizeControllerLayersWith:(CALayer*)layer and:(CGFloat)sizeFactor;
@end
+93
View File
@@ -233,6 +233,14 @@ static float L3_Y;
_downButton.name = @"downButton";
_leftButton.name = @"leftButton";
_standardRoundButtonBounds = CGRectMake(0, 0, [UIImage imageNamed:@"AButton"].size.width, [UIImage imageNamed:@"AButton"].size.height);
_standardRectangleButtonBounds = CGRectMake(0, 0, [UIImage imageNamed:@"StartButton"].size.width, [UIImage imageNamed:@"StartButton"].size.height);
_standardStickBounds = CGRectMake(0, 0, [UIImage imageNamed:@"StickInner"].size.width * 1.33, [UIImage imageNamed:@"StickInner"].size.height * 1.33);
_standardStickBackgroundBounds = CGRectMake(0, 0, [UIImage imageNamed:@"StickOuter"].size.width * 1.10, [UIImage imageNamed:@"StickOuter"].size.height * 1.10);
_standardUpDownButtonBounds = CGRectMake(0, 0, [UIImage imageNamed:@"UpButton"].size.width, [UIImage imageNamed:@"UpButton"].size.height);
_standardLeftRightButtonBounds = CGRectMake(0, 0, [UIImage imageNamed:@"LeftButton"].size.width, [UIImage imageNamed:@"LeftButton"].size.height);
_activeCustomOscButtonPositionDict = [[NSMutableDictionary alloc] init];
touchAddrsCapturedByOnScreenControls = [[NSMutableSet alloc] init];
@@ -1429,5 +1437,90 @@ static float L3_Y;
}
- (void) resizeControllerLayersWith:(CALayer*)layer and:(CGFloat)sizeFactor{
// CALayer* superLayer = layer.superlayer;
// if(layerBeingDragged.name == @"")
if (layer == self._aButton ||
layer == self._bButton ||
layer == self._xButton ||
layer == self._yButton ||
layer == self._l1Button ||
layer == self._l2Button ||
layer == self._r1Button ||
layer == self._r2Button){
layer.bounds = CGRectMake(0, 0, self.standardRoundButtonBounds.size.width * sizeFactor, self.standardRoundButtonBounds.size.height * sizeFactor);
}
if (layer == self._selectButton ||
layer == self._startButton) {
layer.bounds = CGRectMake(0, 0, self.standardRectangleButtonBounds.size.width * sizeFactor, self.standardRectangleButtonBounds.size.height * sizeFactor);
}
if (layer == self._rightStickBackground) {
// Resize the rightStick & Background bounds
self._rightStickBackground.bounds = CGRectMake(0, 0, self.standardStickBackgroundBounds.size.width * sizeFactor, self.standardStickBackgroundBounds.size.height * sizeFactor);
self._rightStick.bounds = CGRectMake(0, 0, self.standardStickBounds.size.width * sizeFactor, self.standardStickBounds.size.height * sizeFactor);
// Retrieve the current frame to account for transformations, this will update the coords for new position CGPointMake
CGRect transformedBackgroundFrame = self._rightStickBackground.frame;
// Explicitly adjust the position of _rightStickBackground using the transformed frame
self._rightStickBackground.position = CGPointMake(CGRectGetMidX(transformedBackgroundFrame), CGRectGetMidY(transformedBackgroundFrame));
// Update the position of _rightStick to match the new center of the transformed _rightStickBackground
self._rightStick.position = CGPointMake(CGRectGetMidX(self._rightStickBackground.bounds), CGRectGetMidY(self._rightStickBackground.bounds));
}
if (layer == self._leftStickBackground){
// Resize the rightStick & Background bounds
self._leftStickBackground.bounds = CGRectMake(0, 0, self.standardStickBackgroundBounds.size.width * sizeFactor, self.standardStickBackgroundBounds.size.height * sizeFactor);
self._leftStick.bounds = CGRectMake(0, 0, self.standardStickBounds.size.width * sizeFactor, self.standardStickBounds.size.height * sizeFactor);
// Retrieve the current frame to account for transformations, this will update the coords for new position CGPointMake
CGRect transformedBackgroundFrame = self._leftStickBackground.frame;
// Explicitly adjust the position of _rightStickBackground using the transformed frame
self._leftStickBackground.position = CGPointMake(CGRectGetMidX(transformedBackgroundFrame), CGRectGetMidY(transformedBackgroundFrame));
// Update the position of _rightStick to match the new center of the transformed _rightStickBackground
self._leftStick.position = CGPointMake(CGRectGetMidX(self._leftStickBackground.bounds), CGRectGetMidY(self._leftStickBackground.bounds));
}
if (layer == self._dPadBackground){
// Calculate the distances of each button from the shared center based on their transformed positions
CGFloat newDPadDistFactor = 0.1/sizeFactor;
// 1. Resize and reposition the Down button
CGFloat newLongSideLength = _standardLeftRightButtonBounds.size.width * sizeFactor;
CGFloat newShortSideLength = _standardLeftRightButtonBounds.size.height * sizeFactor;
CGPoint sharedCenter = CGPointMake(_standardLeftRightButtonBounds.size.width, _standardLeftRightButtonBounds.size.width); // this will anchor the center point of the dPad
// Resize and reposition the Up button
_upButton.anchorPoint = CGPointMake(0.5, 1 + newDPadDistFactor);
_upButton.bounds = CGRectMake(0, 0, newShortSideLength, newLongSideLength);
_upButton.position = CGPointMake(sharedCenter.x, sharedCenter.y);
// Resize and reposition the Down button
_downButton.anchorPoint = CGPointMake(0.5, 0 - newDPadDistFactor);
_downButton.bounds = CGRectMake(0, 0, newShortSideLength, newLongSideLength);
_downButton.position = CGPointMake(sharedCenter.x, sharedCenter.y);
// Resize and reposition the Right button
_rightButton.anchorPoint = CGPointMake(0 - newDPadDistFactor, 0.5);
_rightButton.bounds = CGRectMake(0, 0, newLongSideLength, newShortSideLength);
_rightButton.position = CGPointMake(sharedCenter.x, sharedCenter.y);
// Resize and reposition the Left button
_leftButton.anchorPoint = CGPointMake(1 + newDPadDistFactor, 0.5);
_leftButton.bounds = CGRectMake(0, 0, newLongSideLength, newShortSideLength);
_leftButton.position = CGPointMake(sharedCenter.x, sharedCenter.y);
}
}
@end
+4 -1
View File
@@ -383,9 +383,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
if(buttonState.buttonType == KeyboardOrMouseButton){
OnScreenButtonView* buttonView = [[OnScreenButtonView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias]; //reconstruct buttonView
buttonView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
buttonView.widthFactor = buttonState.widthFactor;
buttonView.heightFactor = buttonState.heightFactor;
// Add the buttonView to the view controller's view
[self->streamFrameTopLayerView addSubview:buttonView]; // add keyboard button to the stream frame view. must add it to the target view before setting location.
[buttonView setKeyLocationWithXOffset:buttonState.position.x yOffset:buttonState.position.y];
[buttonView setLocationWithXOffset:buttonState.position.x yOffset:buttonState.position.y];
[buttonView resizeButtonView]; // resize must be called after relocation
}
}
}