简体   繁体   中英

How to set a custom cursor in an SKScene? (XCode, Swift4, Spritekit)

I want to use a custom cursor for my project. Now, using one of the system cursors in XCode is no biggie, i simply call:

NSCursor.crosshair() .set() 

(just an example)

This works fine but then I try to set my custom cursor the following way: (inside didMove: to View or inside sceneDidLoad(), it doesn't seem to matter which.)

let image = NSImage(named: "hand1.png")
let spot = NSPoint(x: 4, y: 8)
let customCursor = NSCursor(image: image!, hotSpot: spot)
self.view!.addCursorRect(self.frame, cursor:customCursor)

When I try to build I get an error in line 3 saying "unexpectedly found nil".

So then I changed the code to this:

let image = NSImage(byReferencingFile: "hand1.png")
let spot = NSPoint(x: 4, y: 8)
let customCursor = NSCursor(image: image!, hotSpot: spot)
self.view!.addCursorRect(self.frame, cursor: customCursor)

Now the project builds, but nothing happens. The cursor doesn't change.

I also tried these lines here:

NSCursor.init(image: image!, hotSpot: spot)
NSCursor.set(customCursor)()

Again, the project builds but the cursor doesn't change. What am I doing wrong here?

I tried to follow all the guidelines i could find but the Apple Documentation on cursor events is not much help since its heavily outdated and mouse related topics are generally very rare since most stuff is about ios. Thanks in advance for your help.

From the NSImage(byReferencingFile:) docs,

This method initializes the image object lazily. It does not actually open the specified file or create any image representations from its data until an app attempts to draw the image or request information about it.

As a result, the image is not loaded from the file when the addCursorRect() method is called. In fact, the image size is (height:0, width:0) as shown in the following.

if let image = NSImage(byReferencingFile:"cursorImage.png") {
    print("\(image.size)")
}

// (0.0, 0.0)

I suggest you use NSImage(named:) to create the image from a file:

if let image = NSImage(named:NSImage.Name("cursorImage.png")) {
    print("\(image.size)")
}

// (32.0, 32.0)

Also, addCursorRect(image:,hotSpot:) should only be called from the resetCursorRects() method. From the docs,

This method is intended to be invoked only by the resetCursorRects() method. If invoked in any other way, the resulting cursor rectangle will be discarded the next time the view's cursor rectangles are rebuilt.

addCursorRect() is an instance method of NSView and, for SpriteKit, the view is an SKView which inherits from NSView . Accordingly, you could subclass SKView, override the subclass's addCursorRect() method, and change the view's class (to our SKView subclass) in the Storyboard.

Alternatively, you can accomplish this by extending SKView and overriding the resetCursorRects() method. For example,

For Xcode 9.3

extension SKView {
    override open func resetCursorRects() {
        if let image = NSImage(named:NSImage.Name(rawValue:"cursorImage.png")) {
            let spot = NSPoint(x: 0, y: 0)
            let customCursor = NSCursor(image: image, hotSpot: spot)
            addCursorRect(visibleRect, cursor:customCursor)
        }
    }
}

For Xcode 9.2

extension SKView {
    override open func resetCursorRects() {
        if let image = NSImage(named:NSImage.Name("cursorImage.png")) {
            let spot = NSPoint(x: 0, y: 0)
            let customCursor = NSCursor(image: image, hotSpot: spot)
            addCursorRect(visibleRect, cursor:customCursor)
        }
    }
}

For older Xcode versions:

extension SKView {
    override open func resetCursorRects() {
        if let path = Bundle.main.path(forResource: "cursorImage", ofType: "png") {
            if let image = NSImage(contentsOfFile:path) {
                let spot = NSPoint(x: 0, y: 0)
                let customCursor = NSCursor(image: image, hotSpot: spot)
                addCursorRect(visibleRect, cursor:customCursor)
            }
        }
    }
}

Project Navigator with cursor image highlighted.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM