David James
David James

Reputation: 2466

How to convert points between UIViews and SKNodes

I would like to convert CGPoint between UIView and SKNode, similarly to how you can convert between views/layers via their respective convert(_:to/from:) methods.

What is the correct way to do this?

Upvotes: 3

Views: 698

Answers (2)

Knight0fDragon
Knight0fDragon

Reputation: 16827

All you need to do is scene.convertPoint(toView:pointOnScene)

If you need to convert a node that is not a child of the scene but a descendent of the scene , you do:

let absolutePosition = node.convert(node.position,toNode:node.scene)
scene.convertPoint(toView: absolutePosition)

A nice little extension to use:

extension SKNode {

    /// Find point in node relative to it's containing SKView
    /// so that it can be further converted relative to other views.
    func pointInContainingView(_ point:CGPoint) -> (SKView, CGPoint)? {

        guard let scene = scene, let view = scene.view else {
            return nil
        }
        let pointInView.convertPoint(toView: convert(point,toNode:scene))
        return (view, pointInView)
    }
}

Upvotes: 1

David James
David James

Reputation: 2466

Here is what I came up with:

extension SKNode {

    /// Find point in node relative to it's containing SKView
    /// so that it can be further converted relative to other views.
    func pointInContainingView(_ point:CGPoint) -> (SKView, CGPoint)? {

        guard let scene = scene, let view = scene.view else {
            return nil
        }
        // Invert Y to match view coordinate system.
        let invertedY = CGPoint(x: point.x, y: -point.y)

        // Get the point in it's containing scene.
        let pointInScene = convert(invertedY, from: scene)

        // Get the resulting point in the containing SKView
        let pointInView = view.convert(pointInScene, from: scene)

        return (view, pointInView)
    }
}

Used like this:

// view/node

let origin = node.frame.origin

if let (nodeView, point) = node.parent?.pointInContainingView(origin) {
    let converted = nodeView.convert(point, from:view)
}

Upvotes: 4

Related Questions