Subversion Repositories Mobile Apps.GyroMouse

Rev

Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
//
2
//  MouseViewController.swift
3
//  GyroMouse
4
//
5
//  Created by Matteo Riva on 08/08/15.
6
//  Copyright © 2015 Matteo Riva. All rights reserved.
7
//
8
 
9
import UIKit
10
import CoreMotion
11
 
12
 
13
// Extend from MyUITextFieldDelegate instead of UITextFieldDelegate in your class
14
protocol MyUITextFieldDelegate : UITextFieldDelegate {
15
    func didPressBackspace(_ textField: MyUITextField)
16
}
17
class MyUITextField: UITextField {
18
    override func deleteBackward() {
19
        super.deleteBackward()
20
        if let myDelegate = self.delegate as? MyUITextFieldDelegate {
21
            myDelegate.didPressBackspace(self)
22
        }
23
    }
24
}
25
 
26
 
27
class MouseViewController: UIViewController, MyUITextFieldDelegate, SettingsViewControllerDelegate {
28
 
29
    private var txtInput = MyUITextField(frame: CGRect(x: UIScreen.main.bounds.size.width * 1 / 8,
30
                                                       y: UIScreen.main.bounds.size.height * 1 / 32,
31
                                                       width: UIScreen.main.bounds.size.width * 6 / 8,
32
                                                       height: UIScreen.main.bounds.size.width * 1 / 16))
33
 
34
    private var lButton = UIButton(frame: CGRect(x: 0,
35
                                                 y: UIScreen.main.bounds.size.height * 2 / 16,
36
                                                 width: UIScreen.main.bounds.size.width * 3 / 4,
7 pmbaty 37
                                                 height: UIScreen.main.bounds.size.height * 7 / 16))
1 pmbaty 38
    private var rButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.size.width * 3 / 4,
39
                                                 y: UIScreen.main.bounds.size.height * 2 / 16,
40
                                                 width: UIScreen.main.bounds.size.width * 1 / 4,
7 pmbaty 41
                                                 height: UIScreen.main.bounds.size.height * 5 / 16))
42
    private var resetButton = UIButton(frame: CGRect(x: UIScreen.main.bounds.size.width * 3 / 4,
43
                                                     y: UIScreen.main.bounds.size.height * 7 / 16,
44
                                                     width: UIScreen.main.bounds.size.width * 1 / 4,
45
                                                     height: UIScreen.main.bounds.size.height * 2 / 16))
1 pmbaty 46
 
47
    private let client = (UIApplication.shared.delegate as! AppDelegate).client
48
    private let manager = CMMotionManager()
49
 
50
    private var moveVelocity = UserDefaults.standard.double(forKey: "moveVelocity")
51
    private var scrollVelocity = UserDefaults.standard.double(forKey: "scrollVelocity")
52
    private var shakeToReset = UserDefaults.standard.bool(forKey: "shakeToReset")
7 pmbaty 53
 
54
    private var suspendMotionPacketsUntil: Date = Date()
1 pmbaty 55
 
56
    private lazy var handler: CMDeviceMotionHandler = {
57
        return {[weak self] (data, error) -> Void in
7 pmbaty 58
            if (error == nil) && (self != nil) && (Date() > self!.suspendMotionPacketsUntil) {
59
                self?.client.sendPacket(
60
                    ((data!.attitude.roll > -0.45) && (data!.attitude.roll < 0.45) ? "move" : "scroll"),
61
                    keyTapped: "",
62
                    isButtonDown: false,
63
                    isRightButton: false,
64
                    roll: data!.attitude.roll,
65
                    scrollVelocity: (self?.scrollVelocity ?? 0),
66
                    grav: (X: data!.gravity.x, Y: data!.gravity.y, Z: data!.gravity.z),
67
                    rotat: (X: data!.rotationRate.x, Z: data!.rotationRate.z),
68
                    acc: (X: data!.userAcceleration.x, Y: data!.userAcceleration.y, Z: data!.userAcceleration.z),
69
                    moveVelocity: (self?.moveVelocity ?? 0)
70
                )
1 pmbaty 71
            }
72
        }
73
    }()
74
 
75
    override func viewDidLoad() {
76
        super.viewDidLoad()
77
 
78
        if manager.isDeviceMotionAvailable {
79
            manager.deviceMotionUpdateInterval = 0.01
80
            manager.startDeviceMotionUpdates(to: OperationQueue.main, withHandler: handler)
81
        }
82
 
7 pmbaty 83
        NotificationCenter.default.addObserver(forName: GyroMouseDisconnectedNotification, object: client, queue: OperationQueue.main) {[weak self] (_) -> Void in
1 pmbaty 84
            _=self?.navigationController?.popViewController(animated: true)
85
        }
86
 
87
        txtInput.tintColor = UIColor.white
88
        txtInput.backgroundColor = UIColor.darkGray.withAlphaComponent(0.7)
89
        txtInput.textColor = UIColor.white
90
        txtInput.textAlignment = .center
91
        txtInput.font = UIFont.systemFont(ofSize: 15)
92
        txtInput.borderStyle = UITextField.BorderStyle.roundedRect
93
        txtInput.keyboardType = UIKeyboardType.default
94
        txtInput.returnKeyType = UIReturnKeyType.done
95
        txtInput.clearButtonMode = UITextField.ViewMode.whileEditing
96
        txtInput.autocorrectionType = .no
97
        txtInput.spellCheckingType = .no
98
        txtInput.delegate = self
99
        self.view.addSubview(txtInput)
100
 
101
        lButton.backgroundColor = .black
102
        lButton.layer.borderWidth = CGFloat(1.0)
103
        lButton.layer.borderColor = UIColor.darkGray.cgColor//(gray: 0.25, alpha: 1)//(red: 0.25, green: 0.25, blue: 0.25, alpha: 1)
104
        lButton.addTarget(self, action: #selector(lButtonDown), for: .touchDown)
105
        lButton.addTarget(self, action: #selector(lButtonUp), for: .touchUpInside)
106
        self.view.addSubview(lButton)
107
 
108
        rButton.backgroundColor = .black
109
        rButton.layer.borderWidth = CGFloat(1.0)
110
        rButton.layer.borderColor = UIColor.darkGray.cgColor//CGColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1)
111
        rButton.addTarget(self, action: #selector(rButtonDown), for: .touchDown)
112
        rButton.addTarget(self, action: #selector(rButtonUp), for: .touchUpInside)
113
        self.view.addSubview(rButton)
7 pmbaty 114
 
115
        resetButton.backgroundColor = .black
116
        resetButton.layer.borderWidth = CGFloat(1.0)
117
        resetButton.layer.borderColor = UIColor.darkGray.cgColor//CGColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1)
118
        resetButton.addTarget(self, action: #selector(resetButtonTouched), for: .touchDown)
119
        self.view.addSubview(resetButton)
1 pmbaty 120
    }
121
 
122
    @objc func lButtonDown()
123
    {
124
        lButton.backgroundColor = UIColor (red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5) // grey
7 pmbaty 125
        self.suspendMotionPacketsUntil = Date() + TimeInterval(0.25) // block motion packets for 250 milliseconds to facilitate precise clicks
126
        self.client.sendPacket("click", keyTapped: "", isButtonDown: true, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 127
    }
128
    @objc func lButtonUp()
129
    {
130
        lButton.backgroundColor = UIColor (red: 0, green: 0, blue: 0, alpha: 0.8) // black
7 pmbaty 131
        self.client.sendPacket("click", keyTapped: "", isButtonDown: false, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 132
    }
133
 
134
    @objc func rButtonDown()
135
    {
136
        rButton.backgroundColor = UIColor (red: 0.5, green: 0.5, blue: 0.5, alpha: 0.5) // grey
7 pmbaty 137
        self.suspendMotionPacketsUntil = Date() + TimeInterval(0.25) // block motion packets for 250 milliseconds to facilitate precise clicks
138
        self.client.sendPacket("click", keyTapped: "", isButtonDown: true, isRightButton: true, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 139
    }
140
 
141
    @objc func rButtonUp()
142
    {
143
        rButton.backgroundColor = UIColor (red: 0, green: 0, blue: 0, alpha: 0.8) // black
7 pmbaty 144
        self.client.sendPacket("click", keyTapped: "", isButtonDown: false, isRightButton: true, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 145
    }
146
 
7 pmbaty 147
    @objc func resetButtonTouched()
148
    {
149
        self.client.sendPacket("reset", keyTapped: "", isButtonDown: false, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
150
    }
151
 
1 pmbaty 152
    deinit {
153
        NotificationCenter.default.removeObserver(self)
154
        manager.stopDeviceMotionUpdates()
155
        client.endConnection()
156
    }
157
 
158
    //MARK: - Mouse actions
159
 
160
    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
161
        if event?.subtype == .motionShake && shakeToReset {
162
            resetPointerPositionAction()
163
        }
164
    }
165
 
166
    //MARK: - Button actions
167
 
168
    @IBAction func resetPointerPositionAction() {
7 pmbaty 169
        self.client.sendPacket("reset", keyTapped: "", isButtonDown: false, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 170
    }
171
 
172
    //MARK: - KeyboardHandlerDelegate
173
 
174
    override func viewDidAppear(_ animated: Bool) {
175
        txtInput.becomeFirstResponder() // forces iOS keyboard to appear
176
    }
177
 
178
    func didPressBackspace(_ textField: MyUITextField) {
7 pmbaty 179
        self.client.sendPacket("backspace", keyTapped: "", isButtonDown: false, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 180
    }
181
 
182
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
7 pmbaty 183
        self.client.sendPacket("key", keyTapped: string, isButtonDown: false, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 184
        return true
185
    }
186
 
187
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
7 pmbaty 188
        self.client.sendPacket("enter", keyTapped: "", isButtonDown: false, isRightButton: false, roll: 0, scrollVelocity: 0, grav: (X: 0, Y: 0, Z: 0), rotat: (X: 0, Z: 0), acc: (X: 0, Y: 0, Z: 0), moveVelocity: 0)
1 pmbaty 189
        txtInput.text = ""
190
        return false
191
    }
192
 
193
    //MARK: - SettingsViewControllerDelegate
194
 
195
    func settingsDidChangeMoveVelocity(_ moveVelocity: Double) {
196
        self.moveVelocity = moveVelocity
197
    }
198
 
199
    func settingsDidChangeScrollVelocity(_ scrollVelocity: Double) {
200
        self.scrollVelocity = scrollVelocity
201
    }
202
 
203
    func settingsDidChangeShakeToReset(_ shakeActive: Bool) {
204
        self.shakeToReset = shakeActive
205
    }
206
 
207
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
208
        if segue.identifier == "settingsSegue" {
209
            let controller = segue.destination as! UINavigationController
210
            let view = controller.viewControllers.first! as! SettingsViewController
211
            view.delegate = self
212
        }
213
    }
214
 
215
}