Skip to content

Commit

Permalink
Remove Converter from StickManager.swift
Browse files Browse the repository at this point in the history
  • Loading branch information
tekezo committed Aug 15, 2024
1 parent 8e82c79 commit d2aeb4a
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 295 deletions.
25 changes: 8 additions & 17 deletions appendix/GamePadViewer/src/EventObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ private func callback(
public class EventObserver: ObservableObject {
public static let shared = EventObserver()

@ObservedObject var stickManager = StickManager.shared
@Published var counter = 0

// We register the callback in the `start` method rather than in `init`.
Expand Down Expand Up @@ -51,21 +50,17 @@ public class EventObserver: ObservableObject {
if usagePage == 0x1, usage == 0x30 {
counter += 1
Task { @MainActor in
stickManager.leftStick.horizontal.add(logicalMax, logicalMin, integerValue)
stickManager.leftStick.update()

stickManager.converter.convert()
StickManager.shared.leftStick.horizontal.add(logicalMax, logicalMin, integerValue)
StickManager.shared.leftStick.update()
}
}

// usage::generic_desktop::y
if usagePage == 0x1, usage == 0x31 {
counter += 1
Task { @MainActor in
stickManager.leftStick.vertical.add(logicalMax, logicalMin, integerValue)
stickManager.leftStick.update()

stickManager.converter.convert()
StickManager.shared.leftStick.vertical.add(logicalMax, logicalMin, integerValue)
StickManager.shared.leftStick.update()
}
}

Expand All @@ -77,21 +72,17 @@ public class EventObserver: ObservableObject {
if usagePage == 0x1, usage == 0x32 {
counter += 1
Task { @MainActor in
stickManager.rightStick.horizontal.add(logicalMax, logicalMin, integerValue)
stickManager.rightStick.update()

stickManager.converter.convert()
StickManager.shared.rightStick.horizontal.add(logicalMax, logicalMin, integerValue)
StickManager.shared.rightStick.update()
}
}

// usage::generic_desktop::rz
if usagePage == 0x1, usage == 0x35 {
counter += 1
Task { @MainActor in
stickManager.rightStick.vertical.add(logicalMax, logicalMin, integerValue)
stickManager.rightStick.update()

stickManager.converter.convert()
StickManager.shared.rightStick.vertical.add(logicalMax, logicalMin, integerValue)
StickManager.shared.rightStick.update()
}
}
}
Expand Down
166 changes: 1 addition & 165 deletions appendix/GamePadViewer/src/StickManager.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Combine
import SwiftUI

public class StickManager: ObservableObject {
public class StickManager {
public static let shared = StickManager()

class StickSensor: ObservableObject {
Expand All @@ -21,192 +21,28 @@ public class StickManager: ObservableObject {
}
}

struct HistoryEntry {
let time = Date()
let horizontalStickSensorValue: Double
let verticalStickSensorValue: Double
}

class Stick: ObservableObject, Equatable {
public let id = UUID()

@Published var horizontal = StickSensor()
@Published var vertical = StickSensor()
@Published var history: [HistoryEntry] = []

@Published var radian = 0.0
@Published var magnitude = 0.0
@Published var deltaMagnitude = 0.0

var previousMagnitude = 0.0

@MainActor
public func update() {
let now = Date()

radian = atan2(vertical.lastDoubleValue, horizontal.lastDoubleValue)
magnitude = min(
1.0,
sqrt(pow(vertical.lastDoubleValue, 2) + pow(horizontal.lastDoubleValue, 2)))

deltaMagnitude = max(0.0, magnitude - previousMagnitude)

history.append(
HistoryEntry(
horizontalStickSensorValue: horizontal.lastDoubleValue,
verticalStickSensorValue: vertical.lastDoubleValue))
history.removeAll(where: { now.timeIntervalSince($0.time) > 0.1 })
}

@MainActor
public func getMaxDistanceInHistory() -> Double {
var distance = 0.0

history.forEach { h1 in
history.forEach { h2 in
let h = h1.horizontalStickSensorValue - h2.horizontalStickSensorValue
let v = h1.verticalStickSensorValue - h2.verticalStickSensorValue
let d = sqrt(h * h + v * v)
if d > distance {
distance = d
}
}
}

return min(1.0, distance)
}

@MainActor func updatePreviousMagnitude() {
previousMagnitude = magnitude
}

public static func == (lhs: Stick, rhs: Stick) -> Bool {
lhs.id == rhs.id
}
}

class Converter: ObservableObject {
@Published var pointerX = 0.5 // 0.0 ... 1.0
@Published var pointerY = 0.5 // 0.0 ... 1.0
@Published var continuedMovementMagnitude = 0.0

let continuedMovementThreshold = 1.0
let deltaMagnitudeThreshold = 0.01

var continuedMovementPrimaryStick: Stick?
var continuedMovementSecondaryStick: Stick?
var continuedMovementTimer: Cancellable?
var continuedMovementCalled = false

@MainActor
public func convert() {

if let s = continuedMovementPrimaryStick {
if s.magnitude < continuedMovementThreshold {
continuedMovementPrimaryStick = nil
}
}

if continuedMovementPrimaryStick == nil {
if StickManager.shared.leftStick.magnitude >= continuedMovementThreshold {
continuedMovementPrimaryStick = StickManager.shared.leftStick
} else if StickManager.shared.rightStick.magnitude >= continuedMovementThreshold {
continuedMovementPrimaryStick = StickManager.shared.rightStick
}
}

if let continuedMovementPrimaryStick = continuedMovementPrimaryStick {
continuedMovementSecondaryStick =
continuedMovementPrimaryStick == StickManager.shared.leftStick
? StickManager.shared.rightStick
: StickManager.shared.leftStick

if continuedMovementTimer == nil {
continuedMovementMagnitude = continuedMovementPrimaryStick.getMaxDistanceInHistory()

continuedMovementTimer = Timer.publish(
every: 0.3, // 300 ms
on: .main, in: .default
).autoconnect()
.sink { _ in
self.updatePointerXY(
magnitude: self.getAdjustedContinuedMovementMagnitude(),
radian: self.getAdjustedContinuedMovementRadian())

if !self.continuedMovementCalled {
self.continuedMovementTimer = Timer.publish(
every: 0.02, // 20 ms
on: .main, in: .default
)
.autoconnect().sink { _ in

self.updatePointerXY(
magnitude: self.getAdjustedContinuedMovementMagnitude(),
radian: self.getAdjustedContinuedMovementRadian())
}
self.continuedMovementCalled = true
}
}

continuedMovementCalled = false
}
} else {
continuedMovementSecondaryStick = nil
continuedMovementTimer = nil

var keepPreviousMagnitude = false
if 0 < StickManager.shared.rightStick.deltaMagnitude {
if StickManager.shared.rightStick.deltaMagnitude < deltaMagnitudeThreshold {
keepPreviousMagnitude = true
} else {
updatePointerXY(
magnitude: StickManager.shared.rightStick.deltaMagnitude,
radian: StickManager.shared.rightStick.radian)
}
}

if !keepPreviousMagnitude {
StickManager.shared.rightStick.updatePreviousMagnitude()
}
}
}

@MainActor
private func getAdjustedContinuedMovementMagnitude() -> Double {
let m2 = continuedMovementSecondaryStick?.magnitude ?? 0.0

if m2 < deltaMagnitudeThreshold {
return continuedMovementMagnitude
} else {
return continuedMovementMagnitude + m2
}
}

@MainActor
private func getAdjustedContinuedMovementRadian() -> Double {
let r1 = continuedMovementPrimaryStick?.radian ?? 0.0
let m2 = continuedMovementSecondaryStick?.magnitude ?? 0.0
let r2 = continuedMovementSecondaryStick?.radian ?? 0.0

if m2 < deltaMagnitudeThreshold {
return r1
} else {
return (r1 + r2) / 2
}
}

@MainActor
private func updatePointerXY(magnitude: Double, radian: Double) {
let scale = 1.0 / 16

pointerX += magnitude * cos(radian) * scale
pointerX = max(0.0, min(1.0, pointerX))
pointerY -= magnitude * sin(radian) * scale
pointerY = max(0.0, min(1.0, pointerY))
}
}

@Published var leftStick = Stick()
@Published var rightStick = Stick()
@Published var converter = Converter()
}
Loading

0 comments on commit d2aeb4a

Please sign in to comment.