将 acceptMouseMovedEvents 用于带有故事板的 SpriteKit 鼠标操作和 Swift

Using acceptsMouseMovedEvents for SpriteKit mouse actions with Storyboards and Swift

我在 Xcode 中使用故事板引用自定义 NSView 创建了一个 SpriteKit 场景。但是,我无法使用 SpriteKit 实现任何 mouseMoved 事件,因为我不知道如何引用程序的 NSWindow 来将其 acceptsMouseMovedEvents 属性 设置为 "true"。

如何在我的 AppDelegate.swift 文件中创建对我的 NSWindow@IBOutlet 引用,以便我可以更改此 属性?

您可以配置一个 NSTrackingArea 对象来跟踪鼠标的移动以及光标何时进入或退出视图。要创建 NSTrackingArea 对象,您需要指定要跟踪鼠标事件的视图区域、将接收鼠标事件消息的所有者以及跟踪发生的时间(例如,在键 window).以下是如何将跟踪区域添加到视图的示例。添加到您的 SKScene 子类,例如 GameScene.swift.

Swift 3 和 4

override func didMove(to view: SKView) {
    // Create a tracking area object with self as the owner (i.e., the recipient of mouse-tracking messages
    let trackingArea = NSTrackingArea(rect: view.frame, options: [.activeInKeyWindow, .mouseMoved], owner: self, userInfo: nil)
    // Add the tracking area to the view
    view.addTrackingArea(trackingArea)
}

// This method will be called when the mouse moves in the view
override func mouseMoved(with theEvent: NSEvent) {
    let location = theEvent.location(in: self)
    print(location)
}

Swift 2

override func didMoveToView(view: SKView) {
    // Create a tracking area object with self as the owner (i.e., the recipient of mouse-tracking messages
    let trackingArea = NSTrackingArea(rect: view.frame, options: NSTrackingAreaOptions.ActiveInKeyWindow | NSTrackingAreaOptions.MouseMoved, owner: self, userInfo: nil)
    // Add the tracking area to the view
    view.addTrackingArea(trackingArea)
}

// This method will be called when the mouse moves in the view
override func mouseMoved(theEvent: NSEvent) {
    let location = theEvent.locationInNode(self)
    println(location)
}

0x141E 的回答更新:

override func didChangeSize(_ oldSize: CGSize) {
    guard let newRect = view?.bounds else {return}

    let options = NSTrackingArea.Options(rawValue: NSTrackingArea.Options.activeInKeyWindow.rawValue | NSTrackingArea.Options.mouseMoved.rawValue)
    let userInfo = ["SKMouseInput": 1]
    let trackingArea = NSTrackingArea(rect: newRect, options: options, owner: self, userInfo: userInfo)
    if let previousTrackingAreas = view?.trackingAreas {
        for area in previousTrackingAreas {
            if let theInfo = area.userInfo {
                if let _ = theInfo["SKMouseInput"]  {
                    view?.removeTrackingArea(area)
                }
            }
        }
    }
    view?.addTrackingArea(trackingArea)
}

此 SKScene 方法覆盖将在初始化后不久调用,将允许不受 window 大小更改的影响,并将清理旧的跟踪区域。请注意,它仍然需要覆盖 mouseMoved。