implementation of round custom osc buttons in OnscreenButtonView.swift

This commit is contained in:
TrueZhuangjia committed 2025-01-26 15:17:20 +08:00
1 parent 4e85d3d079
commit 5747656be7
5 files changed
+119 -72

No files matched your search

+19 -2
View File
@@ -56,9 +56,26 @@ import UIKit
"M_RIGHT" : BUTTON_RIGHT, "M_RIGHT" : BUTTON_RIGHT,
"M_X1" : BUTTON_X1, "M_X1" : BUTTON_X1,
"M_X2" : BUTTON_X2] "M_X2" : BUTTON_X2]
@objc public static let oscButtonMappings: [String: Int32] = ["OSCA" : A_FLAG,
"OSCB" : B_FLAG,
"OSCX" : X_FLAG,
"OSCY" : Y_FLAG,
"OSCL1" : LB_FLAG,
"OSCR1" : RB_FLAG,
"OSCL3" : LS_CLK_FLAG,
"OSCR3" : RS_CLK_FLAG,
"OSCSTART" : PLAY_FLAG,
"OSCSELECT" : BACK_FLAG,
"OSCUP" : UP_FLAG,
"OSCDOWN" : DOWN_FLAG,
"OSCLEFT" : LEFT_FLAG,
"OSCRIGHT" : RIGHT_FLAG,
"OSCL2" : 0,
"OSCR2" : 0]
@objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "MousePAD", "DPAD", "WASDPAD", "ARROWPAD"] @objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "MousePAD", "DPAD", "WASDPAD", "ARROWPAD"]
static let keyboardButtonMappings: [String: Int16] = [ static let keyboardButtonMappings: [String: Int16] = [
// Windows Key Codes // Windows Key Codes
"CTRL": 0x11, // VK_CONTROL "CTRL": 0x11, // VK_CONTROL
+85 -69
View File
@@ -54,7 +54,8 @@ import UIKit
private let stickBallColor: CGColor = UIColor(white: 1, alpha: 0.75).cgColor private let stickBallColor: CGColor = UIColor(white: 1, alpha: 0.75).cgColor
private var stickInputScale: CGFloat = 30 private var stickInputScale: CGFloat = 30
private let borderLayer = CAShapeLayer() private let buttonDownVisualEffectLayer = CAShapeLayer()
private var buttonDownVisualEffectWidth: CGFloat
private var upIndicator = CAShapeLayer() private var upIndicator = CAShapeLayer()
private var downIndicator = CAShapeLayer() private var downIndicator = CAShapeLayer()
@@ -87,6 +88,7 @@ import UIKit
self.quickDoubleTapDetected = false self.quickDoubleTapDetected = false
self.touchTapTimeInterval = 100 self.touchTapTimeInterval = 100
self.touchTapTimeStamp = 100 self.touchTapTimeStamp = 100
self.buttonDownVisualEffectWidth = 0
super.init(frame: .zero) super.init(frame: .zero)
upIndicator = createLrudDirectionLayer() upIndicator = createLrudDirectionLayer()
@@ -125,22 +127,7 @@ import UIKit
else{ else{
self.backgroundAlpha = 0.5 self.backgroundAlpha = 0.5
} }
self.tweakAlpha()
// setup default border from self.backgroundAlpha
var borderAlpha = 1.15 * self.backgroundAlpha
if borderAlpha < minimumBorderAlpha {
borderAlpha = minimumBorderAlpha
}
defaultBorderColor = UIColor(white: 0.2, alpha: borderAlpha).cgColor
self.layer.borderColor = defaultBorderColor
if CommandManager.touchPadCmds.contains(self.keyString){
self.backgroundColor = UIColor.clear // make touchPad transparent
self.layer.borderColor = UIColor(white: 0.2, alpha: borderAlpha - 0.2).cgColor // reduce border alpha for touchPad
}
else{ // backgroundColor works for buttons other than touch pad
self.backgroundColor = UIColor(white: 0.2, alpha: self.backgroundAlpha - 0.18) // offset to be consistent with onScreen controller layer opacity
}
} }
@objc public func resizeButtonView(){ @objc public func resizeButtonView(){
@@ -159,14 +146,8 @@ import UIKit
if self.heightFactor == 0 {self.heightFactor = 1.0} if self.heightFactor == 0 {self.heightFactor = 1.0}
// Constraints for resizing // 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),
])
self.changeAndActivateContraints()
// Trigger layout update // Trigger layout update
superview.layoutIfNeeded() superview.layoutIfNeeded()
@@ -175,9 +156,43 @@ import UIKit
setupView() setupView()
} }
private func tweakAlpha(){
// setup default border from self.backgroundAlpha
let realBackgroundAlpha = self.backgroundAlpha - 0.18 // offset to be consistent with legacy onScreen controller layer opacity
self.backgroundColor = UIColor(white: 0.2, alpha: realBackgroundAlpha) // offset to be consistent with legacy onScreen controller layer opacity
var borderAlpha = realBackgroundAlpha * 1.01
if borderAlpha < minimumBorderAlpha {
borderAlpha = minimumBorderAlpha
}
defaultBorderColor = UIColor(white: 0.2, alpha: borderAlpha).cgColor
self.layer.borderColor = defaultBorderColor
if CommandManager.touchPadCmds.contains(self.keyString){
self.backgroundColor = UIColor.clear // make touchPad transparent
self.layer.borderColor = UIColor(white: 0.2, alpha: borderAlpha - 0.15).cgColor // reduced border alpha for touchPad
}
}
private func changeAndActivateContraints(){
if CommandManager.oscButtonMappings.keys.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),
])}
else{
NSLayoutConstraint.activate([
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),
label.centerXAnchor.constraint(equalTo: centerXAnchor),
label.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
@objc public func setupView() { private func setupView() {
label.text = self.keyLabel label.text = self.keyLabel
label.font = UIFont.boldSystemFont(ofSize: 19) label.font = UIFont.boldSystemFont(ofSize: 19)
label.translatesAutoresizingMaskIntoConstraints = false label.translatesAutoresizingMaskIntoConstraints = false
@@ -192,47 +207,31 @@ import UIKit
self.translatesAutoresizingMaskIntoConstraints = true // this is mandatory to prevent unexpected key view location change self.translatesAutoresizingMaskIntoConstraints = true // this is mandatory to prevent unexpected key view location change
// reset to default border self.layer.cornerRadius = 20
self.layer.borderWidth = 1 self.layer.borderWidth = 1
var borderAlpha = 1.15 * self.backgroundAlpha
if borderAlpha < minimumBorderAlpha { self.tweakAlpha()
borderAlpha = minimumBorderAlpha
}
defaultBorderColor = UIColor(white: 0.2, alpha: borderAlpha).cgColor
self.borderLayer.borderColor = defaultBorderColor
self.layer.cornerRadius = 15 if CommandManager.oscButtonMappings.keys.contains(self.keyString){ //make oscButtons round and no border
self.layer.cornerRadius = self.frame.width/2
self.layer.borderWidth = 0
label.minimumScaleFactor = 0.15 // Adjust the scale factor for oscButtons
label.font = UIFont.boldSystemFont(ofSize: 22)
}
if CommandManager.touchPadCmds.contains(self.keyString){ if CommandManager.touchPadCmds.contains(self.keyString){
self.backgroundColor = UIColor.clear // make touchPad transparent
self.layer.borderColor = UIColor(white: 0.2, alpha: borderAlpha - 0.2).cgColor // reduce border alpha for touchPad
label.text = "" // make touchPad display no text label.text = "" // make touchPad display no text
} }
else{ // backgroundColor works for buttons other than touch pad
self.backgroundColor = UIColor(white: 0.2, alpha: self.backgroundAlpha - 0.18) // offset to be consistent with onScreen controller layer opacity
}
// self.layer.shadowColor = UIColor.clear.cgColor // self.layer.shadowColor = UIColor.clear.cgColor
// self.layer.shadowRadius = 8 // self.layer.shadowRadius = 8
// self.layer.shadowOpacity = 0.5 // self.layer.shadowOpacity = 0.5
addSubview(label) addSubview(label)
NSLayoutConstraint.activate([ self.changeAndActivateContraints()
//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.widthFactor),
self.heightAnchor.constraint(equalToConstant: 65 * self.widthFactor),
])
NSLayoutConstraint.activate([ setupButtonDownVisualEffectLayer();
label.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10), // set up label size contrain within UIView
label.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10),
label.centerXAnchor.constraint(equalTo: centerXAnchor),
label.centerYAnchor.constraint(equalTo: centerYAnchor),
//label.heightAnchor.constraint(equalToConstant: 40)
])
setupBorderLayer();
} }
private func createAndShowl3r3Indicator() -> CAShapeLayer{ private func createAndShowl3r3Indicator() -> CAShapeLayer{
@@ -525,8 +524,8 @@ import UIKit
CATransaction.begin() CATransaction.begin()
CATransaction.setDisableActions(true) CATransaction.setDisableActions(true)
// self.layer.borderWidth = 0 // self.layer.borderWidth = 0
borderLayer.borderWidth = 8.6 buttonDownVisualEffectLayer.borderWidth = self.buttonDownVisualEffectWidth // this will show the visual effect
borderLayer.borderColor = moonlightPurple buttonDownVisualEffectLayer.borderColor = moonlightPurple
CATransaction.commit() CATransaction.commit()
} }
@@ -534,31 +533,32 @@ import UIKit
CATransaction.begin() CATransaction.begin()
CATransaction.setDisableActions(true) CATransaction.setDisableActions(true)
// self.layer.borderWidth = 1 // self.layer.borderWidth = 1
borderLayer.borderWidth = 0 buttonDownVisualEffectLayer.borderWidth = 0
borderLayer.borderColor = defaultBorderColor buttonDownVisualEffectLayer.borderColor = defaultBorderColor
CATransaction.commit() CATransaction.commit()
} }
private func setupBorderLayer() { private func setupButtonDownVisualEffectLayer() {
// Create a shape layer for the border self.buttonDownVisualEffectWidth = 8.6
if CommandManager.oscButtonMappings.keys.contains(self.keyString) {self.buttonDownVisualEffectWidth = 15.3} // wider visual effect for osc buttons
// Set the frame to be larger than the view to expand outward // Set the frame to be larger than the view to expand outward
borderLayer.borderWidth = 0 buttonDownVisualEffectLayer.borderWidth = 0 // set this 0 to hide the visual effect first
borderLayer.frame = self.bounds.insetBy(dx: -8.6, dy: -8.6) // Adjust the inset as needed buttonDownVisualEffectLayer.frame = self.bounds.insetBy(dx: -self.buttonDownVisualEffectWidth, dy: -self.buttonDownVisualEffectWidth) // Adjust the inset as needed
borderLayer.cornerRadius = self.layer.cornerRadius + 8.6 buttonDownVisualEffectLayer.cornerRadius = self.layer.cornerRadius + self.buttonDownVisualEffectWidth
borderLayer.backgroundColor = UIColor.clear.cgColor; buttonDownVisualEffectLayer.backgroundColor = UIColor.clear.cgColor;
borderLayer.fillColor = UIColor.clear.cgColor; buttonDownVisualEffectLayer.fillColor = UIColor.clear.cgColor;
// Create a path for the border // Create a path for the border
let path = UIBezierPath(roundedRect: borderLayer.bounds, cornerRadius: borderLayer.cornerRadius) let path = UIBezierPath(roundedRect: buttonDownVisualEffectLayer.bounds, cornerRadius: buttonDownVisualEffectLayer.cornerRadius)
borderLayer.path = path.cgPath buttonDownVisualEffectLayer.path = path.cgPath
// Add the border layer below the main view layer // Add the border layer below the main view layer
self.layer.superlayer?.insertSublayer(borderLayer, below: self.layer) self.layer.superlayer?.insertSublayer(buttonDownVisualEffectLayer, below: self.layer)
// Retrieve the current frame to account for transformations, this will update the coords for new position CGPointMake // Retrieve the current frame to account for transformations, this will update the coords for new position CGPointMake
borderLayer.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) buttonDownVisualEffectLayer.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
} }
//========================================================================================================== //==========================================================================================================
@@ -620,7 +620,8 @@ import UIKit
// OnScreenControls.testMethod(); // OnScreenControls.testMethod();
// RelativeTouchHandler.testMethod(); // RelativeTouchHandler.testMethod();
if !OnScreenButtonView.editMode { if !OnScreenButtonView.editMode {
if CommandManager.touchPadCmds.contains(self.keyString) && touches.count == 1{ if CommandManager.touchPadCmds.contains(self.keyString) && touches.count == 1{
switch self.keyString { switch self.keyString {
@@ -657,6 +658,14 @@ import UIKit
if !CommandManager.touchPadCmds.contains(self.keyString) { if !CommandManager.touchPadCmds.contains(self.keyString) {
self.buttonDownVisualEffect() self.buttonDownVisualEffect()
} }
if CommandManager.oscButtonMappings.keys.contains(self.keyString) {
let buttonFlag = CommandManager.oscButtonMappings[self.keyString]
if buttonFlag != 0 {self.onScreenControls.pressDownControllerButton(buttonFlag!)}
if self.keyString == "OSCL2" {self.onScreenControls.updateLeftTrigger(0xFF)}
if self.keyString == "OSCR2" {self.onScreenControls.updateRightTrigger(0xFF)}
}
// if the command(keystring contains "+", it's a multi-key command or a quick triggering key, rather than a physical button // if the command(keystring contains "+", it's a multi-key command or a quick triggering key, rather than a physical button
if self.keyString.contains("+"){ if self.keyString.contains("+"){
let keyboardCmdStrings = CommandManager.shared.extractKeyStrings(from: self.keyString)! let keyboardCmdStrings = CommandManager.shared.extractKeyStrings(from: self.keyString)!
@@ -784,6 +793,13 @@ import UIKit
self.leftIndicator.removeFromSuperlayer() self.leftIndicator.removeFromSuperlayer()
self.rightIndicator.removeFromSuperlayer() self.rightIndicator.removeFromSuperlayer()
self.lrudIndicatorBall.removeFromSuperlayer() self.lrudIndicatorBall.removeFromSuperlayer()
if CommandManager.oscButtonMappings.keys.contains(self.keyString) {
let buttonFlag = CommandManager.oscButtonMappings[self.keyString]
if buttonFlag != 0 {self.onScreenControls.releaseControllerButton(buttonFlag!)}
if self.keyString == "OSCL2" {self.onScreenControls.updateLeftTrigger(0x00)}
if self.keyString == "OSCR2" {self.onScreenControls.updateRightTrigger(0x00)}
}
if !OnScreenButtonView.editMode && !self.keyString.contains("+") { // if the command(keystring contains "+", it's a multi-key command rather than a single key button if !OnScreenButtonView.editMode && !self.keyString.contains("+") { // if the command(keystring contains "+", it's a multi-key command rather than a single key button
+2
View File
@@ -111,6 +111,8 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
- (void) clearLeftStickTouchPadFlag; - (void) clearLeftStickTouchPadFlag;
- (void) pressDownControllerButton: (int)flag; - (void) pressDownControllerButton: (int)flag;
- (void) releaseControllerButton: (int)flag; - (void) releaseControllerButton: (int)flag;
- (void) updateLeftTrigger:(unsigned char)input;
- (void) updateRightTrigger:(unsigned char)input;
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport streamConfig:(StreamConfiguration*)streamConfig; - (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport streamConfig:(StreamConfiguration*)streamConfig;
- (BOOL) handleTouchDownEvent:(NSSet*)touches; - (BOOL) handleTouchDownEvent:(NSSet*)touches;
+10
View File
@@ -179,6 +179,16 @@ static float L3_Y;
[_controllerSupport updateFinished:_controller]; [_controllerSupport updateFinished:_controller];
} }
- (void) updateLeftTrigger:(unsigned char)input{
[_controllerSupport updateLeftTrigger:_controller left:input];
[_controllerSupport updateFinished:_controller];
}
- (void) updateRightTrigger:(unsigned char)input{
[_controllerSupport updateRightTrigger:_controller right:input];
[_controllerSupport updateFinished:_controller];
}
// sending self as an instance to OnScreenButtonView // sending self as an instance to OnScreenButtonView
- (void)sendInstance{ - (void)sendInstance{
NSLog(@"OnScreenControls is sending its instance..."); NSLog(@"OnScreenControls is sending its instance...");
@@ -337,7 +337,8 @@
bool noValidKeyboardString = [CommandManager.shared extractKeyStringsFrom:cmdString] == nil; // this is a invalid string. bool noValidKeyboardString = [CommandManager.shared extractKeyStringsFrom:cmdString] == nil; // this is a invalid string.
bool noValidMouseButtonString = ![CommandManager.mouseButtonMappings.allKeys containsObject:cmdString]; bool noValidMouseButtonString = ![CommandManager.mouseButtonMappings.allKeys containsObject:cmdString];
bool noValidTouchPadString = ![CommandManager.touchPadCmds containsObject:cmdString]; bool noValidTouchPadString = ![CommandManager.touchPadCmds containsObject:cmdString];
if(noValidKeyboardString && noValidMouseButtonString && noValidTouchPadString) return; bool noValidOscButtonString = ![CommandManager.oscButtonMappings.allKeys containsObject:cmdString];
if(noValidKeyboardString && noValidMouseButtonString && noValidTouchPadString && noValidOscButtonString) return;
//saving & present the keyboard button: //saving & present the keyboard button:
OnScreenButtonView* buttonView = [[OnScreenButtonView alloc] initWithKeyString:cmdString keyLabel:keyLabel]; OnScreenButtonView* buttonView = [[OnScreenButtonView alloc] initWithKeyString:cmdString keyLabel:keyLabel];
@@ -347,6 +348,7 @@
// Add the buttonView to the view controller's view // Add the buttonView to the view controller's view
[self.view addSubview:buttonView]; [self.view addSubview:buttonView];
[buttonView setLocationWithXOffset:50 yOffset:50]; [buttonView setLocationWithXOffset:50 yOffset:50];
[buttonView resizeButtonView];
}]; }];
[alertController addAction:cancelAction]; [alertController addAction:cancelAction];
[alertController addAction:okAction]; [alertController addAction:okAction];