|
/// Make the ViewController conform to this protocol |
|
/// |
|
protocol SceneKitViewController { |
|
var sceneKitView: SceneKitView! { get } |
|
} |
|
|
|
/// Make the ViewController conform to this protocol too |
|
/// |
|
protocol SpriteSceneNavigationDelegate { |
|
func present(_ scene: BaseSpriteScene) |
|
func transition(to scene: BaseSpriteScene, completion: (() -> Void)?) |
|
func willTransition(from srcScene: BaseSpriteScene?, to dstScene: BaseSpriteScene) |
|
func didTransition(from srcScene: BaseSpriteScene?, to dstScene: BaseSpriteScene) |
|
} |
|
|
|
/// All SpriteKit scenes must subclass this. To transition to another scene, |
|
/// call `navigationDelegate.transtion(to:completion:) |
|
/// |
|
class BaseSpriteKitScene: SKScene { |
|
weak var navigationDelegate: SpriteSceneNavigationDelegate? |
|
} |
|
|
|
/// Default implementation of the transition methods for an object that |
|
/// conforms to both `SpriteSceneNavigationDelegate` and `SceneKitViewController` |
|
/// |
|
extension SpriteSceneNavigationDelegate where Self: SceneKitViewController { |
|
|
|
/// Presents a sprite scene immediately. |
|
func present(_ scene: BaseSpriteScene) { |
|
sceneKitView.overlaySKScene = scene |
|
scene.navigationDelegate = self |
|
} |
|
|
|
/// Transitions into a new sprite scene gradually. |
|
func transition(to scene: BaseSpriteScene, completion: (() -> Void)? = nil) { |
|
let source = sceneKitView?.overlaySKScene as? BaseSpriteScene |
|
|
|
willTransition(from: source, to: scene) |
|
sceneKitView.overlaySKScene?.run(.fadeAlpha(to: 0, duration: 0.25)) { [unowned self] in |
|
scene.alpha = 0 |
|
self.sceneKitView.overlaySKScene = scene |
|
scene.run(.fadeAlpha(to: 1, duration: 0.25)) { [unowned self] in |
|
self.didTransition(from: source, to: scene) |
|
completion?() |
|
} |
|
} |
|
} |
|
} |
|
|