From 9aa84c03d7fcd114494f896b41fea3d190fc27e5 Mon Sep 17 00:00:00 2001 From: TrueZhuangjia Date: Mon, 24 Mar 2025 00:36:24 +0800 Subject: [PATCH] - button-touchPad hybrid widgets - minimum stick offset for stick widgets - expand controller cmd strings to playStation style --- Limelight/Input/CommandManager.swift | 43 ++- .../Input/CustomOSC/OSCProfilesManager.m | 5 +- .../Input/CustomOSC/OnScreenButtonState.h | 1 + .../Input/CustomOSC/OnScreenButtonState.m | 2 + Limelight/Input/OnScreenControls.m | 4 +- Limelight/Input/OnScreenWidgetView.swift | 334 ++++++++++-------- Limelight/Input/StreamView.m | 3 +- .../LayoutOnScreenControlsViewController.m | 61 +++- 8 files changed, 258 insertions(+), 195 deletions(-) diff --git a/Limelight/Input/CommandManager.swift b/Limelight/Input/CommandManager.swift index 1b359652..233892ec 100644 --- a/Limelight/Input/CommandManager.swift +++ b/Limelight/Input/CommandManager.swift @@ -52,8 +52,6 @@ import UIKit @objc public static let shared = CommandManager() @objc public static let mouseButtonMappings: [String: Int32] = [ - "YSML" : BUTTON_LEFT, - "YSMR" : BUTTON_RIGHT, "M_LEFT" : BUTTON_LEFT, "MLEFT" : BUTTON_LEFT, "M_MIDDLE" : BUTTON_MIDDLE, @@ -68,26 +66,37 @@ import UIKit @objc public static let oscButtonMappings: [String: Int32] = [ - "YSLT" : 0, - "YSRT" : 0, // RT button & RsvPad in GenshinImpact - "YSRB" : RB_FLAG, // RB button & RsvPad in GenshinImpact - "YSB" : B_FLAG, // B button & RsvPad in GenshinImpact "OSCA" : A_FLAG, "OSCB" : B_FLAG, "OSCX" : X_FLAG, "OSCY" : Y_FLAG, "OSCL1" : LB_FLAG, + "L1" : LB_FLAG, + "LB" : LB_FLAG, "OSCR1" : RB_FLAG, + "R1" : RB_FLAG, + "RB" : RB_FLAG, "OSCL3" : LS_CLK_FLAG, + "L3" : LS_CLK_FLAG, + "LS" : LS_CLK_FLAG, "OSCR3" : RS_CLK_FLAG, + "R3" : RS_CLK_FLAG, + "RS" : RS_CLK_FLAG, "OSCSTART" : PLAY_FLAG, + "OSCPLAY" : PLAY_FLAG, "OSCSELECT" : BACK_FLAG, + "OSCBACK" : BACK_FLAG, "OSCUP" : UP_FLAG, "OSCDOWN" : DOWN_FLAG, "OSCLEFT" : LEFT_FLAG, "OSCRIGHT" : RIGHT_FLAG, "OSCL2" : 0, - "OSCR2" : 0] + "L2" : 0, + "LT" : 0, + "OSCR2" : 0, + "R2" : 0, + "RT" : 0 + ] @objc public static let oscRectangleButtonCmds: [String] = [ "OSCUP", @@ -95,20 +104,21 @@ import UIKit "OSCLEFT", "OSCRIGHT", "OSCSTART", - "OSCSELECT"] + "OSCPLAY", + "OSCSELECT", + "OSCBACK" + ] - @objc public static let touchPadCmds: [String] = ["YSRSV", "LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "MOUSEPAD", "DPAD", "WASDPAD", "ARROWPAD", "YSWASD"] - @objc public static let stickTouchPads: [String] = ["YSRSV", "LSVPAD", "RSVPAD", "LSPAD", "RSPAD"] + @objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "MOUSEPAD", "DPAD", "WASDPAD", "ARROWPAD"] + @objc public static let stickTouchPads: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD"] @objc public static let nonVectorStickPads: [String] = ["LSPAD", "RSPAD"] @objc public static let specialOverlayButtonCmds: [String] = ["SETTINGS"] - @objc public static let specialGameWidgets: [String] = ["YSRSV", "YSLT", "YSRT", "YSRB", "YSB", "YSRT2", "YSRB2", "YSB2", "YSEM", "YSML", "YSMR", "YSWASD"] - @objc public static let yuanshenStickPadButtonCmds: [String] = ["YSLT", "YSRT", "YSRB", "YSB"] - @objc public static let yuanshenMouseMoveButtonCmds: [String] = ["YSEM", "YSML", "YSMR"] + // @objc public static let specialGameWidgets: [String] = ["YSRSV", "YSLT", "YSRT", "YSRB", "YSB", "YSRT2", "YSRB2", "YSB2", "YSEM", "YSML", "YSMR", "YSWASD"] static let keyboardButtonMappings: [String: Int16] = [ // Windows Key Codes - "YSEM": 0x45, // 'E' & mousePad button in GenshinImpact + "NULL": 0xFF, "CTRL": 0x11, // VK_CONTROL "SHIFT": 0x10, // VK_SHIFT "ALT": 0x12, // VK_MENU @@ -445,12 +455,15 @@ import UIKit @objc public func extractSinglCmdStringsFromComboKeys(from input: String) -> [String]? { let combinedStrings = [CommandManager.keyboardButtonMappings.keys.map { $0 as String }, CommandManager.oscButtonMappings.keys.map { $0 as String }, - CommandManager.mouseButtonMappings.keys.map { $0 as String }] + CommandManager.mouseButtonMappings.keys.map { $0 as String }, + CommandManager.touchPadCmds.map { $0 as String } + ] .lazy // 零内存开销 .flatMap { $0 } // 三维展开 .map(String.init(describing:)) // 安全类型转换 let keys = combinedStrings.joined(separator: "|") + print(keys) let pattern = "^(?:\(keys))(?:-(?:\(keys)))*(?:-\\d+MS)?$" diff --git a/Limelight/Input/CustomOSC/OSCProfilesManager.m b/Limelight/Input/CustomOSC/OSCProfilesManager.m index baf353b2..ffb40b93 100644 --- a/Limelight/Input/CustomOSC/OSCProfilesManager.m +++ b/Limelight/Input/CustomOSC/OSCProfilesManager.m @@ -291,8 +291,8 @@ static NSMutableSet *OnScreenWidgetViews; // save on-screen widget views (keyboard & mouse command) as buttonstate: for(OnScreenWidgetView* widgetView in OnScreenWidgetViews){ - OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.keyString buttonType:CustomOnScreenWidget andPosition:widgetView.center]; - buttonState.alias = widgetView.keyLabel; + OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.cmdString buttonType:CustomOnScreenWidget andPosition:widgetView.center]; + buttonState.alias = widgetView.buttonLabel; buttonState.widthFactor = widgetView.widthFactor; buttonState.heightFactor = widgetView.heightFactor; buttonState.backgroundAlpha = widgetView.backgroundAlpha; @@ -300,6 +300,7 @@ static NSMutableSet *OnScreenWidgetViews; buttonState.sensitivityFactor = widgetView.sensitivityFactor; buttonState.stickIndicatorOffset = widgetView.stickIndicatorOffset; buttonState.widgetShape = widgetView.shape; + buttonState.minStickOffset = widgetView.minStickOffset; NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil]; [buttonStatesEncoded addObject: buttonStateEncoded]; diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.h b/Limelight/Input/CustomOSC/OnScreenButtonState.h index a1ef911d..95ffdd55 100644 --- a/Limelight/Input/CustomOSC/OnScreenButtonState.h +++ b/Limelight/Input/CustomOSC/OnScreenButtonState.h @@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) CGFloat borderWidth; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat sensitivityFactor; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat stickIndicatorOffset; // for OnScreenWidgetView +@property (nonatomic, assign) CGFloat minStickOffset; // for OnScreenWidgetView @property NSString* widgetShape; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat oscLayerSizeFactor; // for OnScreenController CALayer diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.m b/Limelight/Input/CustomOSC/OnScreenButtonState.m index 16a4a81e..31115f5c 100644 --- a/Limelight/Input/CustomOSC/OnScreenButtonState.m +++ b/Limelight/Input/CustomOSC/OnScreenButtonState.m @@ -40,6 +40,7 @@ [encoder encodeFloat:self.backgroundAlpha forKey:@"backgroundAlpha"]; [encoder encodeFloat:self.borderWidth forKey:@"borderWidth"]; [encoder encodeObject:self.widgetShape forKey:@"widgetShape"]; + [encoder encodeFloat:self.minStickOffset forKey:@"minStickOffset"]; } - (id) initWithCoder:(NSCoder*)decoder { @@ -57,6 +58,7 @@ self.backgroundAlpha = [decoder decodeFloatForKey:@"backgroundAlpha"]; self.borderWidth = [decoder decodeFloatForKey:@"borderWidth"]; self.widgetShape = [decoder decodeObjectForKey:@"widgetShape"]; + self.minStickOffset = [decoder decodeFloatForKey:@"minStickOffset"]; } return self; } diff --git a/Limelight/Input/OnScreenControls.m b/Limelight/Input/OnScreenControls.m index e0123aec..2555eedb 100644 --- a/Limelight/Input/OnScreenControls.m +++ b/Limelight/Input/OnScreenControls.m @@ -159,13 +159,13 @@ static float L3_Y; - (void) clearRightStickTouchPadFlag{ [_controllerSupport updateRightStick:_controller x:0 y:0]; - [_controllerSupport clearButtonFlag:_controller flags:RS_CLK_FLAG]; + // [_controllerSupport clearButtonFlag:_controller flags:RS_CLK_FLAG]; [_controllerSupport updateFinished:_controller]; } - (void) clearLeftStickTouchPadFlag{ [_controllerSupport updateLeftStick:_controller x:0 y:0]; - [_controllerSupport clearButtonFlag:_controller flags:LS_CLK_FLAG]; + // [_controllerSupport clearButtonFlag:_controller flags:LS_CLK_FLAG]; [_controllerSupport updateFinished:_controller]; } diff --git a/Limelight/Input/OnScreenWidgetView.swift b/Limelight/Input/OnScreenWidgetView.swift index 0a02e195..bde704ed 100644 --- a/Limelight/Input/OnScreenWidgetView.swift +++ b/Limelight/Input/OnScreenWidgetView.swift @@ -19,9 +19,23 @@ import UIKit } } + enum WidgetTypeEnum: UInt8 { + case uninitialized = 0 + case button = 1 + case touchPad = 2 + } + + private var widgetType: WidgetTypeEnum = WidgetTypeEnum.uninitialized + @objc static public var editMode: Bool = false - @objc public var keyLabel: String - @objc public var keyString: String + @objc public var buttonLabel: String + @objc public var cmdString: String + private var buttonString: String = "" + private var touchPadString: String = "" + // super combo key string set + private var comboButtonStrings: [String] = [] + private var comboKeyTimeIntervalMs: UInt32 = 0 + @objc public var pressed: Bool @objc public var widthFactor: CGFloat = 1.0 @objc public var heightFactor: CGFloat = 1.0 @@ -36,9 +50,17 @@ import UIKit - + + + // for all touchPad or buttons hybrid with touchPads + @objc public var hasStickIndicator: Bool = false + @objc public var hasSensitivityTweak: Bool = false + + // for all stick pads + @objc public var minStickOffset: CGFloat = 0 public let stickMaxOffset: CGFloat = 0x7FFE + // for LSVPAD, RSVPAD @objc public var deltaX: CGFloat @objc public var deltaY: CGFloat @@ -94,40 +116,66 @@ import UIKit 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 - // super combo key string set - private var comboKeyStrings: [String] = [] - private var comboKeyTimeIntervalMs: UInt32 = 10 // whole button press down visual effect @objc public let buttonDownVisualEffectLayer = CAShapeLayer() private var buttonDownVisualEffectWidth: CGFloat - @objc init(keyString: String, keyLabel: String, shape:String) { - self.keyString = keyString - if self.keyString.contains("-"){ + @objc init(cmdString: String, buttonLabel: String, shape:String) { + + self.cmdString = cmdString + self.touchPadString = "" + + if !self.cmdString.contains("+"){ // 安全解包并处理 `comboKeyStrings` - if let comboKeyStrings = CommandManager.shared.extractSinglCmdStringsFromComboKeys(from: self.keyString) { - self.comboKeyStrings = comboKeyStrings - // 检查最后一个元素是否包含 "MS" - if let lastComboKey = self.comboKeyStrings.last, lastComboKey.contains("MS") { + if var comboStrings = CommandManager.shared.extractSinglCmdStringsFromComboKeys(from: self.cmdString) { + + // extract timeInterval + if let lastString = comboStrings.last, lastString.contains("MS") { // 移除 "MS" 后的部分并转换为整数 - let timeIntervalString = lastComboKey.replacingOccurrences(of: "MS", with: "") + let timeIntervalString = lastString.replacingOccurrences(of: "MS", with: "") // 安全地将字符串转换为整数 if let timeInterval = UInt32(timeIntervalString) { self.comboKeyTimeIntervalMs = timeInterval - } else { - // 处理转换失败的情况 - print("无法将时间字符串转换为整数") - } + } else {print("无法将时间字符串转换为整数")} + comboStrings.removeLast() + } + + if CommandManager.touchPadCmds.contains(comboStrings.first ?? "") {self.widgetType = WidgetTypeEnum.touchPad} + else {self.widgetType = WidgetTypeEnum.button} + + let touchPadString = Set(comboStrings).intersection(Set(CommandManager.touchPadCmds)).first ?? "" + self.comboButtonStrings = comboStrings.filter{$0 != touchPadString} + self.touchPadString = touchPadString + self.buttonString = self.comboButtonStrings.first ?? "" + + let stickAndMouseTouchpads = ["LSPAD", "RSPAD", "LSVPAD", "RSVPAD", "MOUSEPAD"] + let nonVectorStickPads = ["LSPAD", "RSPAD"] + if stickAndMouseTouchpads.contains(self.touchPadString) {self.hasSensitivityTweak = true} + if nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad {self.hasStickIndicator = true} + + switch self.cmdString { + case "LSPAD", "LSVPAD": + self.comboButtonStrings = ["OSCL3"] + case "RSPAD", "RSVPAD": + self.comboButtonStrings = ["OSCR3"] + default: break } - self.comboKeyStrings.removeLast() - } else { - // 如果无法提取 comboKeyStrings - print("无法从 keyString 提取 comboKeyStrings") } + else {print("无法从 keyString 提取 comboKeyStrings")} + } + else { + self.widgetType = WidgetTypeEnum.button // legacy combo button connected by "+" + } + + + print("widgetType: \(self.widgetType)") + print("touchPadString: \(self.touchPadString)") + for comboButtonString in comboButtonStrings { + print("comboButtonString: \(comboButtonString)") } - self.keyLabel = keyLabel + self.buttonLabel = buttonLabel self.shape = shape self.label = UILabel() // self.originalBackgroundColor = UIColor(white: 0.2, alpha: 0.7) @@ -172,7 +220,6 @@ import UIKit fatalError("init(coder:) has not been implemented") } - // ====================================================================================================== @@ -246,7 +293,7 @@ import UIKit 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 CommandManager.touchPadCmds.contains(self.keyString){ + if widgetType == WidgetTypeEnum.touchPad { minimumBorderAlpha = 0.0 } if borderAlpha < minimumBorderAlpha { @@ -255,7 +302,7 @@ import UIKit defaultBorderColor = UIColor(white: 0.2, alpha: borderAlpha).cgColor self.layer.borderColor = defaultBorderColor - if CommandManager.touchPadCmds.contains(self.keyString){ + if widgetType == WidgetTypeEnum.touchPad { self.backgroundColor = UIColor.clear // make touchPad transparent self.layer.borderColor = UIColor(white: 0.2, alpha: borderAlpha - 0.15).cgColor // reduced border alpha for touchPad } @@ -286,7 +333,7 @@ import UIKit } private func setupView() { - label.text = self.keyLabel + label.text = self.buttonLabel label.font = UIFont.boldSystemFont(ofSize: 19) label.translatesAutoresizingMaskIntoConstraints = false label.adjustsFontSizeToFitWidth = true @@ -306,7 +353,7 @@ import UIKit self.tweakAlpha() if self.shape == "default" || self.shape.isEmpty { - if CommandManager.oscButtonMappings.keys.contains(self.keyString) && !CommandManager.oscRectangleButtonCmds.contains(self.keyString){ //make oscButtons round + if CommandManager.oscButtonMappings.keys.contains(self.buttonString) && !CommandManager.oscRectangleButtonCmds.contains(self.buttonString){ //make oscButtons round self.shape = "round" } else { @@ -314,18 +361,17 @@ import UIKit } } - - if CommandManager.touchPadCmds.contains(self.keyString){ + if self.widgetType == WidgetTypeEnum.touchPad { self.shape = "largeSquare" // override shape from user input if(self.borderWidth < 1) {self.layer.borderWidth = 1} else {self.layer.borderWidth = self.borderWidth} label.text = "" // make touchPad display no text if OnScreenWidgetView.editMode { //display label in edit mode to make the pad more visible - label.text = self.keyString + label.text = self.cmdString } } - if CommandManager.specialOverlayButtonCmds.contains(self.keyString){ + if CommandManager.specialOverlayButtonCmds.contains(self.cmdString){ self.layer.borderWidth = 0 } @@ -608,8 +654,8 @@ import UIKit if(buttonPressed & Direction.up.rawValue == Direction.up.rawValue){ showLrudDirectionIndicator(with: upIndicator) - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_DOWN), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_DOWN), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["UP_ARROW"]!,Int8(KEY_ACTION_DOWN), 0) case "DPAD": self.onScreenControls.pressDownControllerButton(UP_FLAG) default: break @@ -617,8 +663,8 @@ import UIKit } else{ self.upIndicator.removeFromSuperlayer() - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_UP), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_UP), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["UP_ARROW"]!,Int8(KEY_ACTION_UP), 0) case "DPAD": self.onScreenControls.releaseControllerButton(UP_FLAG) default: break @@ -626,8 +672,8 @@ import UIKit } if(buttonPressed & Direction.down.rawValue == Direction.down.rawValue){ showLrudDirectionIndicator(with: downIndicator) - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["S"]!,Int8(KEY_ACTION_DOWN), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["S"]!,Int8(KEY_ACTION_DOWN), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["DOWN_ARROW"]!,Int8(KEY_ACTION_DOWN), 0) case "DPAD": self.onScreenControls.pressDownControllerButton(DOWN_FLAG) default: break @@ -635,8 +681,8 @@ import UIKit } else{ self.downIndicator.removeFromSuperlayer() - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["S"]!,Int8(KEY_ACTION_UP), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["S"]!,Int8(KEY_ACTION_UP), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["DOWN_ARROW"]!,Int8(KEY_ACTION_UP), 0) case "DPAD": self.onScreenControls.releaseControllerButton(DOWN_FLAG) default: break @@ -644,8 +690,8 @@ import UIKit } if(buttonPressed & Direction.left.rawValue == Direction.left.rawValue){ showLrudDirectionIndicator(with: leftIndicator) - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["A"]!,Int8(KEY_ACTION_DOWN), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["A"]!,Int8(KEY_ACTION_DOWN), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["LEFT_ARROW"]!,Int8(KEY_ACTION_DOWN), 0) case "DPAD": self.onScreenControls.pressDownControllerButton(LEFT_FLAG) default: break @@ -653,8 +699,8 @@ import UIKit } else{ self.leftIndicator.removeFromSuperlayer() - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["A"]!,Int8(KEY_ACTION_UP), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["A"]!,Int8(KEY_ACTION_UP), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["LEFT_ARROW"]!,Int8(KEY_ACTION_UP), 0) case "DPAD": self.onScreenControls.releaseControllerButton(LEFT_FLAG) default: break @@ -662,8 +708,8 @@ import UIKit } if(buttonPressed & Direction.right.rawValue == Direction.right.rawValue){ showLrudDirectionIndicator(with: rightIndicator) - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["D"]!,Int8(KEY_ACTION_DOWN), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["D"]!,Int8(KEY_ACTION_DOWN), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["RIGHT_ARROW"]!,Int8(KEY_ACTION_DOWN), 0) case "DPAD": self.onScreenControls.pressDownControllerButton(RIGHT_FLAG) default: break @@ -671,8 +717,8 @@ import UIKit } else{ self.rightIndicator.removeFromSuperlayer() - switch keyString { - case "WASDPAD","YSWASD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["D"]!,Int8(KEY_ACTION_UP), 0) + switch touchPadString { + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["D"]!,Int8(KEY_ACTION_UP), 0) case "ARROWPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["RIGHT_ARROW"]!,Int8(KEY_ACTION_UP), 0) case "DPAD": self.onScreenControls.releaseControllerButton(RIGHT_FLAG) default: break @@ -794,39 +840,42 @@ import UIKit var targetX = self.touchInputToStickInput(input: inputX) var targetY = -self.touchInputToStickInput(input: inputY) // vertical input must be inverted - switch self.keyString { - //tweaking yuanshen RsvPad related widgets - case "YSB", "YSRT", "YSRB", "YSRSV": - targetX = (targetX >= 0 ? 1.0 : -1.0) * 3000.0 + (stickMaxOffset - 3000.0) * (targetX/stickMaxOffset) - targetY = (targetY >= 0 ? 1.0 : -1.0) * 3000.0 + (stickMaxOffset - 3000.0) * (targetY/stickMaxOffset) - default: break - } + targetX = (targetX >= 0 ? 1.0 : -1.0) * minStickOffset + (stickMaxOffset - minStickOffset) * (targetX/stickMaxOffset) + targetY = (targetY >= 0 ? 1.0 : -1.0) * minStickOffset + (stickMaxOffset - minStickOffset) * (targetY/stickMaxOffset) self.onScreenControls.sendRightStickTouchPadEvent(targetX, targetY) } private func sendLeftStickTouchPadEvent(inputX: CGFloat, inputY: CGFloat){ let targetX = self.touchInputToStickInput(input: inputX) let targetY = -self.touchInputToStickInput(input: inputY) + // targetX = (targetX >= 0 ? 1.0 : -1.0) * Float(minStickOffset) + (stickMaxOffset - Float(minStickOffset)) * (targetX/stickMaxOffset) + // targetY = (targetY >= 0 ? 1.0 : -1.0) * Float(minStickOffset) + (stickMaxOffset - Float(minStickOffset)) * (targetY/stickMaxOffset) self.onScreenControls.sendLeftStickTouchPadEvent(targetX, targetY) } //========================================================================================================== - private func sendOscButtonDownEvent(keyString: String){ - let buttonFlag = CommandManager.oscButtonMappings[keyString] + private func sendOscButtonDownEvent(oscString: String){ + let buttonFlag = CommandManager.oscButtonMappings[oscString] if buttonFlag != 0 {self.onScreenControls.pressDownControllerButton(buttonFlag!)} - if keyString == "OSCL2" || keyString == "YSLT" { + else {switch oscString { + case "OSCL2", "L2", "LT": self.onScreenControls.updateLeftTrigger(0xFF) - } - if keyString == "OSCR2" || keyString == "YSRT" {self.onScreenControls.updateRightTrigger(0xFF)} + case "OSCR2", "R2", "RT": + self.onScreenControls.updateRightTrigger(0xFF) + default:break + }} } - private func sendOscButtonUpEvent(keyString: String){ - let buttonFlag = CommandManager.oscButtonMappings[keyString] + private func sendOscButtonUpEvent(oscString: String){ + let buttonFlag = CommandManager.oscButtonMappings[oscString] if buttonFlag != 0 {self.onScreenControls.releaseControllerButton(buttonFlag!)} - if keyString == "OSCL2" || keyString == "YSLT" { + else {switch oscString { + case "OSCL2", "L2", "LT": self.onScreenControls.updateLeftTrigger(0x00) - } - if keyString == "OSCR2" || keyString == "YSRT" {self.onScreenControls.updateRightTrigger(0x00)} + case "OSCR2", "R2", "RT": + self.onScreenControls.updateRightTrigger(0x00) + default:break + }} } //============================================================================== @@ -834,7 +883,7 @@ import UIKit DispatchQueue.global(qos: .userInitiated).async { for comboString in comboStrings { if CommandManager.oscButtonMappings.keys.contains(comboString) { - self.sendOscButtonDownEvent(keyString: comboString) + self.sendOscButtonDownEvent(oscString: comboString) } if CommandManager.keyboardButtonMappings.keys.contains(comboString) { LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[comboString]!,Int8(KEY_ACTION_DOWN), 0) @@ -853,7 +902,7 @@ import UIKit DispatchQueue.global(qos: .userInitiated).async { for comboString in comboStrings { if CommandManager.oscButtonMappings.keys.contains(comboString) { - self.sendOscButtonUpEvent(keyString: comboString) + self.sendOscButtonUpEvent(oscString: comboString) } if CommandManager.keyboardButtonMappings.keys.contains(comboString) { LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[comboString]!,Int8(KEY_ACTION_UP), 0) @@ -875,7 +924,7 @@ import UIKit self.touchBegan = true super.touchesBegan(touches, with: event) - self.isMultipleTouchEnabled = self.keyString == "MOUSEPAD" // only enable multi-touch in mousePad mode + self.isMultipleTouchEnabled = self.touchPadString == "MOUSEPAD" // only enable multi-touch in mousePad mode if touches.count == 1 { // to make sure touchBegan location captured properly, don't use event.alltouches.count here let currentTime = CACurrentMediaTime() @@ -897,9 +946,8 @@ import UIKit self.pressed = true if !OnScreenWidgetView.editMode { - - if CommandManager.touchPadCmds.contains(self.keyString) && touches.count == 1{ // don't use event?.allTouches?.count here, it will counts all touches including the ones captured by other UIViews - switch self.keyString { + if self.widgetType == WidgetTypeEnum.touchPad && touches.count == 1{ // don't use event?.allTouches?.count here, it will counts all touches including the ones captured by other UIViews + switch self.touchPadString { case "LSPAD": self.crossMarkLayer.removeFromSuperlayer() self.stickBallLayer.removeFromSuperlayer() @@ -907,8 +955,7 @@ import UIKit self.showStickIndicator() if quickDoubleTapDetected { self.l3r3Indicator = self.createAndShowl3r3Indicator() - self.onScreenControls.pressDownControllerButton(LS_CLK_FLAG)} - break + self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)} case "RSPAD": self.crossMarkLayer.removeFromSuperlayer() self.stickBallLayer.removeFromSuperlayer() @@ -916,72 +963,64 @@ import UIKit self.showStickIndicator() if quickDoubleTapDetected { self.l3r3Indicator = self.createAndShowl3r3Indicator() - self.onScreenControls.pressDownControllerButton(RS_CLK_FLAG)} - break + self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)} case "LSVPAD": if quickDoubleTapDetected { self.l3r3Indicator = self.createAndShowl3r3Indicator() - self.onScreenControls.pressDownControllerButton(LS_CLK_FLAG)} - break - case "RSVPAD", "YSRSV": + self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)} + case "RSVPAD": if quickDoubleTapDetected { self.l3r3Indicator = self.createAndShowl3r3Indicator() - self.onScreenControls.pressDownControllerButton(RS_CLK_FLAG)} - break + self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)} case "DPAD", "WASDPAD", "ARROWPAD": self.lrudIndicatorBall = createAndShowLrudBall(at: touchBeganLocation) - case "YSWASD": - self.lrudIndicatorBall = createAndShowLrudBall(at: touchBeganLocation) if quickDoubleTapDetected { - LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["CTRL"]!,Int8(KEY_ACTION_DOWN), 0) + LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[self.buttonString]!,Int8(KEY_ACTION_DOWN), 0) DispatchQueue.global(qos: .userInitiated).async { usleep(100000) - LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["CTRL"]!,Int8(KEY_ACTION_UP), 0) + LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[self.buttonString]!,Int8(KEY_ACTION_UP), 0) } } - break default: break } } - if !self.keyString.contains("+") && !self.keyString.contains("-") { + /* + if !self.buttonString.isEmpty { // if there's no "+" in the keystring, treat it as a regular button: - if CommandManager.oscButtonMappings.keys.contains(self.keyString) { - self.sendOscButtonDownEvent(keyString: self.keyString) + if CommandManager.oscButtonMappings.keys.contains(self.cmdString) { + self.sendOscButtonDownEvent(keyString: self.cmdString) } - if CommandManager.keyboardButtonMappings.keys.contains(self.keyString) { - LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[self.keyString]!,Int8(KEY_ACTION_DOWN), 0) + if CommandManager.keyboardButtonMappings.keys.contains(self.cmdString) { + LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[self.cmdString]!,Int8(KEY_ACTION_DOWN), 0) } - if CommandManager.mouseButtonMappings.keys.contains(self.keyString) { - LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), Int32(CommandManager.mouseButtonMappings[self.keyString]!)) + if CommandManager.mouseButtonMappings.keys.contains(self.cmdString) { + LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), Int32(CommandManager.mouseButtonMappings[self.cmdString]!)) } } + */ - // if the command(keystring contains "-", it's a multi-type super combo button - if self.keyString.contains("-"){ - self.sendComboButtonsDownEvent(comboStrings: self.comboKeyStrings) + // this will also deal with button events + if self.widgetType == WidgetTypeEnum.button && !self.comboButtonStrings.isEmpty { + self.buttonDownVisualEffect() + self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings) } - // 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("+") && !self.keyString.contains("-"){ - let keyboardCmdStrings = CommandManager.shared.extractKeyStringsFromComboCommand(from: self.keyString)! + // legacy keyboard button combo connected by "+" + if self.cmdString.contains("+") && !self.cmdString.contains("-"){ + let keyboardCmdStrings = CommandManager.shared.extractKeyStringsFromComboCommand(from: self.cmdString)! CommandManager.shared.sendKeyComboCommand(keyboardCmdStrings: keyboardCmdStrings) // send multi-key command DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) { // reset shadow color immediately 50ms later self.buttonUpVisualEffect() } } - - if !CommandManager.touchPadCmds.contains(self.keyString) { - self.buttonDownVisualEffect() - } } // here is in edit mode: else{ self.buttonDownVisualEffect() 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 } - } private func moveByTouch(touch: UITouch){ @@ -1004,10 +1043,8 @@ import UIKit override func touchesMoved(_ touches: Set, with event: UIEvent?) { super.touchesMoved(touches, with: event) if !OnScreenWidgetView.editMode { - handleTouchPadMoveEvent(touches, with: event) - - if CommandManager.specialOverlayButtonCmds.contains(self.keyString){ + if CommandManager.specialOverlayButtonCmds.contains(self.cmdString){ if let touch = touches.first { NSLog("touchTapTimeStamp %f", self.touchTapTimeStamp) if CACurrentMediaTime() - self.touchTapTimeStamp > 0.3 { // temporarily relocate special buttons @@ -1023,11 +1060,8 @@ import UIKit if let touch = touches.first { self.moveByTouch(touch: touch) } - - if CommandManager.nonVectorStickPads.contains(self.keyString) { - self.stickBallLayer.removeFromSuperlayer() - self.crossMarkLayer.removeFromSuperlayer() - } + self.stickBallLayer.removeFromSuperlayer() + self.crossMarkLayer.removeFromSuperlayer() } } @@ -1041,26 +1075,25 @@ import UIKit self.offSetY = currentTouchLocation.y - self.touchBeganLocation.y self.latestTouchLocation = currentTouchLocation - switch self.keyString{ - case "MOUSEPAD","YSEM","YSML","YSMR": + switch self.touchPadString{ + case "MOUSEPAD": LiSendMouseMoveEvent(Int16(truncatingIfNeeded: Int(deltaX * 1.7 * sensitivityFactor)), Int16(truncatingIfNeeded: Int(deltaY * 1.7 * sensitivityFactor))) break - case "LSPAD", "YSLT": - self.sendLeftStickTouchPadEvent(inputX: offSetX * sensitivityFactor, inputY: offSetY*sensitivityFactor) - updateStickIndicator() + case "LSPAD": + self.sendLeftStickTouchPadEvent(inputX: offSetX * sensitivityFactor, inputY: offSetY * sensitivityFactor) + if widgetType == WidgetTypeEnum.touchPad {updateStickIndicator()} case "RSPAD": self.sendRightStickTouchPadEvent(inputX: offSetX * sensitivityFactor, inputY: offSetY * sensitivityFactor); - updateStickIndicator() + if widgetType == WidgetTypeEnum.touchPad {updateStickIndicator()} case "LSVPAD": self.sendLeftStickTouchPadEvent(inputX: deltaX*1.5167*sensitivityFactor, inputY: deltaY*1.5167*sensitivityFactor) - case "RSVPAD", "YSB", "YSRT", "YSRB", "YSRSV": + case "RSVPAD": self.sendRightStickTouchPadEvent(inputX: deltaX*1.5167*sensitivityFactor, inputY: deltaY*1.5167*sensitivityFactor); - case "DPAD", "WASDPAD", "ARROWPAD", "YSWASD": + case "DPAD", "WASDPAD", "ARROWPAD": handleLrudTouchMove() default: break } - } } @@ -1070,13 +1103,13 @@ import UIKit // for checking stationary touch points - if self.keyString != "MOUSEPAD" {quickDoubleTapDetected = false} //do not reset this flag here in mousePad mode + if self.touchPadString != "MOUSEPAD" {quickDoubleTapDetected = false} //do not reset this flag here in mousePad mode let allCapturedTouchesCount = event?.allTouches?.filter({ $0.view == self }).count // this will counts all valid touches within the self widgetView, and excludes touches in other widgetViews - // deal with MOUSPAD first - if !OnScreenWidgetView.editMode && self.keyString == "MOUSEPAD" && allCapturedTouchesCount == 1 && !twoTouchesDetected { + // deal with pure MOUSPAD first + if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && allCapturedTouchesCount == 1 && !twoTouchesDetected { if !mousePointerMoved && !quickDoubleTapDetected {self.sendLongMouseLeftButtonClickEvent()} // deal with single tap(click) if quickDoubleTapDetected { //deal with quick double tap LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT) //must release the button anyway, because the button is likely being held down since the long click turned into a dragging event. @@ -1085,29 +1118,26 @@ import UIKit } mousePointerMoved = false // reset this flag } - - if !OnScreenWidgetView.editMode && self.keyString == "MOUSEPAD" && twoTouchesDetected && touches.count == allCapturedTouchesCount { // need to enable multi-touch first + if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "MOUSEPAD" && twoTouchesDetected && touches.count == allCapturedTouchesCount { // need to enable multi-touch first // touches.count == allCapturedTouchesCount means allfingers are lifting self.sendMouseRightButtonClickEvent() twoTouchesDetected = false } - // then other types of pads - if !OnScreenWidgetView.editMode && (CommandManager.touchPadCmds.contains(self.keyString) || CommandManager.yuanshenStickPadButtonCmds.contains(self.keyString)) { - switch self.keyString{ + // then other types of pads or buttons with touchPad function + if !OnScreenWidgetView.editMode && !self.touchPadString.isEmpty { + switch self.touchPadString{ case "LSPAD": self.onScreenControls.clearLeftStickTouchPadFlag() - self.resetStickBallPositionAndRemoveIndicator() - case "YSLT": - self.onScreenControls.clearLeftStickTouchPadFlag() + if widgetType == WidgetTypeEnum.touchPad {self.resetStickBallPositionAndRemoveIndicator()} case "RSPAD": self.onScreenControls.clearRightStickTouchPadFlag() - self.resetStickBallPositionAndRemoveIndicator() + if widgetType == WidgetTypeEnum.touchPad {self.resetStickBallPositionAndRemoveIndicator()} case "LSVPAD": self.onScreenControls.clearLeftStickTouchPadFlag() - case "RSVPAD", "YSB", "YSRT", "YSRB", "YSRSV": + case "RSVPAD": self.onScreenControls.clearRightStickTouchPadFlag() - case "WASDPAD","YSWASD": + case "WASDPAD": LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_UP), 0) LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["A"]!,Int8(KEY_ACTION_UP), 0) LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["S"]!,Int8(KEY_ACTION_UP), 0) @@ -1133,27 +1163,13 @@ import UIKit self.rightIndicator.removeFromSuperlayer() self.lrudIndicatorBall.removeFromSuperlayer() - if !OnScreenWidgetView.editMode && !self.keyString.contains("+") && !self.keyString.contains("-") { // if the command(keystring contains "+", it's a multi-key command rather than a single key button - if CommandManager.oscButtonMappings.keys.contains(self.keyString) { - sendOscButtonUpEvent(keyString: self.keyString) - } - if CommandManager.keyboardButtonMappings.keys.contains(self.keyString) { - LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[self.keyString]!,Int8(KEY_ACTION_UP), 0) - } - if CommandManager.mouseButtonMappings.keys.contains(self.keyString){ - LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), Int32(CommandManager.mouseButtonMappings[self.keyString]!)) - } + if !OnScreenWidgetView.editMode && !self.cmdString.contains("+") && !self.comboButtonStrings.isEmpty { // if the command(keystring contains "+", it's a legacy multi-key command + self.sendComboButtonsUpEvent(comboStrings: self.comboButtonStrings) } - // if the command(keystring contains "-", it's a multi-type super combo button - if !OnScreenWidgetView.editMode && self.keyString.contains("-"){ - let comboStrings = CommandManager.shared.extractSinglCmdStringsFromComboKeys(from: self.keyString)! - self.sendComboButtonsUpEvent(comboStrings: comboStrings) - } - - if !OnScreenWidgetView.editMode && CommandManager.specialOverlayButtonCmds.contains(self.keyString){ + if !OnScreenWidgetView.editMode && CommandManager.specialOverlayButtonCmds.contains(self.cmdString){ if CACurrentMediaTime() - self.touchTapTimeStamp < 0.3 { - switch self.keyString { + switch self.cmdString { case "SETTINGS": NotificationCenter.default.post(name: Notification.Name("SettingsOverlayButtonPressedNotification"), object:nil) // inform layout tool controller to fetch button size factors. self will be passed as the object of the notification default: @@ -1183,11 +1199,15 @@ import UIKit setupView(); //re-setup widgetView style - if CommandManager.nonVectorStickPads.contains(self.keyString) { - self.crossMarkLayer.removeFromSuperlayer() - self.stickBallLayer.removeFromSuperlayer() - self.showStickIndicator() - self.updateStickIndicator() + self.crossMarkLayer.removeFromSuperlayer() + self.stickBallLayer.removeFromSuperlayer() + if self.widgetType == WidgetTypeEnum.touchPad{ + switch self.touchPadString{ + case "LSPAD", "RSPAD": + self.showStickIndicator() + self.updateStickIndicator() + default: break + } } } diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 70d649ab..8f115573 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -393,7 +393,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; for (NSData *buttonStateEncoded in oscProfile.buttonStates) { OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil]; if(buttonState.buttonType == CustomOnScreenWidget){ - OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView + OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView //-------------------------------------------------- onScreenControls.delegate = widgetView; // connecting onScreenControls to OnScreenWidgetView, sending the active instance for touchPad stick control [onScreenControls sendInstance]; @@ -404,6 +404,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5; widgetView.borderWidth = buttonState.borderWidth; widgetView.sensitivityFactor = buttonState.sensitivityFactor; widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; + widgetView.minStickOffset = buttonState.minStickOffset; // Add the widgetView to the view controller's view [self->streamFrameTopLayerView addSubview:widgetView]; // add keyboard button to the stream frame view. must add it to the target view before setting location. [widgetView setLocationWithXOffset:buttonState.position.x yOffset:buttonState.position.y]; diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index c3a28091..06bf4f47 100644 --- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -69,6 +69,9 @@ } - (void) reloadOnScreenWidgetViews { + [self->selectedWidgetView.stickBallLayer removeFromSuperlayer]; + [self->selectedWidgetView.crossMarkLayer removeFromSuperlayer]; + for (UIView *subview in self.view.subviews) { // 检查子视图是否是特定类型的实例 if ([subview isKindOfClass:[OnScreenWidgetView class]]) { @@ -78,6 +81,7 @@ } [self.OnScreenWidgetViews removeAllObjects]; + NSLog(@"reload os Key here"); @@ -86,14 +90,14 @@ for (NSData *buttonStateEncoded in oscProfile.buttonStates) { OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil]; if(buttonState.buttonType == CustomOnScreenWidget){ - OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView + OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place widgetView.widthFactor = buttonState.widthFactor; widgetView.heightFactor = buttonState.heightFactor; widgetView.borderWidth = buttonState.borderWidth; widgetView.sensitivityFactor = buttonState.sensitivityFactor; widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; - // widgetView.backgroundAlpha = buttonState.backgroundAlpha; + widgetView.minStickOffset = buttonState.minStickOffset; // Add the widgetView to the view controller's view [self.view addSubview:widgetView]; [widgetView setLocationWithXOffset:buttonState.position.x yOffset:buttonState.position.y]; @@ -350,8 +354,8 @@ - (IBAction) addTapped:(id)sender{ - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"New On-Screen Widget"] - message:[LocalizationHelper localizedStringForKey:@"Enter the command & alias label"] + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@""] + message:[LocalizationHelper localizedStringForKey:@"New On-Screen Widget"] preferredStyle:UIAlertControllerStyleAlert]; [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { @@ -367,13 +371,31 @@ textField.autocorrectionType = UITextAutocorrectionTypeNo; textField.spellCheckingType = UITextSpellCheckingTypeNo; }]; - + + [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.placeholder = [LocalizationHelper localizedStringForKey:@"Minimum stick offset (0~32766)"]; + textField.keyboardType = UIKeyboardTypeASCIICapable; + textField.autocorrectionType = UITextAutocorrectionTypeNo; + textField.spellCheckingType = UITextSpellCheckingTypeNo; + }]; + [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.placeholder = [LocalizationHelper localizedStringForKey:@"Shape (r - round, s - square)"]; textField.keyboardType = UIKeyboardTypeASCIICapable; textField.autocorrectionType = UITextAutocorrectionTypeNo; textField.spellCheckingType = UITextSpellCheckingTypeNo; }]; + + + UIAlertAction *readInstruction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Read Widget Instruction"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action){ + NSURL *url = [NSURL URLWithString:@"https://b23.tv/J8qEXOr"]; + if ([[UIApplication sharedApplication] canOpenURL:url]) { + [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; + } + }]; + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel @@ -391,40 +413,47 @@ alertController.textFields[1].spellCheckingType = UITextSpellCheckingTypeNo;*/ NSString *cmdString = [alertController.textFields[0].text uppercaseString]; // convert to uppercase - NSString *keyLabel = alertController.textFields[1].text; - NSString *widgetShape = [alertController.textFields[2].text lowercaseString]; + NSString *buttonLabel = alertController.textFields[1].text; + NSString *minStickOffsetString = alertController.textFields[2].text; + NSString *widgetShape = [alertController.textFields[3].text lowercaseString]; + - if([keyLabel isEqualToString:@""]) keyLabel = [[cmdString lowercaseString] capitalizedString]; + if([buttonLabel isEqualToString:@""]) buttonLabel = [[cmdString lowercaseString] capitalizedString]; bool noValidKeyboardString = [CommandManager.shared extractKeyStringsFromComboCommandFrom:cmdString] == nil; // this is a invalid string. bool noValidSuperComboButtonString = [CommandManager.shared extractSinglCmdStringsFromComboKeysFrom:cmdString] == nil; // this is a invalid string. bool noValidMouseButtonString = ![CommandManager.mouseButtonMappings.allKeys containsObject:cmdString]; bool noValidTouchPadString = ![CommandManager.touchPadCmds containsObject:cmdString]; bool noValidOscButtonString = ![CommandManager.oscButtonMappings.allKeys containsObject:cmdString]; bool noValidSpecialButtonString = ![CommandManager.specialOverlayButtonCmds containsObject:cmdString]; - bool noValidSpecialGameWidgetString = ![CommandManager.specialGameWidgets containsObject:cmdString]; - bool invalidInput = noValidKeyboardString && noValidMouseButtonString && noValidTouchPadString && noValidOscButtonString && noValidSpecialButtonString && noValidSuperComboButtonString && noValidSpecialGameWidgetString; + bool invalidInput = noValidKeyboardString && noValidMouseButtonString && noValidTouchPadString && noValidOscButtonString && noValidSpecialButtonString && noValidSuperComboButtonString; if([widgetShape isEqualToString:@"r"]) widgetShape = @"round"; else if([widgetShape isEqualToString:@"s"]) widgetShape = @"square"; else if([widgetShape isEqualToString:@""]) widgetShape = @"default"; else invalidInput = true; + NSCharacterSet *nonDigitCharacterSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + NSString *trimmedString = [minStickOffsetString stringByTrimmingCharactersInSet:nonDigitCharacterSet]; + if(trimmedString.length != minStickOffsetString.length) invalidInput = true; + minStickOffsetString = trimmedString; + if(invalidInput) { [self presentInvalidWidgetCommandAlert]; return; } //saving & present the keyboard button: - OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithKeyString:cmdString keyLabel:keyLabel shape:widgetShape]; + OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:cmdString buttonLabel:buttonLabel shape:widgetShape]; widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place - + widgetView.minStickOffset = [minStickOffsetString floatValue]; [self.OnScreenWidgetViews addObject:widgetView]; // Add the widgetView to the view controller's view [self.view addSubview:widgetView]; [widgetView setLocationWithXOffset:50 yOffset:50]; [widgetView resizeWidgetView]; }]; + [alertController addAction:readInstruction]; [alertController addAction:cancelAction]; [alertController addAction:okAction]; [self presentViewController:alertController animated:YES completion:nil]; @@ -466,12 +495,8 @@ [self.widgetAlphaSlider setValue: self->selectedWidgetView.backgroundAlpha]; [self.widgetBorderWidthSlider setValue:self->selectedWidgetView.borderWidth]; - NSSet *stickAndMouseTouchpads = [NSSet setWithObjects:@"YSRSV", @"YSB", @"YSLT", @"YSRT", @"YSRB",@"YSB2", @"YSRT2", @"YSRB2", @"YSEM", @"YSML", @"YSMR", @"LSPAD", @"RSPAD", @"LSVPAD", @"RSVPAD", @"MOUSEPAD", nil]; - NSSet *nonVectorStickPads = [NSSet setWithObjects: @"LSPAD", @"RSPAD", nil]; - - - bool showSensitivityFactorSlider = [stickAndMouseTouchpads containsObject:self->selectedWidgetView.keyString]; - bool showStickIndicatorOffsetSlider = [nonVectorStickPads containsObject:self->selectedWidgetView.keyString]; + bool showSensitivityFactorSlider = selectedWidgetView.hasSensitivityTweak; + bool showStickIndicatorOffsetSlider = selectedWidgetView.hasStickIndicator; self.sensitivityFactorSlider.hidden = self->sensitivitySliderLabel.hidden = !showSensitivityFactorSlider; self.stickIndicatorOffsetSlider.hidden = self->stickIndicatorOffsetExplain.hidden = self->stickIndicatorOffsetSliderLabel.hidden = !showStickIndicatorOffsetSlider; if(showSensitivityFactorSlider){