Created
February 14, 2019 04:20
-
-
Save brynbodayle/46a6baeb575070f6e9bfc48371c74d23 to your computer and use it in GitHub Desktop.
SKScene UserInteraction Bug Fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Original Objective C version: https://gist.github.com/bobmoff/7110052 | |
// | |
// Fix SpriteKit's SKNode bug on iOS 7 & 8: nodes capture touch events | |
// even when userInteractionEnabled is false and the nodes are hidden. | |
// | |
// Details: | |
// http://stackoverflow.com/questions/19511334/sprite-with-userinteractionenabled-set-to-yes-does-not-receive-touches-when-cove | |
// | |
// How to use: | |
// Use SKSceneWithUserInteractionBugfix class in place of SKScene. | |
// | |
import SpriteKit | |
extension SKNode { | |
func nodeDepthPriority() -> String { | |
var code = "" | |
var currentNode = self | |
while let parent = currentNode.parent { | |
var idx = 0 | |
for obj in parent.children { | |
if obj == currentNode { | |
code = NSString(format: "%03d%@", idx, code) as String | |
break | |
} | |
idx += 1 | |
} | |
currentNode = parent | |
} | |
return code | |
} | |
} | |
extension SKScene { | |
func nodeWithHighestPriority(_ touches: Set<UITouch>) -> SKNode? { | |
// Only allow touches to be receieved by nodes with userInteractionEnabled, and only the one with the highest touch priority | |
guard let touch = touches.first else { return nil } | |
let touchLocation = touch.location(in: self) | |
let touchedNodes = nodes(at: touchLocation) | |
var nodeToTouch: SKNode! | |
for node in touchedNodes { | |
if node.isUserInteractionEnabled && !node.isHidden && node.alpha > 0 { | |
if nodeToTouch == nil { | |
nodeToTouch = node | |
} else if node.parent == nodeToTouch.parent && node.zPosition > nodeToTouch.zPosition { | |
nodeToTouch = node | |
} else if node.parent == nodeToTouch.parent && node.zPosition == nodeToTouch.zPosition && nodeToTouch.nodeDepthPriority().compare(node.nodeDepthPriority()) == .orderedAscending { | |
nodeToTouch = node | |
} else if node.parent != nodeToTouch.parent && nodeToTouch.nodeDepthPriority().compare(node.nodeDepthPriority()) == .orderedAscending { | |
nodeToTouch = node | |
} | |
} | |
} | |
return nodeToTouch | |
} | |
} | |
extension SKScene { | |
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { | |
let nodeToTouch = nodeWithHighestPriority(touches) | |
nodeToTouch?.touchesBegan(touches, with: event) | |
} | |
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { | |
let nodeToTouch = nodeWithHighestPriority(touches) | |
nodeToTouch?.touchesEnded(touches, with: event) | |
} | |
open override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) { | |
guard let touches = touches else { return } | |
let nodeToTouch = nodeWithHighestPriority(touches) | |
nodeToTouch?.touchesCancelled(touches, with: event) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment