I'm trying to make a first person game where moving the mouse changes the camera angle, similar to in Roblox in first person mode or in Minecraft. How to do that? I'm asking how to do basic functionality so there is no code to provide. I just need to know how to hide and lock the cursor position in Swift or more specifically Metal or Cocoa.
You can subclass NSView, add a tracking area for mouse entered and exited, override NSView mouseEntered and mouseExited methods and just hide and unhide the cursor there:
import Cocoa
class HiddenCursorView: NSView {
override func awakeFromNib() {
addTrackingArea(NSTrackingArea(rect: bounds, options: [.activeAlways, .mouseEnteredAndExited], owner: self, userInfo: nil))
}
override func mouseEntered(with event: NSEvent) {
NSCursor.hide()
}
#objc override func mouseExited(with event: NSEvent) {
NSCursor.unhide()
}
}
Related
I'm new to SpriteKit and starting to collect some experience.
What I currently can not understand is how to mix a GameScene with my own code?
So, there is a way to do all manually like this:
class GameScene: SKScene {
override func didMove(to view: SKView) {
//...
}
override func update(_ currentTime: TimeInterval) {
//...
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//...
}
}
And then pass it to my SpriteView:
SpriteView(scene: GameScene())
This is fine, so I can do everything in Swift by code. To use a .sks GameScene file its also easy by using:
SpriteView(scene: SKScene(fileNamed: "MyScene")!)
BUT what I need to do to override the methods in MyScene and access the Sprites I created via the editor?
I found it in the example. I can use the Custom Class property in the .sks file
this probably has something to do with the fact that I am overriding touchesBegan in my custom subclass:
class myCustomButton: UIButton {
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
print("TOUCHES BEGAN OVERRIDE CALLED")
originalColor = self.backgroundColor ?? .red
self.backgroundColor = .white
self.animateScale()
setNeedsDisplay()
}
//...
}
touchesEnded is similarly overridden, and both of these functions are called and print debug statements to console on button press. however, the code in the button pressed IBAction from my view controller is never run
#IBAction func nextButtonPressed(_ sender: Any) {
print("this is never executed")
//...
}
I have double checked that the IBOutlet is not broken and changed the (_ sender: Any) to (_ sender: AnyObject) both to no avail. any insights would be appreciated
ah ok, figured it out. in my custom button initializer I added a subview which, by default, had userInteractionEnabled set to true. setting userInteractionEnabled = true on my custom button object and userInteractionEnabled = false on my view before adding it as a subview allows my custom button to capture the touch and handle it properly rather than the view capturing the touch
Instead of overriding touchesBegan, try overriding the sendAction function of your UIButton:
override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
super.sendAction(action, to: target, for: event)
//Insert your code here
}
I have a NSViewController/NSView with a SpriteKit Scene filling the whole view. Here are the events I need to handle:
override func mouseDown(with event: NSEvent) {
override func rightMouseDown(with event: NSEvent) {
override func otherMouseDown(with event: NSEvent) {
override func mouseDragged(with event: NSEvent) {
override func rightMouseDragged(with event: NSEvent) {
override func otherMouseDragged(with event: NSEvent) {
But they are very inconsistent, and I'm not able to get rightMouseDragged working at all.
mouseDown works fine in the SKScene
rightMouseDown works fine in the SKScene
otherMouseDown had to be implemented in the viewController and passed on to the scene
mouseDragged worked fine in the SKScene
rightMouseDragged is not working at all
otherMouseDragged had to be implemented in the viewController and passed on to the scene
My main need is to fix rightMouseDragged. It doesn't receive any dragged events either in the view controller or the scene controller.
Ok, I don't understand why, but the rightMouseDragged was being delivered to the SKView. So here's where I needed to implement my event handlers:
mouseDown in the SKScene
rightMouseDown in the SKScene
otherMouseDown in the viewController and passed on to the scene
mouseDragged in the SKScene
rightMouseDragged in the SKView and be passed to the scene
otherMouseDragged in the viewController and passed on to the scene
I working with swift 4 for osx.
I have a view based NSTableView with 4 columns.
the cells in each column has got the same custom cell class:
class CustomCell: NSTableCellView {
#IBOutlet weak var btnInfo: NSButton!
private var trackingArea: NSTrackingArea!
override func awakeFromNib() {
super.awakeFromNib()
self.trackingArea = NSTrackingArea(
rect: bounds,
options: [.activeAlways, .mouseEnteredAndExited],
owner: self,
userInfo: nil
)
addTrackingArea(trackingArea)
}
override func mouseEntered(with event: NSEvent) {
super.mouseEntered(with: event)
btnInfo.isHidden = false
}
override func mouseExited(with event: NSEvent) {
super.mouseExited(with: event)
btnInfo.isHidden = true
}
}
Now i would like to realize the following situation:
if the user goes with the mouse over a row, the btnInfo should be visible and hide again, it the mouse leaves the row.
problem is (with the code above), that my apps crashes, because btnInfo will be nil
Logically: Because this button is only in column 4 available.
in all other columns it will be nil.
how can i solve this?
The solution is to add an NSTrackingArea to the entire view, not the individual cells. Then on the entire table view, you can get the mouse move events, take the NSEvent's locationInWindow. Then NSTableView has a method row(at point: NSPoint) -> Int that can get you the current row that should be highlighting the button.
I am writing an application for OSX in Swift and I am looking for a good way to catch events on a NSControl.
Obviously, I searched but the informations I found are often unclear or old.
In my case, I would like to catch several events on a NSTextField (key up, text changed, focus lost,...).
When I push on “Enter” in the NSTextField, it sends an action. Maybe is there a way to send an action when I click or write in the NSTextField?
You can subclass NSTextField and override textDidChange for text change, textDidEndEditing for lost focus and keyUp method for key up. Try like this:
import Cocoa
class CustomTextField: NSTextField {
override func viewWillMove(toSuperview newSuperview: NSView?) {
// customize your field here
frame = newSuperview?.frame.insetBy(dx: 50, dy: 50) ?? frame
}
override func textDidChange(_ notification: Notification) {
Swift.print("textDidChange")
}
override func textDidEndEditing(_ notification: Notification) {
Swift.print("textDidEndEditing")
}
override func keyUp(with event: NSEvent) {
Swift.print("keyUp")
}
}
View Controller sample Usage:
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textField = CustomTextField()
view.addSubview(textField)
}
}
Sample