Search code examples
swiftmacosscenekit

SCNCamera rotation no longer works when changing NSGestureRecognizer


Changing NSClickGestureRecognizer to a NSPanGestureRecognizer in a SceneKit MacOS Game Template app and the camera rotate no longer works.

For example if one generates a new MacOS Game template app and then change the line:

let clickGesture = NSClickGestureRecognizer(target: self, action: #selector(handleClick(_:)))

to:

let clickGesture = NSPanGestureRecognizer(target: self, action: #selector(handleClick(_:)))

Then the rotate camera gesture no longer works.


Solution

  • This is due to the nature of the NSPanGestureRecognizer. In order for the Hit-Test to work for your model, you need to click on the mouse button, then drag it some distance, and then release it. The exact same action is required to pan or orbit the camera when the .allowsCameraControl property is true. Thus, by default, NSPanGestureRecognizer blocks the gestures of the camera controller because the first one has a higher priority in SceneKit. Setting priority is a common practice to avoid conflicts between objects with similar behaviors.

    By default, this gesture recognizer blocks the gestures for the camera:

    let panGesture = NSPanGestureRecognizer(target: self, 
                                            action: #selector(handlePan))
    
    panGesture.buttonMask = 1               // default
    

    To do the opposite, use:

    panGesture.buttonMask = 0
    

    Unlike its counterpart, NSClickGestureRecognizer needs you to simply click (not drag) the model.