controller navigation improvements and fixes
This commit is contained in:
1 parent
ef5d839f5e
commit
b0c16922a2
12 files changed
+609
-143
No files matched your search
@@ -19,7 +19,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
private struct Hint {
|
private struct Hint {
|
||||||
let control: ControllerElement
|
let control: ControllerElement
|
||||||
let keyContent: KeyContent
|
let keyContent: KeyContent
|
||||||
let title: String
|
let titles: [String]
|
||||||
let isInAction: Bool
|
let isInAction: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,10 +39,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
private static let hudScale: CGFloat = PublicUtils.isIPhone ? 0.74 : 1
|
private static let hudScale: CGFloat = PublicUtils.isIPhone ? 0.74 : 1
|
||||||
private static let hudWidth: CGFloat = 235
|
private static let hudWidth: CGFloat = 235
|
||||||
private static let edgeMargin: CGFloat = PublicUtils.isIPhone ? 5 : 24
|
private static let edgeMargin: CGFloat = PublicUtils.isIPhone ? 5 : 24
|
||||||
private var hints: [Hint] = [
|
private var hints: [Hint] = []
|
||||||
// Hint(control: .leftStick, keyContent: .text("L"), title: "浏览", isInAction: false),
|
|
||||||
// Hint(control: .a, keyContent: .text("A"), title: "选择", isInAction: false)
|
|
||||||
]
|
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
@@ -83,10 +80,10 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
currentHud = hud
|
currentHud = hud
|
||||||
hud.attach(to: window)
|
hud.attach(to: window)
|
||||||
|
|
||||||
if let mainFrameVC = ControllerNavigator.radialMenuDelegate as? MainFrameViewController {
|
if let mainFrameVC = ControllerNavigator.radialMenuDelegate as? MainFrameViewController, ControllerNavigator.radialMenuView == nil {
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+3) {
|
DispatchQueue.main.asyncAfter(deadline: .now()+3) {
|
||||||
let streamFrameVC = StreamFrameViewController.sharedInstance()
|
let streamFrameVC = StreamFrameViewController.sharedInstance()
|
||||||
if ControllerNavigator.radialMenuView == nil, mainFrameVC.isStreaming(), !mainFrameVC.settingsExpandedInStreamView, streamFrameVC?.hasNoPresentedVC == true {
|
if ControllerNavigator.radialMenuView == nil, mainFrameVC.isStreaming(), !mainFrameVC.settingsExpandedInStreamView, streamFrameVC?.hasNoPresentedVC == true, !ControllerNavigator.controllerMouseEnabled {
|
||||||
requestHudDetachKeepingMinimumActionDuration()
|
requestHudDetachKeepingMinimumActionDuration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +168,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
guard hints.indices.contains(index),
|
guard hints.indices.contains(index),
|
||||||
let rowStack = row as? UIStackView,
|
let rowStack = row as? UIStackView,
|
||||||
let keyView = rowStack.arrangedSubviews.first,
|
let keyView = rowStack.arrangedSubviews.first,
|
||||||
let titleLabel = rowStack.arrangedSubviews.last as? UILabel else {
|
let titleView = rowStack.arrangedSubviews.last else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +189,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
imageView.tintColor = isInAction ? ThemeManager.appPrimaryColor.withAlphaComponent(isDark ? 1 : 1) : ThemeManager.appPrimaryColor.withAlphaComponent(isDark ? 0.83 : 0.83)
|
imageView.tintColor = isInAction ? ThemeManager.appPrimaryColor.withAlphaComponent(isDark ? 1 : 1) : ThemeManager.appPrimaryColor.withAlphaComponent(isDark ? 0.83 : 0.83)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
titleLabel.textColor = ThemeManager.textColor.withAlphaComponent(isDark ? 0.69 : 0.6)
|
updateTitleColors(in: titleView, color: ThemeManager.textColor.withAlphaComponent(isDark ? 0.69 : 0.6))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +220,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateHints(with elements: [ControllerNavigationElement]) {
|
private func updateHints(with elements: [ControllerNavigationElement]) {
|
||||||
let nextHints = elements.compactMap { hint(for: $0) }
|
let nextHints = hints(for: elements)
|
||||||
hints = nextHints.isEmpty ? [] : nextHints
|
hints = nextHints.isEmpty ? [] : nextHints
|
||||||
guard !hints.isEmpty else {return}
|
guard !hints.isEmpty else {return}
|
||||||
reloadHintRows()
|
reloadHintRows()
|
||||||
@@ -236,7 +233,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
Hint(
|
Hint(
|
||||||
control: hint.control,
|
control: hint.control,
|
||||||
keyContent: hint.keyContent,
|
keyContent: hint.keyContent,
|
||||||
title: hint.title,
|
titles: hint.titles,
|
||||||
isInAction: Self.isControlActive(hint.control)
|
isInAction: Self.isControlActive(hint.control)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -252,12 +249,35 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
hints.forEach { contentStackView.addArrangedSubview(makeRow(for: $0)) }
|
hints.forEach { contentStackView.addArrangedSubview(makeRow(for: $0)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private func hint(for navigationElement: ControllerNavigationElement) -> Hint? {
|
private func hints(for navigationElements: [ControllerNavigationElement]) -> [Hint] {
|
||||||
|
var groupedElements: [ControllerElement: [ControllerNavigationElement]] = [:]
|
||||||
|
var orderedControls: [ControllerElement] = []
|
||||||
|
|
||||||
|
for navigationElement in navigationElements {
|
||||||
|
if groupedElements[navigationElement.control] == nil {
|
||||||
|
orderedControls.append(navigationElement.control)
|
||||||
|
groupedElements[navigationElement.control] = []
|
||||||
|
}
|
||||||
|
groupedElements[navigationElement.control]?.append(navigationElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedControls.flatMap { control -> [Hint] in
|
||||||
|
guard let elements = groupedElements[control] else { return [] }
|
||||||
|
if elements.count == 2 {
|
||||||
|
return [hint(for: elements)]
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements.map { hint(for: [$0]) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func hint(for navigationElements: [ControllerNavigationElement]) -> Hint {
|
||||||
|
let control = navigationElements.first?.control ?? .null
|
||||||
return Hint(
|
return Hint(
|
||||||
control: navigationElement.control,
|
control: control,
|
||||||
keyContent: keyContent(for: navigationElement.control),
|
keyContent: keyContent(for: control),
|
||||||
title: navigationElement.action.localized,
|
titles: navigationElements.map { $0.action.localized },
|
||||||
isInAction: navigationElement.isInAction || Self.isControlActive(navigationElement.control)
|
isInAction: navigationElements.contains(where: { $0.isInAction }) || Self.isControlActive(control)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,22 +329,48 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
|
|
||||||
private func makeRow(for hint: Hint) -> UIStackView {
|
private func makeRow(for hint: Hint) -> UIStackView {
|
||||||
let keyView = makeKeyView(for: hint.keyContent)
|
let keyView = makeKeyView(for: hint.keyContent)
|
||||||
|
let titleView = makeTitleView(for: hint.titles)
|
||||||
|
|
||||||
let titleLabel = UILabel()
|
let rowStackView = UIStackView(arrangedSubviews: [keyView, titleView])
|
||||||
titleLabel.text = hint.title
|
|
||||||
titleLabel.font = UIFont.roundedSystemFont(ofSize: 14, weight: .medium)
|
|
||||||
titleLabel.adjustsFontSizeToFitWidth = true
|
|
||||||
titleLabel.minimumScaleFactor = 0.2
|
|
||||||
titleLabel.numberOfLines = 1
|
|
||||||
titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
|
|
||||||
|
|
||||||
let rowStackView = UIStackView(arrangedSubviews: [keyView, titleLabel])
|
|
||||||
rowStackView.axis = .horizontal
|
rowStackView.axis = .horizontal
|
||||||
rowStackView.alignment = .center
|
rowStackView.alignment = .center
|
||||||
rowStackView.spacing = 8
|
rowStackView.spacing = 8
|
||||||
return rowStackView
|
return rowStackView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func makeTitleView(for titles: [String]) -> UIView {
|
||||||
|
if titles.count == 2 {
|
||||||
|
let stackView = UIStackView(arrangedSubviews: titles.map { makeTitleLabel(text: $0, isMergedTitle: true) })
|
||||||
|
stackView.axis = .vertical
|
||||||
|
stackView.alignment = .leading
|
||||||
|
stackView.spacing = 1
|
||||||
|
stackView.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||||
|
return stackView
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeTitleLabel(text: titles.first ?? "", isMergedTitle: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeTitleLabel(text: String, isMergedTitle: Bool) -> UILabel {
|
||||||
|
let titleLabel = UILabel()
|
||||||
|
titleLabel.text = text
|
||||||
|
titleLabel.font = UIFont.roundedSystemFont(ofSize: isMergedTitle ? 12.5 : 14, weight: .medium)
|
||||||
|
titleLabel.adjustsFontSizeToFitWidth = true
|
||||||
|
titleLabel.minimumScaleFactor = isMergedTitle ? 0.55 : 0.2
|
||||||
|
titleLabel.numberOfLines = 1
|
||||||
|
titleLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||||
|
return titleLabel
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateTitleColors(in view: UIView, color: UIColor) {
|
||||||
|
if let label = view as? UILabel {
|
||||||
|
label.textColor = color
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
view.subviews.forEach { updateTitleColors(in: $0, color: color) }
|
||||||
|
}
|
||||||
|
|
||||||
private func makeKeyView(for content: KeyContent) -> UIView {
|
private func makeKeyView(for content: KeyContent) -> UIView {
|
||||||
let keyContainerView = UIView()
|
let keyContainerView = UIView()
|
||||||
keyContainerView.translatesAutoresizingMaskIntoConstraints = false
|
keyContainerView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@@ -423,7 +469,7 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static func isControlActive(_ control: ControllerElement) -> Bool {
|
private static func isControlActive(_ control: ControllerElement) -> Bool {
|
||||||
!relatedControls(for: control).isDisjoint(with: activeControls)
|
!activeControls(forHintControl: control).isDisjoint(with: activeControls)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func requestActionStateEnd(for control: ControllerElement) {
|
private static func requestActionStateEnd(for control: ControllerElement) {
|
||||||
@@ -486,12 +532,16 @@ final class GamepadNavigationIllustrationHud: UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func relatedControls(for control: ControllerElement) -> Set<ControllerElement> {
|
private static func activeControls(forHintControl control: ControllerElement) -> Set<ControllerElement> {
|
||||||
switch control {
|
switch control {
|
||||||
case .leftStick, .leftStickX, .leftStickY:
|
case .leftStick, .leftStickX, .leftStickY:
|
||||||
return [.leftStick, .leftStickX, .leftStickY]
|
return [.leftStick, .leftStickX, .leftStickY]
|
||||||
case .rightStick, .rightStickX, .rightStickY:
|
case .rightStick, .rightStickX, .rightStickY:
|
||||||
return [.rightStick, .rightStickX, .rightStickY]
|
return [.rightStick, .rightStickX, .rightStickY]
|
||||||
|
case .dpad:
|
||||||
|
return [.dpad, .dpadUp, .dpadDown, .dpadLeft, .dpadRight]
|
||||||
|
case .abxy:
|
||||||
|
return [.abxy, .a, .b, .x, .y]
|
||||||
default:
|
default:
|
||||||
return [control]
|
return [control]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,14 @@ final class ControllerNavigationElement: NSObject {
|
|||||||
private var controllerNavigationSelectedIndexPathKey: UInt8 = 0
|
private var controllerNavigationSelectedIndexPathKey: UInt8 = 0
|
||||||
private var controllerNavigationPersistTokenKey: UInt8 = 0
|
private var controllerNavigationPersistTokenKey: UInt8 = 0
|
||||||
private var controllerNavigationHighlightGenerationKey: UInt8 = 0
|
private var controllerNavigationHighlightGenerationKey: UInt8 = 0
|
||||||
|
private var controllerMouseCurvePreviewViewKey: UInt8 = 0
|
||||||
|
private var controllerMouseCurvePreviewDismissWorkItemKey: UInt8 = 0
|
||||||
private let settingsControllerNavigationHighlightedIdentifierKey = "SettingsControllerNavigationHighlightedIdentifier"
|
private let settingsControllerNavigationHighlightedIdentifierKey = "SettingsControllerNavigationHighlightedIdentifier"
|
||||||
private let hostControllerNavigationHighlightedUUIDKey = "HostControllerNavigationHighlightedUUID"
|
private let hostControllerNavigationHighlightedUUIDKey = "HostControllerNavigationHighlightedUUID"
|
||||||
|
private let settingsExcludedControllerNavigationSectionIdentifiers: Set<String> = [
|
||||||
|
"SettingsSectionTouch&Controller",
|
||||||
|
"SettingsSectionPencil"
|
||||||
|
]
|
||||||
|
|
||||||
@available(iOS 13.0, *)
|
@available(iOS 13.0, *)
|
||||||
private final class ControllerMouseDisplayLinkTarget: NSObject {
|
private final class ControllerMouseDisplayLinkTarget: NSObject {
|
||||||
@@ -34,6 +40,125 @@ private final class ControllerMouseDisplayLinkTarget: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 13.0, *)
|
||||||
|
private final class ControllerMouseCurvePreviewView: UIView {
|
||||||
|
var expo: CGFloat = 1.0 {
|
||||||
|
didSet {
|
||||||
|
setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
commonInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
commonInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func commonInit() {
|
||||||
|
isOpaque = false
|
||||||
|
layer.cornerRadius = 14
|
||||||
|
layer.cornerCurve = .continuous
|
||||||
|
layer.masksToBounds = true
|
||||||
|
layer.borderWidth = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override func draw(_ rect: CGRect) {
|
||||||
|
let isDark = ThemeManager.userInterfaceStyle() == .dark
|
||||||
|
let backgroundColor = isDark
|
||||||
|
? UIColor(white: 0.08, alpha: 0.88)
|
||||||
|
: UIColor.white.withAlphaComponent(0.92)
|
||||||
|
let axisColor = ThemeManager.textColor.withAlphaComponent(isDark ? 0.62 : 0.48)
|
||||||
|
let textColor = ThemeManager.textColor.withAlphaComponent(isDark ? 0.78 : 0.68)
|
||||||
|
let curveColor = ThemeManager.appPrimaryColor
|
||||||
|
layer.borderColor = ThemeManager.appPrimaryColor.withAlphaComponent(isDark ? 0.32 : 0.22).cgColor
|
||||||
|
|
||||||
|
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||||
|
context.setFillColor(backgroundColor.cgColor)
|
||||||
|
context.fill(bounds)
|
||||||
|
|
||||||
|
let footerHeight: CGFloat = 22
|
||||||
|
let xLabelHeight: CGFloat = 24
|
||||||
|
let plotHorizontalMargin: CGFloat = 34
|
||||||
|
let chartRect = bounds.inset(by: UIEdgeInsets(top: 18, left: 0, bottom: footerHeight + xLabelHeight, right: 0))
|
||||||
|
let plotSide = min(bounds.width - plotHorizontalMargin * 2, chartRect.height)
|
||||||
|
let plotRect = CGRect(
|
||||||
|
x: bounds.midX - plotSide / 2,
|
||||||
|
y: chartRect.midY - plotSide / 2,
|
||||||
|
width: plotSide,
|
||||||
|
height: plotSide
|
||||||
|
)
|
||||||
|
guard plotRect.width > 1, plotRect.height > 1 else { return }
|
||||||
|
|
||||||
|
let textAttributes: [NSAttributedString.Key: Any] = [
|
||||||
|
.font: UIFont.roundedSystemFont(ofSize: 11, weight: .medium),
|
||||||
|
.foregroundColor: textColor
|
||||||
|
]
|
||||||
|
|
||||||
|
("Cursor Speed".localized as NSString).draw(at: CGPoint(x: plotRect.minX + 8, y: plotRect.minY + 8), withAttributes: textAttributes)
|
||||||
|
let xAxisTitle = "Stick Offset".localized as NSString
|
||||||
|
let xAxisTitleSize = xAxisTitle.size(withAttributes: textAttributes)
|
||||||
|
xAxisTitle.draw(at: CGPoint(x: plotRect.midX - xAxisTitleSize.width / 2, y: plotRect.maxY + 10), withAttributes: textAttributes)
|
||||||
|
|
||||||
|
context.setStrokeColor(axisColor.cgColor)
|
||||||
|
context.setLineWidth(1)
|
||||||
|
context.move(to: CGPoint(x: plotRect.minX, y: plotRect.minY))
|
||||||
|
context.addLine(to: CGPoint(x: plotRect.minX, y: plotRect.maxY))
|
||||||
|
context.addLine(to: CGPoint(x: plotRect.maxX, y: plotRect.maxY))
|
||||||
|
context.strokePath()
|
||||||
|
|
||||||
|
("0" as NSString).draw(at: CGPoint(x: plotRect.minX - 10, y: plotRect.maxY - 8), withAttributes: textAttributes)
|
||||||
|
("1" as NSString).draw(at: CGPoint(x: plotRect.minX - 10, y: plotRect.minY - 7), withAttributes: textAttributes)
|
||||||
|
("1" as NSString).draw(at: CGPoint(x: plotRect.maxX - 4, y: plotRect.maxY + 10), withAttributes: textAttributes)
|
||||||
|
|
||||||
|
let guidePath = UIBezierPath()
|
||||||
|
guidePath.move(to: CGPoint(x: plotRect.minX, y: plotRect.maxY))
|
||||||
|
guidePath.addLine(to: CGPoint(x: plotRect.maxX, y: plotRect.minY))
|
||||||
|
context.saveGState()
|
||||||
|
context.setLineDash(phase: 0, lengths: [4, 4])
|
||||||
|
axisColor.withAlphaComponent(0.35).setStroke()
|
||||||
|
guidePath.lineWidth = 1
|
||||||
|
guidePath.stroke()
|
||||||
|
context.restoreGState()
|
||||||
|
|
||||||
|
let curvePath = UIBezierPath()
|
||||||
|
for step in 0...120 {
|
||||||
|
let normalizedX = CGFloat(step) / 120
|
||||||
|
let speed = abs(PublicUtils.controllerMouseExpoMappedOffset(normalizedX, expo: expo))
|
||||||
|
let point = CGPoint(
|
||||||
|
x: plotRect.minX + normalizedX * plotRect.width,
|
||||||
|
y: plotRect.maxY - min(max(speed, 0), 1) * plotRect.height
|
||||||
|
)
|
||||||
|
if step == 0 {
|
||||||
|
curvePath.move(to: point)
|
||||||
|
} else {
|
||||||
|
curvePath.addLine(to: point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curveColor.setStroke()
|
||||||
|
curvePath.lineWidth = 3
|
||||||
|
curvePath.lineCapStyle = .round
|
||||||
|
curvePath.lineJoinStyle = .round
|
||||||
|
curvePath.stroke()
|
||||||
|
|
||||||
|
let footerParagraphStyle = NSMutableParagraphStyle()
|
||||||
|
footerParagraphStyle.alignment = .center
|
||||||
|
let footerAttributes: [NSAttributedString.Key: Any] = [
|
||||||
|
.font: UIFont.roundedSystemFont(ofSize: 10, weight: .medium),
|
||||||
|
.foregroundColor: textColor.withAlphaComponent(0.76),
|
||||||
|
.paragraphStyle: footerParagraphStyle
|
||||||
|
]
|
||||||
|
("Inspired by RC hobby transmitters".localized as NSString).draw(
|
||||||
|
in: CGRect(x: 12, y: bounds.maxY - footerHeight + 1, width: bounds.width - 24, height: footerHeight - 2),
|
||||||
|
withAttributes: footerAttributes
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@available(iOS 13.0, *)
|
@available(iOS 13.0, *)
|
||||||
@objc protocol ControllerNavigatorRadialMenuDelegate: AnyObject {
|
@objc protocol ControllerNavigatorRadialMenuDelegate: AnyObject {
|
||||||
func controllerNavigatorDidSelect(item: RadialMenuItem)
|
func controllerNavigatorDidSelect(item: RadialMenuItem)
|
||||||
@@ -508,11 +633,11 @@ final class ControllerNavigator: NSObject {
|
|||||||
}
|
}
|
||||||
case .exit:
|
case .exit:
|
||||||
exit(0)
|
exit(0)
|
||||||
case .shortcuts:
|
case .toolbox:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
radialMenuView?.dismiss()
|
radialMenuView?.dismiss()
|
||||||
radialMenuView = nil
|
radialMenuView = nil
|
||||||
StreamFrameViewController.sharedInstance().bringUpToolboxMenu()
|
StreamFrameViewController.sharedInstance().bringUpToolboxMenuWithoutWidgetLayoutTool()
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@@ -544,7 +669,7 @@ final class ControllerNavigator: NSObject {
|
|||||||
if radialMenuState == .moreOptions {
|
if radialMenuState == .moreOptions {
|
||||||
if mainFrameVC.isStreaming() {
|
if mainFrameVC.isStreaming() {
|
||||||
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "Game Profiles".localized, subtitle: "", symbol:PublicUtils.iOS18Available ? "gamecontroller.circle" : "gamecontroller.fill", item: .gameProfiles))
|
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "Game Profiles".localized, subtitle: "", symbol:PublicUtils.iOS18Available ? "gamecontroller.circle" : "gamecontroller.fill", item: .gameProfiles))
|
||||||
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "=shortcuts".localized, subtitle: "", symbol: "apple.terminal", item: .shortcuts))
|
RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "=toolbox".localized, subtitle: "", symbol: "apple.terminal", item: .toolbox))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if !mainFrameVC.isInAppView(), !mainFrameVC.settingsViewExpanded {RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "About".localized, subtitle: "", symbol: "questionmark.circle", item: .aboutView))}
|
if !mainFrameVC.isInAppView(), !mainFrameVC.settingsViewExpanded {RadialMenuOverlayView.menuSectors.append(RadialMenuSector(title: "About".localized, subtitle: "", symbol: "questionmark.circle", item: .aboutView))}
|
||||||
@@ -655,6 +780,94 @@ final class ControllerNavigator: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static func listenToNavigationCluster() {
|
||||||
|
guard let mainFrameVC = radialMenuDelegate as? MainFrameViewController else {return}
|
||||||
|
|
||||||
|
let upNavButton: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .dpadUp : .y
|
||||||
|
let downNavButton: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .dpadDown : .a
|
||||||
|
let leftNavButton: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .dpadLeft : .x
|
||||||
|
let rightNavButton: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .dpadRight : .b
|
||||||
|
|
||||||
|
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is ToolboxViewController || uiNavigationDelegate is ProfileSelectorViewController {
|
||||||
|
let verticalNavigationAxis: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .leftStickY : .rightStickY
|
||||||
|
ControllerUtil.listenPrimaryControllerStickAxis(verticalNavigationAxis, threshold: 0.6) {state in
|
||||||
|
GamepadNavigationIllustrationHud.updateActionState(for: verticalNavigationAxis, isInAction: state != .orderedSame)
|
||||||
|
guard radialMenuView == nil else {return}
|
||||||
|
switch state {
|
||||||
|
case .orderedAscending:
|
||||||
|
if navigationTimer?.isRunning() != true {
|
||||||
|
if uiNavigationDelegate is SettingsViewController {
|
||||||
|
navigateContinuously(downward: true)
|
||||||
|
}
|
||||||
|
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
|
||||||
|
navigateContinuously(downward: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .orderedDescending:
|
||||||
|
if navigationTimer?.isRunning() != true {
|
||||||
|
if uiNavigationDelegate is SettingsViewController {
|
||||||
|
navigateContinuously(downward: false)
|
||||||
|
}
|
||||||
|
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
|
||||||
|
navigateContinuously(downward: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .orderedSame:
|
||||||
|
navigationTimer?.clean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControllerUtil.listenPrimaryControllerButton(upNavButton) {pressed in
|
||||||
|
GamepadNavigationIllustrationHud.updateActionState(for: upNavButton, isInAction: pressed)
|
||||||
|
if pressed {
|
||||||
|
uiNavigationDelegate.navigateByController(downward: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControllerUtil.listenPrimaryControllerButton(downNavButton) {pressed in
|
||||||
|
GamepadNavigationIllustrationHud.updateActionState(for: downNavButton, isInAction: pressed)
|
||||||
|
if pressed {
|
||||||
|
uiNavigationDelegate.navigateByController(downward: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || uiNavigationDelegate is ToolboxViewController || uiNavigationDelegate is ProfileSelectorViewController {
|
||||||
|
let horizontalNavigationAxis: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .leftStickX : .rightStickX
|
||||||
|
ControllerUtil.listenPrimaryControllerStickAxis(horizontalNavigationAxis, threshold: 0.6) {state in
|
||||||
|
GamepadNavigationIllustrationHud.updateActionState(for: horizontalNavigationAxis, isInAction: state != .orderedSame)
|
||||||
|
guard radialMenuView == nil else {return}
|
||||||
|
switch state {
|
||||||
|
case .orderedAscending:
|
||||||
|
if navigationTimer?.isRunning() != true {
|
||||||
|
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
|
||||||
|
navigateContinuously(forward: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .orderedDescending:
|
||||||
|
if navigationTimer?.isRunning() != true {
|
||||||
|
if uiNavigationDelegate is ControllerCollectionNavigationDelegate {
|
||||||
|
navigateContinuously(forward: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .orderedSame:
|
||||||
|
navigationTimer?.clean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControllerUtil.listenPrimaryControllerButton(leftNavButton) {pressed in
|
||||||
|
GamepadNavigationIllustrationHud.updateActionState(for: leftNavButton, isInAction: pressed)
|
||||||
|
if pressed {
|
||||||
|
uiNavigationDelegate.navigateByController(forward: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ControllerUtil.listenPrimaryControllerButton(rightNavButton) {pressed in
|
||||||
|
GamepadNavigationIllustrationHud.updateActionState(for: rightNavButton, isInAction: pressed)
|
||||||
|
if pressed {
|
||||||
|
uiNavigationDelegate.navigateByController(forward: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@objc static func listenToControllerMouse() {
|
@objc static func listenToControllerMouse() {
|
||||||
guard radialMenuState == .mouseModeEnabled else { return }
|
guard radialMenuState == .mouseModeEnabled else { return }
|
||||||
ControllerUtil.listenPrimaryControllerButton(controllerMouseLeftButton){ pressed in
|
ControllerUtil.listenPrimaryControllerButton(controllerMouseLeftButton){ pressed in
|
||||||
@@ -693,9 +906,9 @@ final class ControllerNavigator: NSObject {
|
|||||||
|
|
||||||
listenToRadialMenuButton()
|
listenToRadialMenuButton()
|
||||||
listenToRadialMenuStick()
|
listenToRadialMenuStick()
|
||||||
|
listenToNavigationCluster()
|
||||||
|
|
||||||
|
/*
|
||||||
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is ToolboxViewController || uiNavigationDelegate is ProfileSelectorViewController {
|
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is ToolboxViewController || uiNavigationDelegate is ProfileSelectorViewController {
|
||||||
let verticalNavigationAxis: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .leftStickY : .rightStickY
|
let verticalNavigationAxis: ControllerElement = ControllerNavigator.radialMenuButtonPosition == .right ? .leftStickY : .rightStickY
|
||||||
ControllerUtil.listenPrimaryControllerStickAxis(verticalNavigationAxis, threshold: 0.6) {state in
|
ControllerUtil.listenPrimaryControllerStickAxis(verticalNavigationAxis, threshold: 0.6) {state in
|
||||||
@@ -749,6 +962,7 @@ final class ControllerNavigator: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is UIAlertController || uiNavigationDelegate is ProfileSelectorViewController || uiNavigationDelegate is ToolboxViewController {
|
if let uiNavigationDelegate = uiNavigationDelegate, !mainFrameVC.isStreaming() || mainFrameVC.settingsExpandedInStreamView || uiNavigationDelegate is UIAlertController || uiNavigationDelegate is ProfileSelectorViewController || uiNavigationDelegate is ToolboxViewController {
|
||||||
let navigations = uiNavigationDelegate.getNavigationElements()
|
let navigations = uiNavigationDelegate.getNavigationElements()
|
||||||
@@ -792,6 +1006,13 @@ final class ControllerNavigator: NSObject {
|
|||||||
|
|
||||||
@available(iOS 13.0, *)
|
@available(iOS 13.0, *)
|
||||||
extension SettingsViewController: ControllerUINavigationDelegate {
|
extension SettingsViewController: ControllerUINavigationDelegate {
|
||||||
|
@objc(showControllerMouseCurvePreviewWithExpo:)
|
||||||
|
func showControllerMouseCurvePreview(expo: CGFloat) {
|
||||||
|
PublicUtils.runOnMain { [weak self] in
|
||||||
|
self?.showControllerMouseCurvePreviewOnMain(expo: expo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc func persistControllerNavigationHighlight() {
|
@objc func persistControllerNavigationHighlight() {
|
||||||
guard let highlightedView = ControllerNavigator.controllerNavigationHighlightedView,
|
guard let highlightedView = ControllerNavigator.controllerNavigationHighlightedView,
|
||||||
let identifier = controllerNavigationPersistenceIdentifier(for: highlightedView) else {
|
let identifier = controllerNavigationPersistenceIdentifier(for: highlightedView) else {
|
||||||
@@ -801,6 +1022,64 @@ extension SettingsViewController: ControllerUINavigationDelegate {
|
|||||||
UserDefaults.standard.set(identifier, forKey: settingsControllerNavigationHighlightedIdentifierKey)
|
UserDefaults.standard.set(identifier, forKey: settingsControllerNavigationHighlightedIdentifierKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var controllerMouseCurvePreviewView: ControllerMouseCurvePreviewView? {
|
||||||
|
get {
|
||||||
|
objc_getAssociatedObject(self, &controllerMouseCurvePreviewViewKey) as? ControllerMouseCurvePreviewView
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objc_setAssociatedObject(self, &controllerMouseCurvePreviewViewKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var controllerMouseCurvePreviewDismissWorkItem: DispatchWorkItem? {
|
||||||
|
get {
|
||||||
|
objc_getAssociatedObject(self, &controllerMouseCurvePreviewDismissWorkItemKey) as? DispatchWorkItem
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objc_setAssociatedObject(self, &controllerMouseCurvePreviewDismissWorkItemKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showControllerMouseCurvePreviewOnMain(expo: CGFloat) {
|
||||||
|
let previewView = controllerMouseCurvePreviewView ?? ControllerMouseCurvePreviewView()
|
||||||
|
controllerMouseCurvePreviewView = previewView
|
||||||
|
previewView.expo = expo
|
||||||
|
previewView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
|
if previewView.superview == nil {
|
||||||
|
previewView.alpha = 0
|
||||||
|
view.addSubview(previewView)
|
||||||
|
let preferredWidth = previewView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor, multiplier: 0.72)
|
||||||
|
preferredWidth.priority = .defaultHigh
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
previewView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
|
||||||
|
previewView.widthAnchor.constraint(lessThanOrEqualToConstant: 360),
|
||||||
|
preferredWidth,
|
||||||
|
previewView.heightAnchor.constraint(equalToConstant: 190),
|
||||||
|
previewView.bottomAnchor.constraint(equalTo: controllerMouseExpoStack.topAnchor, constant: -10)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
view.bringSubviewToFront(previewView)
|
||||||
|
UIView.animate(withDuration: 0.12) {
|
||||||
|
previewView.alpha = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
controllerMouseCurvePreviewDismissWorkItem?.cancel()
|
||||||
|
let workItem = DispatchWorkItem { [weak self, weak previewView] in
|
||||||
|
UIView.animate(withDuration: 0.18, animations: {
|
||||||
|
previewView?.alpha = 0
|
||||||
|
}, completion: { _ in
|
||||||
|
previewView?.removeFromSuperview()
|
||||||
|
if self?.controllerMouseCurvePreviewView === previewView {
|
||||||
|
self?.controllerMouseCurvePreviewView = nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
controllerMouseCurvePreviewDismissWorkItem = workItem
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: workItem)
|
||||||
|
}
|
||||||
|
|
||||||
@objc func restoreControllerNavigationHighlight() {
|
@objc func restoreControllerNavigationHighlight() {
|
||||||
guard ControllerNavigator.enabled, ControllerUtil.primaryGCController != nil else {return}
|
guard ControllerNavigator.enabled, ControllerUtil.primaryGCController != nil else {return}
|
||||||
PublicUtils.runOnMain { [weak self] in
|
PublicUtils.runOnMain { [weak self] in
|
||||||
@@ -853,23 +1132,25 @@ extension SettingsViewController: ControllerUINavigationDelegate {
|
|||||||
}
|
}
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButton, action: "radialMenu"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButton, action: "radialMenu"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStickY : .leftStickY, action: "menuNavigation"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStickY : .leftStickY, action: "menuNavigation"))
|
||||||
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .abxy : .dpad, action: "menuNavigation"))
|
||||||
|
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadLeft : .x, action: "widgetOperationBackward"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadLeft : .x, action: "widgetOperationBackward"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .b, action: "widgetOperationForward"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .b, action: "widgetOperationForward"))
|
||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
func navigateByController(forward:Bool) {
|
func navigateByController(downward:Bool) {
|
||||||
guard self.hasNoPresentedVC else {return}
|
guard self.hasNoPresentedVC else {return}
|
||||||
if currentSettingsMenuMode == .FavoriteSettings,
|
if currentSettingsMenuMode == .FavoriteSettings,
|
||||||
ControllerNavigator.settingsFavoriteReorderActive {
|
ControllerNavigator.settingsFavoriteReorderActive {
|
||||||
moveHighlightedFavoriteSettingStack(by: forward ? 1 : -1)
|
moveHighlightedFavoriteSettingStack(by: downward ? 1 : -1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
performControllerNavigationSelectionMove(by: forward ? 1 : -1)
|
performControllerNavigationSelectionMove(by: downward ? 1 : -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func navigateByController(downward:Bool) {
|
func navigateByController(forward:Bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func uiWidgetActionForControllerNavigator(forward: Bool, from navigation:ControllerNavigationElement) {
|
func uiWidgetActionForControllerNavigator(forward: Bool, from navigation:ControllerNavigationElement) {
|
||||||
@@ -1270,6 +1551,7 @@ extension SettingsViewController: ControllerUINavigationDelegate {
|
|||||||
targets.append(headerView)
|
targets.append(headerView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guard !shouldSkipControllerNavigationSection(sectionView) else { continue }
|
||||||
guard let rootStackView = sectionView.rootStackView else { continue }
|
guard let rootStackView = sectionView.rootStackView else { continue }
|
||||||
guard isControllerNavigationVisible(rootStackView, within: sectionView) else { continue }
|
guard isControllerNavigationVisible(rootStackView, within: sectionView) else { continue }
|
||||||
|
|
||||||
@@ -1282,6 +1564,14 @@ extension SettingsViewController: ControllerUINavigationDelegate {
|
|||||||
return targets
|
return targets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func shouldSkipControllerNavigationSection(_ sectionView: MenuSectionView) -> Bool {
|
||||||
|
guard let identifier = sectionView.identifier else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return settingsExcludedControllerNavigationSectionIdentifiers.contains(identifier)
|
||||||
|
}
|
||||||
|
|
||||||
private func favoriteSettingsControllerNavigationTargets(in parentStack: UIStackView, skippingDisabledStacks: Bool) -> [UIView] {
|
private func favoriteSettingsControllerNavigationTargets(in parentStack: UIStackView, skippingDisabledStacks: Bool) -> [UIView] {
|
||||||
var targets: [UIView] = []
|
var targets: [UIView] = []
|
||||||
for arrangedSubview in parentStack.arrangedSubviews {
|
for arrangedSubview in parentStack.arrangedSubviews {
|
||||||
@@ -1673,10 +1963,11 @@ extension ControllerCollectionNavigationDelegate {
|
|||||||
var elements: [ControllerNavigationElement] = []
|
var elements: [ControllerNavigationElement] = []
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButton, action: "radialMenu"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButton, action: "radialMenu"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
|
||||||
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .abxy : .dpad, action: "focusNavigation"))
|
||||||
if self is HostCollectionViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "applications"))}
|
if self is HostCollectionViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "applications"))}
|
||||||
if self is HostCollectionViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .x, action: "launchPairWake"))}
|
if self is HostCollectionViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .x, action: "launchPairWake"))}
|
||||||
if self is MainFrameViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "launch"))}
|
if self is MainFrameViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "launch"))}
|
||||||
if self is MainFrameViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .x, action: "quitApp"))}
|
if self is MainFrameViewController {elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .b, action: "quitApp"))}
|
||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2055,13 +2346,28 @@ extension UIAlertController: ControllerUINavigationDelegate {
|
|||||||
|
|
||||||
guard enabledActions.count > 1, let lastAction = enabledActions.last else {
|
guard enabledActions.count > 1, let lastAction = enabledActions.last else {
|
||||||
guard let title = firstAction.title, !title.isEmpty else { return [] }
|
guard let title = firstAction.title, !title.isEmpty else { return [] }
|
||||||
return [ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .x, action: title)]
|
return [ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: title)]
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
|
||||||
ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadLeft : .x, action: firstAction.title ?? ""),
|
|
||||||
ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .b, action: lastAction.title ?? "")
|
|
||||||
].filter { !$0.action.isEmpty }
|
var elements: [ControllerNavigationElement] = []
|
||||||
|
|
||||||
|
if ControllerNavigator.radialMenuButtonPosition == .left {
|
||||||
|
elements.append(ControllerNavigationElement(control: firstAction.style == .default ? .dpadRight : .dpadUp, action: firstAction.title ?? ""))
|
||||||
|
if firstAction.style != lastAction.style {
|
||||||
|
elements.append(ControllerNavigationElement(control: lastAction.style == .cancel ? .dpadUp : .dpadRight, action: lastAction.title ?? ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elements.append(ControllerNavigationElement(control: firstAction.style == .default ? .a : .b, action: firstAction.title ?? ""))
|
||||||
|
if firstAction.style != lastAction.style {
|
||||||
|
elements.append(ControllerNavigationElement(control: lastAction.style == .cancel ? .b : .a, action: lastAction.title ?? ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
func navigateByController(forward: Bool) {}
|
func navigateByController(forward: Bool) {}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import Foundation
|
|||||||
case stick
|
case stick
|
||||||
case stickAxis
|
case stickAxis
|
||||||
case touchpad
|
case touchpad
|
||||||
|
case cluster
|
||||||
case undefined
|
case undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +71,9 @@ import Foundation
|
|||||||
case rightStick = 0x800020
|
case rightStick = 0x800020
|
||||||
case rightStickX = 0x800021
|
case rightStickX = 0x800021
|
||||||
case rightStickY = 0x800022
|
case rightStickY = 0x800022
|
||||||
|
|
||||||
|
case dpad = 0x800013
|
||||||
|
case abxy = 0x800023
|
||||||
|
|
||||||
case null = 0xFFFFFF
|
case null = 0xFFFFFF
|
||||||
|
|
||||||
@@ -111,6 +115,9 @@ import Foundation
|
|||||||
case .rightStick: return "RStick".localized
|
case .rightStick: return "RStick".localized
|
||||||
case .rightStickX: return "RStickX".localized
|
case .rightStickX: return "RStickX".localized
|
||||||
case .rightStickY: return "RStickY".localized
|
case .rightStickY: return "RStickY".localized
|
||||||
|
|
||||||
|
case .dpad: return "DPad".localized
|
||||||
|
case .abxy: return "ABXY".localized
|
||||||
|
|
||||||
case .null: return "Null".localized
|
case .null: return "Null".localized
|
||||||
}
|
}
|
||||||
@@ -130,6 +137,9 @@ import Foundation
|
|||||||
case .dpadRight:
|
case .dpadRight:
|
||||||
if #available(iOS 15.0, *) {return "dpad.right.filled"}
|
if #available(iOS 15.0, *) {return "dpad.right.filled"}
|
||||||
else {return ""}
|
else {return ""}
|
||||||
|
case .dpad:
|
||||||
|
if #available(iOS 14.0, *) {return "dpad"}
|
||||||
|
else {return ""}
|
||||||
case .a:
|
case .a:
|
||||||
if #available(iOS 15.0, *) {return "circle.grid.cross.down.filled"}
|
if #available(iOS 15.0, *) {return "circle.grid.cross.down.filled"}
|
||||||
else {return ""}
|
else {return ""}
|
||||||
@@ -142,6 +152,10 @@ import Foundation
|
|||||||
case .y:
|
case .y:
|
||||||
if #available(iOS 15.0, *) {return "circle.grid.cross.up.filled"}
|
if #available(iOS 15.0, *) {return "circle.grid.cross.up.filled"}
|
||||||
else {return ""}
|
else {return ""}
|
||||||
|
case .abxy:
|
||||||
|
if #available(iOS 14.0, *) {return "circle.grid.cross"}
|
||||||
|
else {return ""}
|
||||||
|
|
||||||
default: return ""
|
default: return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,6 +198,9 @@ import Foundation
|
|||||||
case .rightStick: return .stick
|
case .rightStick: return .stick
|
||||||
case .rightStickX: return .stickAxis
|
case .rightStickX: return .stickAxis
|
||||||
case .rightStickY: return .stickAxis
|
case .rightStickY: return .stickAxis
|
||||||
|
|
||||||
|
case .dpad: return .cluster
|
||||||
|
case .abxy: return .cluster
|
||||||
|
|
||||||
case .null: return .undefined
|
case .null: return .undefined
|
||||||
}
|
}
|
||||||
@@ -227,6 +244,9 @@ import Foundation
|
|||||||
case .rightStick: return .right
|
case .rightStick: return .right
|
||||||
case .rightStickX: return .right
|
case .rightStickX: return .right
|
||||||
case .rightStickY: return .right
|
case .rightStickY: return .right
|
||||||
|
|
||||||
|
case .abxy: return .right
|
||||||
|
case .dpad: return .left
|
||||||
|
|
||||||
case .null: return .undefined
|
case .null: return .undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<attribute name="controllerMouseExpo" optional="YES" attributeType="Float" defaultValueString="1.6" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="controllerMouseExpo" optional="YES" attributeType="Float" defaultValueString="1.6" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="controllerMouseLeftButton" attributeType="Integer 32" defaultValueString="8" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="controllerMouseLeftButton" attributeType="Integer 32" defaultValueString="8" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="controllerMousePointerVelocity" optional="YES" attributeType="Float" defaultValueString="12" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="controllerMousePointerVelocity" optional="YES" attributeType="Float" defaultValueString="12" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="controllerMouseRightButton" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="controllerMouseRightButton" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="controllerMouseStick" attributeType="Integer 32" defaultValueString="8388640" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="controllerMouseStick" attributeType="Integer 32" defaultValueString="8388640" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="ctrlDownForPinch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
|
<attribute name="ctrlDownForPinch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
|
||||||
<attribute name="customLocalRadialMenuButtonPosition" attributeType="Integer 32" defaultValueString="16777215" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="customLocalRadialMenuButtonPosition" attributeType="Integer 32" defaultValueString="16777215" usesScalarValueType="NO" syncable="YES"/>
|
||||||
|
|||||||
@@ -4569,29 +4569,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"All Settings" : {
|
|
||||||
"extractionState" : "manual",
|
|
||||||
"localizations" : {
|
|
||||||
"zh-Hans" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "全部设置"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hant" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "所有設定"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-HK" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "所有設定"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"All Profiles" : {
|
"All Profiles" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -4615,6 +4592,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"All Settings" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "全部设置"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "所有設定"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "所有設定"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Alpha" : {
|
"Alpha" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -6390,6 +6390,52 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Current Profile" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "当前配置"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "目前設定檔"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "目前設定檔"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Cursor Speed" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "光标速度"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "游標速度"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "游標速度"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Custom Resolution Selected" : {
|
"Custom Resolution Selected" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -6534,29 +6580,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Current Profile" : {
|
|
||||||
"extractionState" : "manual",
|
|
||||||
"localizations" : {
|
|
||||||
"zh-Hans" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "当前配置"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hant" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "目前設定檔"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-HK" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "目前設定檔"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Del" : {
|
"Del" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -6632,29 +6655,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Duplicate" : {
|
|
||||||
"extractionState" : "manual",
|
|
||||||
"localizations" : {
|
|
||||||
"zh-Hans" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "复制"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hant" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "複製"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-HK" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "複製"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Delete Buttons Here" : {
|
"Delete Buttons Here" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -7496,6 +7496,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Duplicate" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "复制"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "複製"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "複製"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"e.g. ctrl, lswheel, wasdpad..." : {
|
"e.g. ctrl, lswheel, wasdpad..." : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -8211,29 +8234,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Export" : {
|
|
||||||
"extractionState" : "manual",
|
|
||||||
"localizations" : {
|
|
||||||
"zh-Hans" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "导出"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hant" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "匯出"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-HK" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "匯出"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Expands setting menu during streaming" : {
|
"Expands setting menu during streaming" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -8280,6 +8280,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Export" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "导出"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "匯出"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "匯出"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"externalDisplayModeStackDoc" : {
|
"externalDisplayModeStackDoc" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -10229,6 +10252,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Inspired by RC hobby transmitters" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "灵感来自航模遥控发射机"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "靈感來自航模遙控發射機"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "靈感來自航模遙控發射機"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Interval of Multi-Touch Move Events: %d μs" : {
|
"Interval of Multi-Touch Move Events: %d μs" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -16814,6 +16860,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Stick Offset" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "摇杆偏移量"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "搖桿偏移量"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "搖桿偏移量"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"stickWheelLink" : {
|
"stickWheelLink" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -18977,4 +19046,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version" : "1.1"
|
"version" : "1.1"
|
||||||
}
|
}
|
||||||
+3
-2
@@ -1201,9 +1201,10 @@ final class ProfileSelectorViewController: UIViewController, UICollectionViewDat
|
|||||||
func getNavigationElements() -> [ControllerNavigationElement] {
|
func getNavigationElements() -> [ControllerNavigationElement] {
|
||||||
var elements: [ControllerNavigationElement] = []
|
var elements: [ControllerNavigationElement] = []
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
|
||||||
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .abxy : .dpad, action: "focusNavigation"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "holdToReorder"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "holdToReorder"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "doublePressToDelete"))
|
// elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "doublePressToDelete"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "exit"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .b, action: "exit"))
|
||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
@class LayoutOnScreenControlsViewController;
|
@class LayoutOnScreenControlsViewController;
|
||||||
@class MainFrameViewController;
|
@class MainFrameViewController;
|
||||||
|
@class MenuSectionView;
|
||||||
@class MicHandler;
|
@class MicHandler;
|
||||||
@class WidgetPickerViewController;
|
@class WidgetPickerViewController;
|
||||||
|
|
||||||
@@ -105,6 +106,7 @@
|
|||||||
@property (weak, nonatomic) LayoutOnScreenControlsViewController *layoutOnScreenControlsVC;
|
@property (weak, nonatomic) LayoutOnScreenControlsViewController *layoutOnScreenControlsVC;
|
||||||
@property (nonatomic, weak) MainFrameViewController *mainFrameViewController;
|
@property (nonatomic, weak) MainFrameViewController *mainFrameViewController;
|
||||||
@property (strong, nonatomic) UIView *controllerNavigationHighlightOverlayView;
|
@property (strong, nonatomic) UIView *controllerNavigationHighlightOverlayView;
|
||||||
|
@property (nonatomic, strong, readonly) MenuSectionView *touchControlSection;
|
||||||
|
|
||||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *externalDisplayModeSelector;
|
@property (strong, nonatomic) IBOutlet UISegmentedControl *externalDisplayModeSelector;
|
||||||
@property (strong, nonatomic) IBOutlet UISegmentedControl *localMousePointerModeSelector;
|
@property (strong, nonatomic) IBOutlet UISegmentedControl *localMousePointerModeSelector;
|
||||||
|
|||||||
@@ -69,6 +69,10 @@
|
|||||||
@dynamic overrideUserInterfaceStyle;
|
@dynamic overrideUserInterfaceStyle;
|
||||||
@synthesize controllerNavigationHighlightOverlayView = _controllerNavigationHighlightOverlayView;
|
@synthesize controllerNavigationHighlightOverlayView = _controllerNavigationHighlightOverlayView;
|
||||||
|
|
||||||
|
- (MenuSectionView *)touchControlSection {
|
||||||
|
return touchControlSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//static NSString* bitrateFormat;
|
//static NSString* bitrateFormat;
|
||||||
static const int bitrateTable[] = {
|
static const int bitrateTable[] = {
|
||||||
@@ -1839,8 +1843,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[tipsAlertController setValue:attributedMessage forKey:@"attributedMessage"];
|
[tipsAlertController setValue:attributedMessage forKey:@"attributedMessage"];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UIAlertAction *readInstruction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Online Documentation"]
|
UIAlertAction *readInstruction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Learn More"]
|
||||||
style:UIAlertActionStyleDefault
|
style:UIAlertActionStyleCancel
|
||||||
handler:^(UIAlertAction *action){
|
handler:^(UIAlertAction *action){
|
||||||
[PublicUtils openUrl:onlineDocLink];
|
[PublicUtils openUrl:onlineDocLink];
|
||||||
}];
|
}];
|
||||||
@@ -2540,7 +2544,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"]
|
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"]
|
||||||
style:UIAlertActionStyleDefault
|
style:UIAlertActionStyleCancel
|
||||||
handler:nil];
|
handler:nil];
|
||||||
|
|
||||||
UIAlertAction *okAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"OK"]
|
UIAlertAction *okAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"OK"]
|
||||||
@@ -3342,6 +3346,9 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
|
|
||||||
- (void) controllerMouseExpoSliderMoved:(UISlider* )sender {
|
- (void) controllerMouseExpoSliderMoved:(UISlider* )sender {
|
||||||
[self findDynamicLabelFromStack:(UIStackView*)sender.superview].text = [NSString stringWithFormat:@" %.1f ", sender.value];
|
[self findDynamicLabelFromStack:(UIStackView*)sender.superview].text = [NSString stringWithFormat:@" %.1f ", sender.value];
|
||||||
|
if (@available(iOS 13.0, *)) if(!settingsViewJustLoaded) {
|
||||||
|
[self showControllerMouseCurvePreviewWithExpo:sender.value];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (uint32_t) getScreenEdgeFromSelector {
|
- (uint32_t) getScreenEdgeFromSelector {
|
||||||
|
|||||||
@@ -63,5 +63,6 @@
|
|||||||
- (void)resetMagnifierStreamViewWithAnimated:(BOOL)animated;
|
- (void)resetMagnifierStreamViewWithAnimated:(BOOL)animated;
|
||||||
- (void)returnToMainFrame;
|
- (void)returnToMainFrame;
|
||||||
- (void)bringUpToolboxMenu;
|
- (void)bringUpToolboxMenu;
|
||||||
|
- (void)bringUpToolboxMenuWithoutWidgetLayoutTool;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -307,11 +307,20 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)bringUpToolboxMenu{
|
- (void)bringUpToolboxMenu{
|
||||||
|
[self bringUpToolboxMenuWithoutWidgetLayoutTool:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)bringUpToolboxMenuWithoutWidgetLayoutTool{
|
||||||
|
[self bringUpToolboxMenuWithoutWidgetLayoutTool:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)bringUpToolboxMenuWithoutWidgetLayoutTool:(BOOL)hideWidgetLayoutTool{
|
||||||
[self prepareGameProfileSelector];
|
[self prepareGameProfileSelector];
|
||||||
ToolboxViewController* oldToolboxVC = toolBoxViewController;
|
ToolboxViewController* oldToolboxVC = toolBoxViewController;
|
||||||
toolBoxViewController = [[ToolboxViewController alloc] init];
|
toolBoxViewController = [[ToolboxViewController alloc] init];
|
||||||
toolBoxViewController.specialEntryDelegate = self;
|
toolBoxViewController.specialEntryDelegate = self;
|
||||||
toolBoxViewController.specialEntries = oldToolboxVC.specialEntries;
|
toolBoxViewController.specialEntries = [oldToolboxVC.specialEntries mutableCopy];
|
||||||
|
if(hideWidgetLayoutTool) [toolBoxViewController.specialEntries removeObject:@"widgetLayoutTool"];
|
||||||
toolBoxViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
|
toolBoxViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
|
||||||
[self presentViewController:toolBoxViewController animated:YES completion:^{
|
[self presentViewController:toolBoxViewController animated:YES completion:^{
|
||||||
//[self->toolBoxViewController setupConstraints];
|
//[self->toolBoxViewController setupConstraints];
|
||||||
|
|||||||
@@ -946,6 +946,7 @@ extension ToolboxViewController: ControllerCollectionNavigationDelegate {
|
|||||||
@objc func getNavigationElements() -> [ControllerNavigationElement] {
|
@objc func getNavigationElements() -> [ControllerNavigationElement] {
|
||||||
var elements: [ControllerNavigationElement] = []
|
var elements: [ControllerNavigationElement] = []
|
||||||
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
|
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .rightStick : .leftStick, action: "focusNavigation"))
|
||||||
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .abxy : .dpad, action: "focusNavigation"))
|
||||||
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "execute"))
|
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "execute"))
|
||||||
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "doublePressPinExecute"))
|
elements.append(ControllerNavigationElement(control: ControllerNavigator.radialMenuButtonPosition == .left ? .dpadRight : .a, action: "doublePressPinExecute"))
|
||||||
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "holdToReorder"))
|
elements.append(ControllerNavigationElement(control:ControllerNavigator.radialMenuButtonPosition == .left ? .dpadUp : .y, action: "holdToReorder"))
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import UIKit
|
|||||||
case more
|
case more
|
||||||
case navigationSettings
|
case navigationSettings
|
||||||
case exit
|
case exit
|
||||||
case shortcuts
|
case toolbox
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public enum RadialMenuState:Int {
|
@objc public enum RadialMenuState:Int {
|
||||||
|
|||||||
Reference in new issue
Block a user