- button widget skill combo enhanced to macro
- widget picker view UI fixes
This commit is contained in:
1 parent
a7088c70e5
commit
2c2088e4b1
11 files changed
+2057
-312
No files matched your search
@@ -531,7 +531,7 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (index, key) in validKeyStrings.enumerated() {
|
for (index, key) in validKeyStrings.enumerated() {
|
||||||
print("Valid Key \(index): \(key)")
|
// print("Valid Key \(index): \(key)")
|
||||||
}
|
}
|
||||||
|
|
||||||
return validKeyStrings
|
return validKeyStrings
|
||||||
@@ -540,56 +540,72 @@ import UIKit
|
|||||||
|
|
||||||
//super combo key button strings
|
//super combo key button strings
|
||||||
@objc public func extractCmdStrings(from input: String) -> [String]? {
|
@objc public func extractCmdStrings(from input: String) -> [String]? {
|
||||||
let input = input.uppercased()
|
|
||||||
let combinedStrings = [CommandManager.keyboardButtonMappings.keys.map { $0 as String },
|
|
||||||
CommandManager.oscButtonMappings.keys.map { $0 as String },
|
|
||||||
CommandManager.mouseButtonMappings.keys.map { $0 as String },
|
|
||||||
CommandManager.functionalButtonCmds.map { $0 as String },
|
|
||||||
CommandManager.motionControlButtonCmds.map { $0 as String },
|
|
||||||
CommandManager.touchPadCmds.map { $0 as String }
|
|
||||||
]
|
|
||||||
.lazy
|
|
||||||
.flatMap { $0 } // 三维展开
|
|
||||||
.map(String.init(describing:)) // 安全类型转换
|
|
||||||
|
|
||||||
let keys = combinedStrings.joined(separator: "|")
|
|
||||||
let pattern = "^(?:\(keys))(?:-(?:\(keys)))*(?:-\\d+MS)?$"
|
|
||||||
|
|
||||||
|
|
||||||
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
|
|
||||||
print("Failed to create regex")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
let range = NSRange(location: 0, length: input.utf16.count)
|
|
||||||
guard let match = regex.firstMatch(in: input, options: [], range: range) else {
|
|
||||||
print("No match found for input: \(input)")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// print("Regex matched for input: \(input)")
|
|
||||||
|
|
||||||
let matchedString = (input as NSString).substring(with: match.range(at: 0))
|
|
||||||
let cmdStrings = matchedString.split(separator: "-").map { String($0) }
|
|
||||||
|
|
||||||
guard !cmdStrings.isEmpty else {
|
|
||||||
print("No key strings found in the matched string")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var validCmdStrings: [String] = []
|
var validCmdStrings: [String] = []
|
||||||
|
|
||||||
for key in cmdStrings {
|
if GenericUtils.isGUIWidgetPickerAvailable {
|
||||||
validCmdStrings.append(key)
|
let cmdStrings = input
|
||||||
|
.split(separator: "-")
|
||||||
|
.map { String($0) }
|
||||||
|
|
||||||
|
guard !cmdStrings.isEmpty else {
|
||||||
|
print("No key strings found in the input string")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for key in cmdStrings {
|
||||||
|
validCmdStrings.append(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if validCmdStrings.isEmpty {
|
let input = input.uppercased()
|
||||||
print("No valid key strings found in the matched string")
|
let combinedStrings = [CommandManager.keyboardButtonMappings.keys.map { $0 as String },
|
||||||
return nil
|
CommandManager.oscButtonMappings.keys.map { $0 as String },
|
||||||
|
CommandManager.mouseButtonMappings.keys.map { $0 as String },
|
||||||
|
CommandManager.functionalButtonCmds.map { $0 as String },
|
||||||
|
CommandManager.motionControlButtonCmds.map { $0 as String },
|
||||||
|
CommandManager.touchPadCmds.map { $0 as String }
|
||||||
|
]
|
||||||
|
.lazy
|
||||||
|
.flatMap { $0 } // 三维展开
|
||||||
|
.map(String.init(describing:)) // 安全类型转换
|
||||||
|
|
||||||
|
let keys = combinedStrings.joined(separator: "|")
|
||||||
|
let pattern = "^(?:\(keys))(?:-(?:\(keys)))*(?:-\\d+MS)?$"
|
||||||
|
|
||||||
|
|
||||||
|
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
|
||||||
|
print("Failed to create regex")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let range = NSRange(location: 0, length: input.utf16.count)
|
||||||
|
guard let match = regex.firstMatch(in: input, options: [], range: range) else {
|
||||||
|
print("No match found for input: \(input)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// print("Regex matched for input: \(input)")
|
||||||
|
|
||||||
|
let matchedString = (input as NSString).substring(with: match.range(at: 0))
|
||||||
|
let cmdStrings = matchedString.split(separator: "-").map { String($0) }
|
||||||
|
|
||||||
|
guard !cmdStrings.isEmpty else {
|
||||||
|
print("No key strings found in the matched string")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for key in cmdStrings {
|
||||||
|
validCmdStrings.append(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
if validCmdStrings.isEmpty {
|
||||||
|
print("No valid key strings found in the matched string")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, key) in validCmdStrings.enumerated() {
|
for (index, key) in validCmdStrings.enumerated() {
|
||||||
print("Valid Key \(index): \(key)")
|
print("Valid Key \(index): \(key)")
|
||||||
}
|
}
|
||||||
|
|
||||||
return validCmdStrings
|
return validCmdStrings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -453,17 +453,6 @@ import ObjectiveC.runtime
|
|||||||
// 安全解包并处理 `comboKeyStrings`
|
// 安全解包并处理 `comboKeyStrings`
|
||||||
if var comboStrings = CommandManager.shared.extractCmdStrings(from: self.cmdString) {
|
if var comboStrings = CommandManager.shared.extractCmdStrings(from: self.cmdString) {
|
||||||
|
|
||||||
// extract timeInterval
|
|
||||||
if let lastString = comboStrings.last, lastString.contains("MS") {
|
|
||||||
// 移除 "MS" 后的部分并转换为整数
|
|
||||||
let timeIntervalString = lastString.replacingOccurrences(of: "MS", with: "")
|
|
||||||
// 安全地将字符串转换为整数
|
|
||||||
if let timeInterval = UInt32(timeIntervalString) {
|
|
||||||
self.comboKeyTimeIntervalMs = timeInterval
|
|
||||||
} else {print("无法将时间字符串转换为整数")}
|
|
||||||
comboStrings.removeLast()
|
|
||||||
}
|
|
||||||
|
|
||||||
if CommandManager.touchPadCmds.contains(comboStrings.first ?? "") {self.widgetType = WidgetTypeEnum.touchPad}
|
if CommandManager.touchPadCmds.contains(comboStrings.first ?? "") {self.widgetType = WidgetTypeEnum.touchPad}
|
||||||
else {self.widgetType = WidgetTypeEnum.button}
|
else {self.widgetType = WidgetTypeEnum.button}
|
||||||
|
|
||||||
@@ -1322,6 +1311,9 @@ import ObjectiveC.runtime
|
|||||||
let indicatorFrame = CAShapeLayer();
|
let indicatorFrame = CAShapeLayer();
|
||||||
indicatorFrame.frame = CGRectMake(0, 0, 75*highlightSizeFactor, 75*highlightSizeFactor)
|
indicatorFrame.frame = CGRectMake(0, 0, 75*highlightSizeFactor, 75*highlightSizeFactor)
|
||||||
indicatorFrame.cornerRadius = 23 * highlightSizeFactor
|
indicatorFrame.cornerRadius = 23 * highlightSizeFactor
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
indicatorFrame.cornerCurve = .continuous
|
||||||
|
}
|
||||||
directionLayer.borderWidth = 5.3 * min(1.0, highlightSizeFactor)
|
directionLayer.borderWidth = 5.3 * min(1.0, highlightSizeFactor)
|
||||||
directionLayer.frame = indicatorFrame.bounds.insetBy(dx: -directionLayer.borderWidth, dy: -directionLayer.borderWidth) // Adjust the inset as needed
|
directionLayer.frame = indicatorFrame.bounds.insetBy(dx: -directionLayer.borderWidth, dy: -directionLayer.borderWidth) // Adjust the inset as needed
|
||||||
directionLayer.cornerRadius = indicatorFrame.cornerRadius + directionLayer.borderWidth
|
directionLayer.cornerRadius = indicatorFrame.cornerRadius + directionLayer.borderWidth
|
||||||
@@ -1896,44 +1888,136 @@ import ObjectiveC.runtime
|
|||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
private func sendComboButtonsDownEvent(comboStrings: [String]) {
|
|
||||||
|
private var hasUnifiedTriggerInterval: Bool {
|
||||||
|
if let lastString = comboButtonStrings.last, lastString.contains("MS") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else {return false}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getMilliSecIntervalFrom(intervalString: String?) -> UInt32{
|
||||||
|
guard let timeIntervalString = intervalString?.replacingOccurrences(of: "MS", with: "") else { return 0 }
|
||||||
|
if let timeInterval = UInt32(timeIntervalString) {
|
||||||
|
return timeInterval
|
||||||
|
}
|
||||||
|
else {return 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getMilliSecIntervalFrom(cmdString: String) -> UInt32{
|
||||||
|
if cmdString.contains(".") {
|
||||||
|
let intervalString = cmdString.split(separator: ".").last.map(String.init)
|
||||||
|
return getMilliSecIntervalFrom(intervalString: intervalString)
|
||||||
|
}
|
||||||
|
else {return 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleButtonStringDown(_ buttonString: String) {
|
||||||
|
let realButtonString: String
|
||||||
|
if buttonString.contains(".") {
|
||||||
|
realButtonString = buttonString.split(separator: ".").first.map(String.init)!
|
||||||
|
DispatchQueue.global().asyncAfter(deadline: .now() + Double(getMilliSecIntervalFrom(cmdString: buttonString))/1000) {
|
||||||
|
self.handleButtonStringUp(realButtonString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {realButtonString = buttonString}
|
||||||
DispatchQueue.global(qos: .userInteractive).async {
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
for comboString in comboStrings {
|
if CommandManager.oscButtonMappings.keys.contains(realButtonString) {
|
||||||
if CommandManager.oscButtonMappings.keys.contains(comboString) {
|
self.sendOscButtonDownEvent(oscString: realButtonString)
|
||||||
self.sendOscButtonDownEvent(oscString: comboString)
|
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = true}
|
||||||
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = true}
|
}
|
||||||
|
if CommandManager.keyboardButtonMappings.keys.contains(realButtonString) {
|
||||||
|
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[realButtonString]!,Int8(KEY_ACTION_DOWN), 0)
|
||||||
|
}
|
||||||
|
if CommandManager.mouseButtonMappings.keys.contains(realButtonString), self.functionalButtonString != "ABSTCHDRAG" {
|
||||||
|
let button = Int32(CommandManager.mouseButtonMappings[realButtonString]!)
|
||||||
|
if abs(button) == 0xFF {
|
||||||
|
LiSendScrollEvent(button>0 ? 3 : -3)
|
||||||
}
|
}
|
||||||
if CommandManager.keyboardButtonMappings.keys.contains(comboString) {
|
else {LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), button)}
|
||||||
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[comboString]!,Int8(KEY_ACTION_DOWN), 0)
|
}
|
||||||
}
|
}
|
||||||
if CommandManager.mouseButtonMappings.keys.contains(comboString), self.functionalButtonString != "ABSTCHDRAG" {
|
}
|
||||||
let button = Int32(CommandManager.mouseButtonMappings[comboString]!)
|
|
||||||
if abs(button) == 0xFF {
|
private func sendComboButtonsDownEvent(comboStrings: [String]) {
|
||||||
LiSendScrollEvent(button>0 ? 3 : -3)
|
let hasUnifiedTriggerInterval = self.hasUnifiedTriggerInterval
|
||||||
|
if hasUnifiedTriggerInterval {
|
||||||
|
self.comboKeyTimeIntervalMs = self.getMilliSecIntervalFrom(intervalString: comboStrings.last!)
|
||||||
|
}
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
Task {
|
||||||
|
for cmdString in comboStrings {
|
||||||
|
let isIntervalCmd = cmdString.contains("MS")
|
||||||
|
let triggerDelay = hasUnifiedTriggerInterval
|
||||||
|
? self.comboKeyTimeIntervalMs :
|
||||||
|
( isIntervalCmd ? self.getMilliSecIntervalFrom(intervalString: cmdString) : 0)
|
||||||
|
|
||||||
|
if hasUnifiedTriggerInterval || !isIntervalCmd {
|
||||||
|
self.handleButtonStringDown(cmdString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdString != comboStrings.last {
|
||||||
|
try? await Task.sleep(nanoseconds: UInt64(triggerDelay)*1_000_000)
|
||||||
}
|
}
|
||||||
else {LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), button)}
|
|
||||||
}
|
}
|
||||||
if comboString != comboStrings.last {
|
}
|
||||||
usleep(self.comboKeyTimeIntervalMs*1000) // delay xxx ms
|
} else {
|
||||||
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
|
for comboString in comboStrings {
|
||||||
|
self.handleButtonStringDown(comboString)
|
||||||
|
if comboString != comboStrings.last {
|
||||||
|
usleep(hasUnifiedTriggerInterval ? self.comboKeyTimeIntervalMs*1000 : 0) // delay xxx ms
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendComboButtonsUpEvent(comboStrings: [String]) {
|
private func handleButtonStringUp(_ buttonString: String) {
|
||||||
|
if buttonString.contains(".") {return}
|
||||||
DispatchQueue.global(qos: .userInteractive).async {
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
for comboString in comboStrings {
|
if CommandManager.oscButtonMappings.keys.contains(buttonString) {
|
||||||
if CommandManager.oscButtonMappings.keys.contains(comboString) {
|
self.sendOscButtonUpEvent(oscString: buttonString)
|
||||||
self.sendOscButtonUpEvent(oscString: comboString)
|
}
|
||||||
|
if CommandManager.keyboardButtonMappings.keys.contains(buttonString) {
|
||||||
|
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[buttonString]!,Int8(KEY_ACTION_UP), 0)
|
||||||
|
}
|
||||||
|
if CommandManager.mouseButtonMappings.keys.contains(buttonString) {
|
||||||
|
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), Int32(CommandManager.mouseButtonMappings[buttonString]!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func sendComboButtonsUpEvent(comboStrings: [String]) {
|
||||||
|
let hasUnifiedTriggerInterval = self.hasUnifiedTriggerInterval
|
||||||
|
if hasUnifiedTriggerInterval {
|
||||||
|
self.comboKeyTimeIntervalMs = self.getMilliSecIntervalFrom(intervalString: comboStrings.last!)
|
||||||
|
}
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
Task {
|
||||||
|
for cmdString in comboStrings {
|
||||||
|
let isIntervalCmd = cmdString.contains("MS")
|
||||||
|
let triggerDelay = hasUnifiedTriggerInterval
|
||||||
|
? self.comboKeyTimeIntervalMs :
|
||||||
|
( isIntervalCmd ? self.getMilliSecIntervalFrom(intervalString: cmdString) : 0)
|
||||||
|
|
||||||
|
if hasUnifiedTriggerInterval || !isIntervalCmd {
|
||||||
|
self.handleButtonStringUp(cmdString)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmdString != comboStrings.last {
|
||||||
|
try? await Task.sleep(nanoseconds: UInt64(triggerDelay)*1_000_000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if CommandManager.keyboardButtonMappings.keys.contains(comboString) {
|
}
|
||||||
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[comboString]!,Int8(KEY_ACTION_UP), 0)
|
} else {
|
||||||
}
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
if CommandManager.mouseButtonMappings.keys.contains(comboString) {
|
for comboString in comboStrings {
|
||||||
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), Int32(CommandManager.mouseButtonMappings[comboString]!))
|
self.handleButtonStringUp(comboString)
|
||||||
}
|
if comboString != comboStrings.last {
|
||||||
if comboString != comboStrings.last {
|
self.handleButtonStringUp(comboString)
|
||||||
usleep(self.comboKeyTimeIntervalMs*1000) // delay xxx ms
|
usleep(self.comboKeyTimeIntervalMs*1000) // delay xxx ms
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -437,9 +437,7 @@ import UIKit
|
|||||||
pickerViewController.initialTabIdentifier = "keyboard"
|
pickerViewController.initialTabIdentifier = "keyboard"
|
||||||
pickerViewController.shortcutIdentifier = "eraser"
|
pickerViewController.shortcutIdentifier = "eraser"
|
||||||
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "Select eraser shortcut keys")
|
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "Select eraser shortcut keys")
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: viewController)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
viewController.present(nav, animated: true)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,9 +487,7 @@ import UIKit
|
|||||||
pickerViewController.initialTabIdentifier = "keyboard"
|
pickerViewController.initialTabIdentifier = "keyboard"
|
||||||
pickerViewController.shortcutIdentifier = "brush"
|
pickerViewController.shortcutIdentifier = "brush"
|
||||||
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "Select brush shortcut keys")
|
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "Select brush shortcut keys")
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: viewController)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
viewController.present(nav, animated: true)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -551,9 +547,7 @@ import UIKit
|
|||||||
pickerViewController.initialTabIdentifier = "keyboard"
|
pickerViewController.initialTabIdentifier = "keyboard"
|
||||||
pickerViewController.shortcutIdentifier = "squeezePress"
|
pickerViewController.shortcutIdentifier = "squeezePress"
|
||||||
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "squeezePressShortcutPickerTip")
|
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "squeezePressShortcutPickerTip")
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: viewController)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
viewController.present(nav, animated: true)
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
@@ -604,9 +598,7 @@ import UIKit
|
|||||||
pickerViewController.initialTabIdentifier = "keyboard"
|
pickerViewController.initialTabIdentifier = "keyboard"
|
||||||
pickerViewController.shortcutIdentifier = "squeezeRelease"
|
pickerViewController.shortcutIdentifier = "squeezeRelease"
|
||||||
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "squeezeReleaseShortcutPickerTip")
|
pickerViewController.shortcutPickerTipText = LocalizationHelper.localizedString(forKey: "squeezeReleaseShortcutPickerTip")
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: viewController)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
viewController.present(nav, animated: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -935,7 +935,7 @@
|
|||||||
},
|
},
|
||||||
"zh-Hans" : {
|
"zh-Hans" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "needs_review",
|
"state" : "translated",
|
||||||
"value" : "陀螺仪+右摇杆"
|
"value" : "陀螺仪+右摇杆"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2100,6 +2100,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Action mode" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "操作模式"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "操作模式"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "操作模式"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Activate toolbox menu during streaming" : {
|
"Activate toolbox menu during streaming" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -3390,6 +3413,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Confirm" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "确定"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "確定"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "確定"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Connecting" : {
|
"Connecting" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -3603,6 +3649,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Continue adding controls to this combination, or tap button in the pool to set macro." : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "继续向此组合添加控件,或点按池中的按钮以设置宏。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "繼續向此組合加入控制項,或點按池中的按鈕以設定巨集。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "繼續向此組合加入控制項,或點按池中的按鈕以設定巨集。"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Controller" : {
|
"Controller" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -6427,6 +6496,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Gyro button" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "陀螺仪开关"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "陀螺儀開關"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "陀螺儀開關"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Gyro Button" : {
|
"Gyro Button" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -6519,29 +6611,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Gyro switch button" : {
|
|
||||||
"extractionState" : "manual",
|
|
||||||
"localizations" : {
|
|
||||||
"zh-Hans" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "陀螺仪切换按键"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hant" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "陀螺儀切換按鍵"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-HK" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "陀螺儀切換按鍵"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Gyro widgets cannot be combined with direction pad" : {
|
"Gyro widgets cannot be combined with direction pad" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -6842,6 +6911,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Hold until release" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按压直至松开"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按壓直至鬆開"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按壓直至鬆開"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Host information updated" : {
|
"Host information updated" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -10183,6 +10275,98 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Press duration" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按压时长"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按壓時長"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按壓時長"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Press duration: %d ms" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按压时长: %d ms"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按壓時長: %d ms"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "按壓時長: %d ms"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Manually enter press duration in milliseconds" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "手动输入按压时长, 单位毫秒"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "手動輸入按壓時長, 單位毫秒"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "手動輸入按壓時長, 單位毫秒"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Manually enter trigger interval in milliseconds" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "手动输入间隔,单位毫秒"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "手動輸入間隔,單位毫秒"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "手動輸入間隔,單位毫秒"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Press the button for mouse left button" : {
|
"Press the button for mouse left button" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -10229,6 +10413,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Pressed for %dms" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "↓ %dms"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "↓ %dms"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "↓ %dms"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Pressure curve" : {
|
"Pressure curve" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -12912,6 +13119,52 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tap" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "单击"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "單擊"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "單擊"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Tap" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "单击"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "單擊"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "單擊"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Tap 'OK' to set on-screen widget to 'Custom' and enable motion control." : {
|
"Tap 'OK' to set on-screen widget to 'Custom' and enable motion control." : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -13234,6 +13487,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Timed release" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "定时松开"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "定時鬆開"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "定時鬆開"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Tips" : {
|
"Tips" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -14487,25 +14763,163 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"You can continue adding controls to this combination" : {
|
"Insert trigger interval" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"zh-Hans" : {
|
"zh-Hans" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "你可以继续向此组合添加控件"
|
"value" : "插入触发间隔"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zh-Hant" : {
|
"zh-Hant" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "你可以繼續向此組合加入控制項"
|
"value" : "插入觸發間隔"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zh-HK" : {
|
"zh-HK" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "translated",
|
||||||
"value" : "你可以繼續向此組合加入控制項"
|
"value" : "插入觸發間隔"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Not enough room to insert trigger interval slots" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "没有足够空间插入触发间隔格"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "沒有足夠空間插入觸發間隔格"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "沒有足夠空間插入觸發間隔格"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Select at least two button controls before inserting trigger intervals" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "请至少先选择两个按钮型控件,再插入触发间隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "請至少先選擇兩個按鈕型控制項,再插入觸發間隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "請至少先選擇兩個按鈕型控制項,再插入觸發間隔"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Set all" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "统一设置间隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "統一設定間隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "統一設定間隔"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Set this" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "单独设置间隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "單獨設定間隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "單獨設定間隔"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Trigger interval cannot be inserted when WASDPAD or ARROWPAD is in the pool" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "池中存在 WASDPAD 或 ARROWPAD 时,不能插入触发间隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "池中存在 WASDPAD 或 ARROWPAD 時,不能插入觸發間隔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "池中存在 WASDPAD 或 ARROWPAD 時,不能插入觸發間隔"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Trigger interval slots are already inserted" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "触发间隔格已经插入"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "觸發間隔格已經插入"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "觸發間隔格已經插入"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14596,4 +15010,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version" : "1.1"
|
"version" : "1.1"
|
||||||
}
|
}
|
||||||
@@ -434,6 +434,14 @@ import UIKit
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@objc static let isGUIWidgetPickerAvailable: Bool = {
|
||||||
|
if #available(iOS 13.0, tvOS 13.0, *) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
@objc static let menuSeparatorWidth: CGFloat = 0.7
|
@objc static let menuSeparatorWidth: CGFloat = 0.7
|
||||||
@objc static let menuSectionSeparatorWidth: CGFloat = 0.7
|
@objc static let menuSectionSeparatorWidth: CGFloat = 0.7
|
||||||
|
|||||||
+2
-6
@@ -1446,9 +1446,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
|
|||||||
pickerViewController.delegate = self
|
pickerViewController.delegate = self
|
||||||
pickerViewController.tabIdentifiers = ["gamepad", "keyboard", "functional"]
|
pickerViewController.tabIdentifiers = ["gamepad", "keyboard", "functional"]
|
||||||
pickerViewController.initialTabIdentifier = "gamepad"
|
pickerViewController.initialTabIdentifier = "gamepad"
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: self)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
present(nav, animated: true)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1487,9 +1485,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
|
|||||||
pickerViewController.initialCmdString = selectedWidget.cmdString
|
pickerViewController.initialCmdString = selectedWidget.cmdString
|
||||||
pickerViewController.initialButtonLabel = selectedWidget.widgetLabel
|
pickerViewController.initialButtonLabel = selectedWidget.widgetLabel
|
||||||
pickerViewController.initialShape = selectedWidget.shape
|
pickerViewController.initialShape = selectedWidget.shape
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: self)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
present(nav, animated: true)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -292,9 +292,7 @@ import UIKit
|
|||||||
pickerViewController.shortcutPickerNeedAlias = true
|
pickerViewController.shortcutPickerNeedAlias = true
|
||||||
pickerViewController.tabIdentifiers = ["keyboard"]
|
pickerViewController.tabIdentifiers = ["keyboard"]
|
||||||
pickerViewController.initialTabIdentifier = "keyboard"
|
pickerViewController.initialTabIdentifier = "keyboard"
|
||||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
pickerViewController.presentOverFullScreen(from: self)
|
||||||
nav.modalPresentationStyle = .overFullScreen
|
|
||||||
self.present(nav, animated: true)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|||||||
@@ -399,6 +399,14 @@ struct AbstractGamepadView: View {
|
|||||||
|
|
||||||
private func toggle(_ target: GamepadToggleTarget) {
|
private func toggle(_ target: GamepadToggleTarget) {
|
||||||
if activeButtons.contains(target) {
|
if activeButtons.contains(target) {
|
||||||
|
if target.widgets.count == 1, let widget = target.widgets.first {
|
||||||
|
if canSelectCommand?(widget.cmd) == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
AbstractGamepadView.selectedCmd = widget.cmd
|
||||||
|
onCommandSelected?(widget.cmd)
|
||||||
|
return
|
||||||
|
}
|
||||||
activeButtons.remove(target)
|
activeButtons.remove(target)
|
||||||
for widget in target.widgets {
|
for widget in target.widgets {
|
||||||
onCommandDeselected?(widget.cmd)
|
onCommandDeselected?(widget.cmd)
|
||||||
|
|||||||
@@ -368,6 +368,21 @@ struct VirtualKeyboardView: View {
|
|||||||
let keyID = regularHighlightID(for: key)
|
let keyID = regularHighlightID(for: key)
|
||||||
|
|
||||||
if highlightedKeyIDs.contains(keyID) {
|
if highlightedKeyIDs.contains(keyID) {
|
||||||
|
if mode != .shortcutPicker {
|
||||||
|
let cmd = key.cmdString(for: keyboardType) ?? ""
|
||||||
|
guard !cmd.isEmpty else { return }
|
||||||
|
if canSelectCommand?(cmd) == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
VirtualKeyboardView.tappedKeyLabels = [key.label]
|
||||||
|
VirtualKeyboardView.selectedCmd = cmd
|
||||||
|
VirtualKeyboardView.lastSelectionDisplayText = poolDisplayText(for: key)
|
||||||
|
VirtualKeyboardView.lastSelectionUsesMacLayout = keyboardType == .mac
|
||||||
|
VirtualKeyboardView.lastSelectionFromMouseWidgets = isMouseWidgetKey(key)
|
||||||
|
VirtualKeyboardView.lastSelectionUsesFnCommandDisplay = usesFnCommandDisplay(for: key)
|
||||||
|
onCommandSelected?(cmd)
|
||||||
|
return
|
||||||
|
}
|
||||||
highlightedKeyIDs.remove(keyID)
|
highlightedKeyIDs.remove(keyID)
|
||||||
if let cmd = key.cmdString(for: keyboardType), !cmd.isEmpty {
|
if let cmd = key.cmdString(for: keyboardType), !cmd.isEmpty {
|
||||||
onCommandDeselected?(cmd)
|
onCommandDeselected?(cmd)
|
||||||
@@ -406,6 +421,20 @@ struct VirtualKeyboardView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if directionSingleKeyLabels.contains(key.label) {
|
if directionSingleKeyLabels.contains(key.label) {
|
||||||
|
if mode != .shortcutPicker {
|
||||||
|
let command = key.cmdString(for: keyboardType) ?? key.label
|
||||||
|
if canSelectCommand?(command) == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
VirtualKeyboardView.tappedKeyLabels = [key.label]
|
||||||
|
VirtualKeyboardView.selectedCmd = command
|
||||||
|
VirtualKeyboardView.lastSelectionDisplayText = poolDisplayText(for: key)
|
||||||
|
VirtualKeyboardView.lastSelectionUsesMacLayout = keyboardType == .mac
|
||||||
|
VirtualKeyboardView.lastSelectionFromMouseWidgets = false
|
||||||
|
VirtualKeyboardView.lastSelectionUsesFnCommandDisplay = false
|
||||||
|
onCommandSelected?(command)
|
||||||
|
return
|
||||||
|
}
|
||||||
directionSingleKeyLabels.remove(key.label)
|
directionSingleKeyLabels.remove(key.label)
|
||||||
if let cmd = key.cmdString(for: keyboardType), !cmd.isEmpty {
|
if let cmd = key.cmdString(for: keyboardType), !cmd.isEmpty {
|
||||||
onCommandDeselected?(cmd)
|
onCommandDeselected?(cmd)
|
||||||
|
|||||||
+1350
-179
File diff suppressed because it is too large.
Load diff
@@ -74,8 +74,12 @@ public final class WidgetPickerViewController: UIViewController {
|
|||||||
view.addSubview(hostingViewController.view)
|
view.addSubview(hostingViewController.view)
|
||||||
hostingViewController.didMove(toParent: self)
|
hostingViewController.didMove(toParent: self)
|
||||||
|
|
||||||
|
let hostingTopAnchor = UIDevice.current.userInterfaceIdiom == .phone
|
||||||
|
? view.safeAreaLayoutGuide.topAnchor
|
||||||
|
: view.topAnchor
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
hostingViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
|
hostingViewController.view.topAnchor.constraint(equalTo: hostingTopAnchor),
|
||||||
hostingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
hostingViewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
hostingViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
hostingViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
hostingViewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
hostingViewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
@@ -89,11 +93,31 @@ public final class WidgetPickerViewController: UIViewController {
|
|||||||
navigationController?.setNavigationBarHidden(true, animated: false)
|
navigationController?.setNavigationBarHidden(true, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
presentationState.hasHostAppeared = false
|
||||||
|
}
|
||||||
|
|
||||||
public override func viewDidAppear(_ animated: Bool) {
|
public override func viewDidAppear(_ animated: Bool) {
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
presentationState.hasHostAppeared = true
|
presentationState.hasHostAppeared = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||||
|
super.viewWillTransition(to: size, with: coordinator)
|
||||||
|
|
||||||
|
presentationState.hasHostAppeared = false
|
||||||
|
|
||||||
|
coordinator.animate(alongsideTransition: nil) { [weak self] context in
|
||||||
|
guard let self else { return }
|
||||||
|
guard !context.isCancelled else {
|
||||||
|
self.presentationState.hasHostAppeared = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.presentationState.hasHostAppeared = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func resolvedTabs() -> [WidgetPickerTab] {
|
private func resolvedTabs() -> [WidgetPickerTab] {
|
||||||
let tabs = tabIdentifiers.compactMap(WidgetPickerTab.init(identifier:))
|
let tabs = tabIdentifiers.compactMap(WidgetPickerTab.init(identifier:))
|
||||||
return tabs.isEmpty ? WidgetPickerTab.allCases : tabs
|
return tabs.isEmpty ? WidgetPickerTab.allCases : tabs
|
||||||
@@ -104,6 +128,11 @@ public final class WidgetPickerViewController: UIViewController {
|
|||||||
return WidgetPickerTab(identifier: initialTabIdentifier)
|
return WidgetPickerTab(identifier: initialTabIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func presentOverFullScreen(from presenter: UIViewController, animated: Bool = true) {
|
||||||
|
modalPresentationStyle = .overFullScreen
|
||||||
|
presenter.present(self, animated: animated)
|
||||||
|
}
|
||||||
|
|
||||||
public func presentAsOverlay(in parentViewController: UIViewController, animated: Bool = true) {
|
public func presentAsOverlay(in parentViewController: UIViewController, animated: Bool = true) {
|
||||||
guard parent == nil else { return }
|
guard parent == nil else { return }
|
||||||
guard let originalAppWindow = parentViewController.view.window,
|
guard let originalAppWindow = parentViewController.view.window,
|
||||||
|
|||||||
Reference in new issue
Block a user