synthesize rsvPad inertia + gyro input convergently
This commit is contained in:
1 parent
46194a5aa0
commit
41eadce89a
3 files changed
+51
-41
No files matched your search
@@ -12,10 +12,9 @@ class InertialScroller {
|
|||||||
public lazy var timer: SafeTimer? = {
|
public lazy var timer: SafeTimer? = {
|
||||||
SafeTimer(interval: 1/displayLinkRate) { [weak self] in
|
SafeTimer(interval: 1/displayLinkRate) { [weak self] in
|
||||||
guard let self = self, handler != nil else {return}
|
guard let self = self, handler != nil else {return}
|
||||||
let deceratedDeltaX = self.vector.dx * decelerationRate
|
self.vector.dx = self.vector.dx * decelerationRate
|
||||||
let deceratedDeltaY = self.vector.dy * decelerationRate
|
self.vector.dy = self.vector.dy * decelerationRate
|
||||||
self.vector = CGVector(dx: deceratedDeltaX, dy: deceratedDeltaY)
|
if abs(self.vector.dx) < self.timerSuspendThreshold && abs(self.vector.dy) < self.timerSuspendThreshold {
|
||||||
if abs(deceratedDeltaX) < self.timerSuspendThreshold && abs(deceratedDeltaY) < self.timerSuspendThreshold {
|
|
||||||
self.timer?.pause()
|
self.timer?.pause()
|
||||||
}
|
}
|
||||||
(self.handler ?? {})()
|
(self.handler ?? {})()
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ import CoreMotion
|
|||||||
|
|
||||||
private var rightStickPhysicalInputX:Double = 0
|
private var rightStickPhysicalInputX:Double = 0
|
||||||
private var rightStickPhysicalInputY:Double = 0
|
private var rightStickPhysicalInputY:Double = 0
|
||||||
|
public var gyroToStickOffset:CGVector = CGVector(dx: 0, dy: 0)
|
||||||
|
|
||||||
private var leftStickPhysicalInputX:Double = 0
|
private var leftStickPhysicalInputX:Double = 0
|
||||||
private var leftStickPhysicalInputY:Double = 0
|
private var leftStickPhysicalInputY:Double = 0
|
||||||
@@ -302,10 +303,12 @@ import CoreMotion
|
|||||||
|
|
||||||
if oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick {
|
if oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick {
|
||||||
if oscProfile.yawPitchToRightStick {
|
if oscProfile.yawPitchToRightStick {
|
||||||
yaw = rightStickTouchInputX + rightStickPhysicalInputX + gyroInputToStickInput(input:yawSource*sensitvityYaw*widgetYawFactor*10)
|
gyroToStickOffset.dx = gyroInputToStickInput(input:yawSource*sensitvityYaw*widgetYawFactor*10)
|
||||||
|
yaw = rightStickTouchInputX + rightStickPhysicalInputX + gyroToStickOffset.dx
|
||||||
yaw = self.clampStickInput(input: yaw)
|
yaw = self.clampStickInput(input: yaw)
|
||||||
|
|
||||||
pitch = rightStickTouchInputY + rightStickPhysicalInputY - gyroInputToStickInput(input:pitchSource*sensitvityPitch*widgetPitchFactor*10)
|
gyroToStickOffset.dy = -gyroInputToStickInput(input:pitchSource*sensitvityPitch*widgetPitchFactor*10)
|
||||||
|
pitch = rightStickTouchInputY + rightStickPhysicalInputY + gyroToStickOffset.dy
|
||||||
pitch = self.clampStickInput(input: pitch)
|
pitch = self.clampStickInput(input: pitch)
|
||||||
|
|
||||||
let offsetVector = ControllerUtil.compensated(offsetVector: CGVector(dx: yaw, dy: pitch), withMinOffset: gyroToStickMinOffset)
|
let offsetVector = ControllerUtil.compensated(offsetVector: CGVector(dx: yaw, dy: pitch), withMinOffset: gyroToStickMinOffset)
|
||||||
|
|||||||
@@ -143,8 +143,9 @@ import UIKit
|
|||||||
@objc public var deltaX: CGFloat
|
@objc public var deltaX: CGFloat
|
||||||
@objc public var deltaY: CGFloat
|
@objc public var deltaY: CGFloat
|
||||||
|
|
||||||
@objc private var weightedDeltaX: Int = 0
|
private let VectorStickFactor = 1.5167
|
||||||
@objc private var weightedDeltaY: Int = 0
|
private var weightedDeltaX: Int = 0
|
||||||
|
private var weightedDeltaY: Int = 0
|
||||||
|
|
||||||
// for LSPAD, RSPAD
|
// for LSPAD, RSPAD
|
||||||
@objc public var offSetX: CGFloat
|
@objc public var offSetX: CGFloat
|
||||||
@@ -1288,11 +1289,15 @@ import UIKit
|
|||||||
|
|
||||||
|
|
||||||
//=========================================send on screen controller stick/trigger events
|
//=========================================send on screen controller stick/trigger events
|
||||||
private func touchInputToStickInput(input: CGFloat) -> CGFloat{
|
private func weightedTouchInputToStickOffset(input: CGFloat) -> CGFloat{
|
||||||
let target = stickMaxOffset * input / stickInputScale
|
let target = stickMaxOffset * input / stickInputScale
|
||||||
return fmax(fmin(target, stickMaxOffset),-stickMaxOffset)
|
return fmax(fmin(target, stickMaxOffset),-stickMaxOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func stickOffsetToWeightedTouchInput(offset: CGFloat) -> CGFloat {
|
||||||
|
return offset * stickInputScale / stickMaxOffset
|
||||||
|
}
|
||||||
|
|
||||||
private func touchInputToStickBallCoord(input: CGFloat) -> CGFloat {
|
private func touchInputToStickBallCoord(input: CGFloat) -> CGFloat {
|
||||||
if input > stickInputScale {
|
if input > stickInputScale {
|
||||||
return stickBallMaxOffset
|
return stickBallMaxOffset
|
||||||
@@ -1303,9 +1308,9 @@ import UIKit
|
|||||||
return input * (18/stickInputScale)
|
return input * (18/stickInputScale)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendRightStickTouchPadEvent(inputX: CGFloat, inputY: CGFloat){
|
private func sendRightStickTouchPadEvent(weightedTouchX: CGFloat, weightedTouchY: CGFloat){
|
||||||
let targetX = self.touchInputToStickInput(input: inputX)
|
let targetX = self.weightedTouchInputToStickOffset(input: weightedTouchX)
|
||||||
let targetY = -self.touchInputToStickInput(input: inputY)
|
let targetY = -self.weightedTouchInputToStickOffset(input: weightedTouchY)
|
||||||
|
|
||||||
let mixRightStickInputToGyro = (oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick
|
let mixRightStickInputToGyro = (oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick
|
||||||
&& oscProfile.yawPitchToRightStick)
|
&& oscProfile.yawPitchToRightStick)
|
||||||
@@ -1317,9 +1322,9 @@ import UIKit
|
|||||||
self.motionHandler.mixOnScreenRightStickAndGyroInput(x: targetX, y: targetY)
|
self.motionHandler.mixOnScreenRightStickAndGyroInput(x: targetX, y: targetY)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func sendLeftStickTouchPadEvent(inputX: CGFloat, inputY: CGFloat){
|
private func sendLeftStickTouchPadEvent(weightedTouchX: CGFloat, weightedTouchY: CGFloat){
|
||||||
let targetX = self.touchInputToStickInput(input: inputX)
|
let targetX = self.weightedTouchInputToStickOffset(input: weightedTouchX)
|
||||||
let targetY = -self.touchInputToStickInput(input: inputY)
|
let targetY = -self.weightedTouchInputToStickOffset(input: weightedTouchY)
|
||||||
|
|
||||||
let mixLeftStickInputToGyro = (oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick
|
let mixLeftStickInputToGyro = (oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick
|
||||||
&& oscProfile.rollToLeftStick)
|
&& oscProfile.rollToLeftStick)
|
||||||
@@ -1778,32 +1783,32 @@ import UIKit
|
|||||||
case "LSPAD":
|
case "LSPAD":
|
||||||
DispatchQueue.global(qos: .userInteractive).async {
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
self.weightedDeltaX = 1
|
self.weightedDeltaX = 1
|
||||||
self.sendLeftStickTouchPadEvent(inputX: self.offSetX * self.sensitivityFactorX, inputY: self.offSetY * self.sensitivityFactorY)
|
self.sendLeftStickTouchPadEvent(weightedTouchX: self.offSetX * self.sensitivityFactorX, weightedTouchY: self.offSetY * self.sensitivityFactorY)
|
||||||
}
|
}
|
||||||
if widgetType == WidgetTypeEnum.touchPad {updateStickIndicator()}
|
if widgetType == WidgetTypeEnum.touchPad {updateStickIndicator()}
|
||||||
self.updateTouchLocation(touch: touches.first!)
|
self.updateTouchLocation(touch: touches.first!)
|
||||||
case "RSPAD":
|
case "RSPAD":
|
||||||
DispatchQueue.global(qos: .userInteractive).async {
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
self.weightedDeltaX = 1
|
self.weightedDeltaX = 1
|
||||||
self.sendRightStickTouchPadEvent(inputX: self.offSetX * self.sensitivityFactorX, inputY: self.offSetY * self.sensitivityFactorY)
|
self.sendRightStickTouchPadEvent(weightedTouchX: self.offSetX * self.sensitivityFactorX, weightedTouchY: self.offSetY * self.sensitivityFactorY)
|
||||||
}
|
}
|
||||||
if widgetType == WidgetTypeEnum.touchPad {updateStickIndicator()}
|
if widgetType == WidgetTypeEnum.touchPad {updateStickIndicator()}
|
||||||
self.updateTouchLocation(touch: touches.first!)
|
self.updateTouchLocation(touch: touches.first!)
|
||||||
case "LSVPAD":
|
case "LSVPAD":
|
||||||
DispatchQueue.global(qos: .userInteractive).async {
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
self.weightedDeltaX = Int(self.deltaX*1.5167*self.sensitivityFactorX)
|
self.weightedDeltaX = Int(self.deltaX*self.VectorStickFactor*self.sensitivityFactorX)
|
||||||
self.weightedDeltaY = Int(self.deltaY*1.5167*self.sensitivityFactorY)
|
self.weightedDeltaY = Int(self.deltaY*self.VectorStickFactor*self.sensitivityFactorY)
|
||||||
if self.firstTouchMoved {
|
if self.firstTouchMoved {
|
||||||
self.sendLeftStickTouchPadEvent(inputX: CGFloat(self.weightedDeltaX), inputY: CGFloat(self.weightedDeltaY))
|
self.sendLeftStickTouchPadEvent(weightedTouchX: CGFloat(self.weightedDeltaX), weightedTouchY: CGFloat(self.weightedDeltaY))
|
||||||
}
|
}
|
||||||
self.updateTouchLocation(touch: touches.first!)
|
self.updateTouchLocation(touch: touches.first!)
|
||||||
}
|
}
|
||||||
case "RSVPAD":
|
case "RSVPAD":
|
||||||
DispatchQueue.global(qos: .userInteractive).async {
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
self.weightedDeltaX = Int(self.deltaX*1.5167*self.sensitivityFactorX)
|
self.weightedDeltaX = Int(self.deltaX*self.VectorStickFactor*self.sensitivityFactorX)
|
||||||
self.weightedDeltaY = Int(self.deltaY*1.5167*self.sensitivityFactorY)
|
self.weightedDeltaY = Int(self.deltaY*self.VectorStickFactor*self.sensitivityFactorY)
|
||||||
if self.firstTouchMoved {
|
if self.firstTouchMoved {
|
||||||
self.sendRightStickTouchPadEvent(inputX: CGFloat(self.weightedDeltaX), inputY: CGFloat(self.weightedDeltaY))
|
self.sendRightStickTouchPadEvent(weightedTouchX: CGFloat(self.weightedDeltaX), weightedTouchY: CGFloat(self.weightedDeltaY))
|
||||||
}
|
}
|
||||||
self.updateTouchLocation(touch: touches.first!)
|
self.updateTouchLocation(touch: touches.first!)
|
||||||
}
|
}
|
||||||
@@ -2014,17 +2019,6 @@ import UIKit
|
|||||||
self.handleMousePadButtonActionUp()
|
self.handleMousePadButtonActionUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && self.touchPadString == "TRACKBALL" && allSpawnedTouchesCount == 1 && !twoTouchesDetected {
|
|
||||||
if(mousePointerMoved){
|
|
||||||
self.startTrackballMomentum()
|
|
||||||
mousePointerMoved = false //reset flag
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
self.stopTrackballMomentum()
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && CommandManager.mousePadWithButtonActions.contains(self.touchPadString) && twoTouchesDetected && touches.count == allSpawnedTouchesCount { // need to enable multi-touch first
|
if !OnScreenWidgetView.editMode && self.widgetType == WidgetTypeEnum.touchPad && CommandManager.mousePadWithButtonActions.contains(self.touchPadString) && twoTouchesDetected && touches.count == allSpawnedTouchesCount { // need to enable multi-touch first
|
||||||
// touches.count == allCapturedTouchesCount means allfingers are lifting
|
// touches.count == allCapturedTouchesCount means allfingers are lifting
|
||||||
if(self.mouseButtonAction == MouseButtonAction.hovering) {self.sendMouseRightButtonClickEvent()}
|
if(self.mouseButtonAction == MouseButtonAction.hovering) {self.sendMouseRightButtonClickEvent()}
|
||||||
@@ -2046,9 +2040,9 @@ import UIKit
|
|||||||
if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)}
|
if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)}
|
||||||
if self.inertialScroller.handler == nil {
|
if self.inertialScroller.handler == nil {
|
||||||
self.inertialScroller.handler = {
|
self.inertialScroller.handler = {
|
||||||
let weightedDeltaX = self.inertialScroller.vector.dx*1.5167*self.sensitivityFactorX
|
let weightedDeltaX = self.inertialScroller.vector.dx*self.VectorStickFactor*self.sensitivityFactorX
|
||||||
let weightedDeltaY = self.inertialScroller.vector.dy*1.5167*self.sensitivityFactorY
|
let weightedDeltaY = self.inertialScroller.vector.dy*self.VectorStickFactor*self.sensitivityFactorY
|
||||||
self.sendLeftStickTouchPadEvent(inputX: weightedDeltaX, inputY: weightedDeltaY)
|
self.sendLeftStickTouchPadEvent(weightedTouchX: weightedDeltaX, weightedTouchY: weightedDeltaY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.inertialScroller.timer?.restart()
|
self.inertialScroller.timer?.restart()
|
||||||
@@ -2058,10 +2052,24 @@ import UIKit
|
|||||||
if self.decelerationRate > 0.50001 {
|
if self.decelerationRate > 0.50001 {
|
||||||
if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)}
|
if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)}
|
||||||
if self.inertialScroller.handler == nil {
|
if self.inertialScroller.handler == nil {
|
||||||
self.inertialScroller.handler = {
|
var synthesizedDeltaX:CGFloat = 0
|
||||||
let weightedDeltaX = self.inertialScroller.vector.dx*1.5167*self.sensitivityFactorX
|
var synthesizedDeltaY:CGFloat = 0
|
||||||
let weightedDeltaY = self.inertialScroller.vector.dy*1.5167*self.sensitivityFactorY
|
self.inertialScroller.handler = { [self] in
|
||||||
self.sendRightStickTouchPadEvent(inputX: weightedDeltaX, inputY: weightedDeltaY)
|
let weightedScrollerVector = CGVector(dx: self.inertialScroller.vector.dx*self.VectorStickFactor*self.sensitivityFactorX, dy: self.inertialScroller.vector.dy*self.VectorStickFactor*self.sensitivityFactorY)
|
||||||
|
|
||||||
|
if self.motionHandler.gyroMixInputStarted() {
|
||||||
|
let normailizedGyroVector = CGVector(dx: self.stickOffsetToWeightedTouchInput(offset: self.motionHandler.gyroToStickOffset.dx), dy: -self.stickOffsetToWeightedTouchInput(offset: self.motionHandler.gyroToStickOffset.dy))
|
||||||
|
|
||||||
|
let xConvergent = normailizedGyroVector.dx.sign != weightedScrollerVector.dx.sign && abs(normailizedGyroVector.dx) <= abs(weightedScrollerVector.dx)
|
||||||
|
let yConvergent = normailizedGyroVector.dy.sign != weightedScrollerVector.dy.sign && abs(normailizedGyroVector.dy) <= abs(weightedScrollerVector.dy)
|
||||||
|
|
||||||
|
synthesizedDeltaX = xConvergent ? normailizedGyroVector.dx + weightedScrollerVector.dx : weightedScrollerVector.dx
|
||||||
|
synthesizedDeltaY = yConvergent ? normailizedGyroVector.dy + weightedScrollerVector.dy : weightedScrollerVector.dy
|
||||||
|
|
||||||
|
self.inertialScroller.vector.dx = synthesizedDeltaX/(self.VectorStickFactor*self.sensitivityFactorX)
|
||||||
|
self.inertialScroller.vector.dy = synthesizedDeltaY/(self.VectorStickFactor*self.sensitivityFactorY)
|
||||||
|
}
|
||||||
|
self.sendRightStickTouchPadEvent(weightedTouchX: weightedScrollerVector.dx, weightedTouchY: weightedScrollerVector.dy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.inertialScroller.timer?.restart()
|
self.inertialScroller.timer?.restart()
|
||||||
|
|||||||
Reference in new issue
Block a user