Search code examples
swiftmetaluisegmentedcontrol

Overlay a UISegmentedControl over a SKSpriteNode


I'm currently using Metal to create a game board with floating balloons; each balloon is a SKSpriteNode with an image of a balloon attached. The user touches and drags the balloon to a second balloon, merging the two. Exactly how they get merged is based on input from the user. I have a UISegmentedControl that pops up where the user selects one of four responses and the merge occurs. Currently, the UISegmentedControl pops up in the middle of the game board; however, I would like it to overlay on top of the first balloon instead.

I have tried this once the two balloons touch each other:

bubble1.physicsBody!.velocity = CGVector(dx: 0, dy: 0) // Stopping the balloon

requestView.frame.origin.x = bubble1.position.x
requestView.frame.origin.y = bubble1.position.y

Where requestView is a UIView (with the same dimensions of the balloon) with various subviews (including the UISegmentedControl) and bubble1 is the SKSpriteNode (balloon). However, when I add the requestView as a subview of the game board, it does not overlay on top of the SKSpriteNode (bubble1). In fact, each time I try it, it doesn't even seem to appear in the same space relative to the location of the bubble1. Any thoughts on what I might be doing wrong? Thanks!


Solution

  • UIKit uses screen coordinates while Metal uses clip-spaced coordinates.

    Here are functions that convert UIKit coordinates to Metal:

    Convert screen coordinates to Metal's Normalized Device Coordinates

    You will need to do the inverse to convert Metal to UIKit. Something like this:

    func convertToScreenCoordinates(clipPos: CGPoint, viewSize: CGSize) -> CGPoint {
        let screenX = (clipPos.x + 1.0) * 0.5 * viewSize.width
        let screenY = (-clipPos.y + 1.0) * 0.5 * viewSize.height
        return CGPoint(x: screenX, y: screenY)
    }
    

    This may be helpful too: translate between NSView and MTL drawable coordinates