Skip to content

Commit

Permalink
Merge pull request #39 from XuYicong/feat/controller-mapping
Browse files Browse the repository at this point in the history
Controller Mapping - Part 1
  • Loading branch information
Depal1 authored Nov 13, 2022
2 parents d8783b0 + aca900f commit 320d5f3
Show file tree
Hide file tree
Showing 8 changed files with 473 additions and 275 deletions.
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

0 comments on commit 320d5f3

Please sign in to comment.