Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controller Mapping - Part 1 #39

Merged
merged 11 commits into from
Nov 13, 2022
199 changes: 138 additions & 61 deletions PlayTools/Controls/PlayAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,63 @@ extension GCKeyboard {
class ButtonAction: Action {
func invalidate() {
Toucher.touchcam(point: point, phase: UITouch.Phase.ended, tid: id)
if let keyboard = GCKeyboard.coalesced?.keyboardInput {
keyboard.button(forKeyCode: key)?.pressedChangedHandler = nil
if let gcKey = GCKeyboard.coalesced?.keyboardInput?.button(forKeyCode: keyCode) {
gcKey.pressedChangedHandler = nil

} else if let gcControllerElement = GCController.current?.extendedGamepad?.elements[keyName] {

if let gcControllerButton = gcControllerElement as? GCControllerButtonInput {
gcControllerButton.pressedChangedHandler = nil
}

}
}

let key: GCKeyCode
let keyCode: GCKeyCode
let keyName: String
let point: CGPoint
var id: Int

init(id: Int, key: GCKeyCode, point: CGPoint) {
self.key = key
private func getChangedHandler<T1>(handler: ((T1, Float, Bool) -> Void)?) -> (T1, Float, Bool) -> Void {
return { button, value, pressed in
if !mode.visible && !PlayInput.cmdPressed() {
self.update(pressed: pressed)
}
if let previous = handler {
previous(button, value, pressed)
}
}
}

init(id: Int, keyCode: GCKeyCode, keyName: String, point: CGPoint) {
self.keyCode = keyCode
self.keyName = keyName
self.point = point
self.id = id
if let keyboard = GCKeyboard.coalesced?.keyboardInput {
if !PlayMice.shared.setMiceButtons(key.rawValue, action: self) {
let handler = keyboard.button(forKeyCode: key)?.pressedChangedHandler
keyboard.button(forKeyCode: key)?.pressedChangedHandler = { button, value, pressed in
if !mode.visible && !PlayInput.cmdPressed() {
self.update(pressed: pressed)
}
if let previous = handler {
previous(button, value, pressed)
}
}
if PlayMice.shared.setMiceButtons(keyCode.rawValue, action: self) {
// No more work to do for mouse buttons
} else if let gcKey = GCKeyboard.coalesced?.keyboardInput?.button(forKeyCode: keyCode) {
let handler = gcKey.pressedChangedHandler
gcKey.pressedChangedHandler = getChangedHandler(handler: handler)

} else if let gcControllerElement = GCController.current?.extendedGamepad?.elements[keyName] {

if let gcControllerButton = gcControllerElement as? GCControllerButtonInput {
let handler = gcControllerButton.pressedChangedHandler
gcControllerButton.pressedChangedHandler = getChangedHandler(handler: handler)
}

} else {
Toast.showOver(msg: "failed to map button at point \(point)")
}
}

convenience init(id: Int, data: Button) {
let keyCode = GCKeyCode(rawValue: data.keyCode)
self.init(
id: id,
key: GCKeyCode(rawValue: data.keyCode),
keyCode: keyCode,
keyName: data.keyName,
point: CGPoint(
x: data.transform.xCoord.absoluteX,
y: data.transform.yCoord.absoluteY))
Expand All @@ -66,42 +91,93 @@ class ButtonAction: Action {
}

class DraggableButtonAction: ButtonAction {
static public var activeButton: DraggableButtonAction?

var releasePoint: CGPoint

override init(id: Int, key: GCKeyCode, point: CGPoint) {
override init(id: Int, keyCode: GCKeyCode, keyName: String, point: CGPoint) {
self.releasePoint = point
super.init(id: id, key: key, point: point)
if settings.mouseMapping {
PlayMice.shared.setupMouseMovedHandler()
}
super.init(id: id, keyCode: keyCode, keyName: keyName, point: point)
_ = PlayMice.shared.setupThumbstickChangedHandler(name: keyName)
}

override func update(pressed: Bool) {
if pressed {
Toucher.touchcam(point: point, phase: UITouch.Phase.began, tid: id)
self.releasePoint = point
DraggableButtonAction.activeButton = self
PlayMice.shared.draggableHandler[keyName] = self.onMouseMoved
} else {
DraggableButtonAction.activeButton = nil
PlayMice.shared.draggableHandler.removeValue(forKey: keyName)
Toucher.touchcam(point: releasePoint, phase: UITouch.Phase.ended, tid: id)
}
}

override func invalidate() {
DraggableButtonAction.activeButton = nil
PlayMice.shared.draggableHandler.removeValue(forKey: keyName)
PlayMice.shared.stop()
super.invalidate()
}

func onMouseMoved(deltaX: CGFloat, deltaY: CGFloat) {
self.releasePoint.x += deltaX * CGFloat(PlaySettings.shared.sensitivity)
self.releasePoint.y -= deltaY * CGFloat(PlaySettings.shared.sensitivity)
self.releasePoint.x += deltaX
self.releasePoint.y -= deltaY
Toucher.touchcam(point: self.releasePoint, phase: UITouch.Phase.moved, tid: id)
}
}

class ConcreteJoystickAction: Action {
var key: String
var center: CGPoint
var position: CGPoint!
var id: Int
var sensitivity: CGFloat
var begun = false

init(id: Int, data: Joystick) {
self.id = id
self.center = CGPoint(
x: data.transform.xCoord.absoluteX,
y: data.transform.yCoord.absoluteY)
self.key = data.keyName
position = center
self.sensitivity = data.transform.size.absoluteSize / 4
if PlayMice.shared.setupThumbstickChangedHandler(name: key) {
PlayMice.shared.joystickHandler[key] = thumbstickUpdate
} else {
PlayMice.shared.joystickHandler[key] = mouseUpdate
}
}

func update(_ point: CGPoint) {
let dis = (center.x - point.x).magnitude + (center.y - point.y).magnitude
if dis < 16 {
if begun {
begun = false
Toucher.touchcam(point: point, phase: UITouch.Phase.ended, tid: id)
}
} else if !begun {
begun = true
Toucher.touchcam(point: point, phase: UITouch.Phase.began, tid: id)
} else {
Toucher.touchcam(point: point, phase: UITouch.Phase.moved, tid: id)
}
}

func thumbstickUpdate(_ deltaX: CGFloat, _ deltaY: CGFloat) {
let pos = CGPoint(x: center.x + deltaX * sensitivity,
y: center.y - deltaY * sensitivity)
self.update(pos)
}

func mouseUpdate(_ deltaX: CGFloat, _ deltaY: CGFloat) {
position.x += deltaX
position.y -= deltaY
self.update(position)
}

func invalidate() {
PlayMice.shared.joystickHandler.removeValue(forKey: key)
}
}

class JoystickAction: Action {
let keys: [GCKeyCode]
let center: CGPoint
Expand Down Expand Up @@ -153,39 +229,40 @@ class JoystickAction: Action {
}

func update() {
if !mode.visible {
var touch = center
var start = center
if GCKeyboard.pressed(key: keys[0]) {
touch.y -= shift / 3
} else if GCKeyboard.pressed(key: keys[1]) {
touch.y += shift / 3
}
if GCKeyboard.pressed(key: keys[2]) {
touch.x -= shift / 3
} else if GCKeyboard.pressed(key: keys[3]) {
touch.x += shift / 3
}
if moving {
if touch.equalTo(center) {
moving = false
Toucher.touchcam(point: touch, phase: UITouch.Phase.ended, tid: id)
} else {
Toucher.touchcam(point: touch, phase: UITouch.Phase.moved, tid: id)
}
if mode.visible {
return
}
var touch = center
var start = center
if GCKeyboard.pressed(key: keys[0]) {
touch.y -= shift / 3
} else if GCKeyboard.pressed(key: keys[1]) {
touch.y += shift / 3
}
if GCKeyboard.pressed(key: keys[2]) {
touch.x -= shift / 3
} else if GCKeyboard.pressed(key: keys[3]) {
touch.x += shift / 3
}
if moving {
if touch.equalTo(center) {
moving = false
Toucher.touchcam(point: touch, phase: UITouch.Phase.ended, tid: id)
} else {
if !touch.equalTo(center) {
start.x += (touch.x - start.x) / 8
start.y += (touch.y - start.y) / 8
moving = true
Toucher.touchcam(point: start, phase: UITouch.Phase.began, tid: id)
Toucher.touchQueue.asyncAfter(deadline: .now() + 0.04) {
if self.moving {
Toucher.touchcam(point: touch, phase: UITouch.Phase.moved, tid: self.id)
}
}
}
Toucher.touchcam(point: touch, phase: UITouch.Phase.moved, tid: id)
}
}
} else {
if !touch.equalTo(center) {
start.x += (touch.x - start.x) / 8
start.y += (touch.y - start.y) / 8
moving = true
Toucher.touchcam(point: start, phase: UITouch.Phase.began, tid: id)
Toucher.touchQueue.asyncAfter(deadline: .now() + 0.04) {
if self.moving {
Toucher.touchcam(point: touch, phase: UITouch.Phase.moved, tid: self.id)
} // end if
} // end closure
} // end if
} // end else
}
}
57 changes: 44 additions & 13 deletions PlayTools/Controls/PlayInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ class PlayInput {
}
}

func setup() {
func parseKeymap() {
actions = []
// ID 1 is left for mouse area
var counter = 2
// ID starts from 1
var counter = 1
for button in keymap.keymapData.buttonModels {
actions.append(ButtonAction(id: counter, data: button))
counter += 1
Expand All @@ -31,25 +31,33 @@ class PlayInput {
counter += 1
}

if settings.mouseMapping {
for mouse in keymap.keymapData.mouseAreaModel {
PlayMice.shared.setup(mouse)
for mouse in keymap.keymapData.mouseAreaModel {
if mouse.keyName.hasSuffix("tick") || settings.mouseMapping {
actions.append(CameraAction(id: counter, data: mouse))
counter += 1
}
}

for joystick in keymap.keymapData.joystickModel {
actions.append(JoystickAction(id: counter, data: joystick))
// Left Thumbstick, Right Thumbstick, Mouse
if joystick.keyName.contains(Character("u")) {
actions.append(ConcreteJoystickAction(id: counter, data: joystick))
} else { // Keyboard
actions.append(JoystickAction(id: counter, data: joystick))
}
counter += 1
}
}

func setup() {
parseKeymap()
if let keyboard = GCKeyboard.coalesced?.keyboardInput {
keyboard.keyChangedHandler = { _, _, keyCode, _ in
if editor.editorMode
&& !PlayInput.cmdPressed()
&& !PlayInput.FORBIDDEN.contains(keyCode)
&& self.isSafeToBind(keyboard) {
EditorController.shared.setKeyCode(keyCode.rawValue)
EditorController.shared.setKey(keyCode.rawValue)
}
}
keyboard.button(forKeyCode: .leftGUI)?.pressedChangedHandler = { _, _, pressed in
Expand All @@ -65,6 +73,27 @@ class PlayInput {
self.swapMode(pressed)
}
}

if let controller = GCController.current?.extendedGamepad {
controller.valueChangedHandler = { _, element in
// This is the index of controller buttons, which is String, not Int
let alias: String! = element.aliases.first
// Toast.showOver(msg: alias)
if editor.editorMode {
EditorController.shared.setKey(alias)
}
}
}
for mouse in GCMouse.mice() {
mouse.mouseInput?.mouseMovedHandler = { _, deltaX, deltaY in
if editor.editorMode {
// EditorController.shared.setKey("Mouse")
} else {
PlayMice.shared.handleMouseMoved(deltaX: deltaX, deltaY: deltaY)
}
}
}

}

static public func cmdPressed() -> Bool {
Expand All @@ -73,11 +102,9 @@ class PlayInput {

private func isSafeToBind(_ input: GCKeyboardInput) -> Bool {
var result = true
for forbidden in PlayInput.FORBIDDEN {
if input.button(forKeyCode: forbidden)?.isPressed ?? false {
result = false
break
}
for forbidden in PlayInput.FORBIDDEN where input.button(forKeyCode: forbidden)?.isPressed ?? false {
result = false
break
}
return result
}
Expand Down Expand Up @@ -122,6 +149,10 @@ class PlayInput {
PlayInput.shared.setup()
}

centre.addObserver(forName: NSNotification.Name.GCControllerDidConnect, object: nil, queue: main) { _ in
PlayInput.shared.setup()
}

setup()

// Fix beep sound
Expand Down
Loading