zeeple
zeeple

Reputation: 5617

Making an SKLabelNode Ignore Touches

In Swift and SpriteKit, you can designate an object as "isUserInteractionEnabled=false". Confusingly, this does not mean that the object will ignore touches and let those touches pass through to nodes below it.

The way I built SpriteKit apps it is very common for me to create a node (like a SKShapeNode or an SKSpriteNode) and then slap a label on it. What I want is for the label to ignore touches and let those touches pass through to the node behind it but I am failing to understand how this is done, if "isUserInteractionEnable" is not the ticket.

Any suggestions? Here is a sample label that receives touches but should not:

class MenuButton: SKShapeNode {

    /*  The MenuBar will have as children nine buttons of two types.  Dialog Springers and SubMenu Droppers  */

    // MARK: - Class Variables

    var title = "Button"
    var menu = SKShapeNode()

    let buttonLabel = SKLabelNode(fontNamed: devFont4)

    init(title: String)
    {
        super.init()

        isUserInteractionEnabled = true

        self.title = title
        self.name = "\(title) Menu Button"
        let btnLen = title.count * 10 + 16

        let menuSize = CGSize(width: btnLen, height: 32)
        menu = SKShapeNode(rectOf: menuSize)
        addChild(menu)

        menu.fillColor = .clear
        menu.strokeColor = .clear
        menu.lineWidth = 0

        menu.zPosition = 501

        // Add Label
        let letterHeight: CGFloat = 22
        buttonLabel.text = title
        buttonLabel.name = "\(title) Label"
        buttonLabel.fontSize = letterHeight
        buttonLabel.fontColor = .black
        buttonLabel.zPosition = 502
        buttonLabel.position = CGPoint(x: 0, y: Int(-letterHeight/2) + 2)
        buttonLabel.isUserInteractionEnabled = false
        addChild(buttonLabel)

    }
}

Upvotes: 1

Views: 300

Answers (2)

Knight0fDragon
Knight0fDragon

Reputation: 16827

In Swift and SpriteKit, you can designate an object as "isUserInteractionEnabled=false". Confusingly, this does not mean that the object will ignore touches and let those touches pass through to nodes below it.

That is incorrect, isUserInteractionEnabled=false means that the object will ignore touches and let touches pass through it.

You have a completely different problem. In your code, your main menu does not have a size, so it is passing through your label, inner menu node, and outer menu node, hitting your scene.

Upvotes: 1

E.Coms
E.Coms

Reputation: 11531

There is only one first responder to receive the touches event. The isUserInteractionEnabled is used to decide which one is called first even Both are enabled. Play the following codes and you can have a feeling what's going on.

class Button: SKLabelNode{
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("button")
}
}

class MenuButton: SKShapeNode {

/*  The MenuBar will have as children nine buttons of two types.  Dialog Springers and SubMenu Droppers  */

// MARK: - Class Variables

var title = "Button"
var menu = SKShapeNode()

let buttonLabel = Button.init()

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("hit")
}

init(title: String)
{
    super.init()

    isUserInteractionEnabled = true




    self.title = title
    self.name = "\(title) Menu Button"
    let btnLen = title.count * 10 + 16

    let menuSize = CGSize(width: btnLen, height: 32)
    menu = SKShapeNode(rectOf: menuSize)
    addChild(menu)

    menu.fillColor = .green
    menu.strokeColor = .clear
    menu.lineWidth = 0

    menu.zPosition = 501
    menu.isUserInteractionEnabled = false
    // Add Label
    let letterHeight: CGFloat = 122

    buttonLabel.text = title
    buttonLabel.name = "\(title) Label"
    buttonLabel.fontSize = letterHeight
    buttonLabel.fontColor = .black
    buttonLabel.zPosition = 502
    buttonLabel.position = CGPoint(x: 0, y: Int(-letterHeight/2) + 2)
    buttonLabel.isUserInteractionEnabled = true
    addChild(buttonLabel)

     self.path = UIBezierPath.init(rect:self.calculateAccumulatedFrame()).cgPath
    self.fillColor = UIColor.red

 }

 required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
} 

Upvotes: 1

Related Questions