Added Peek & Pop for previewing games

This commit is contained in:
Riley Testut 2015-12-12 14:08:19 -08:00
parent 925fb9454d
commit 8863e8f3d0
4 changed files with 71 additions and 16 deletions

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="wKV-3d-NIY"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="wKV-3d-NIY">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
<capability name="Segues with Peek and Pop" minToolsVersion="7.1"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--Navigation Controller--> <!--Navigation Controller-->
@ -79,7 +80,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tmn-gd-5UN"> <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tmn-gd-5UN">
<rect key="frame" x="0.0" y="0.0" width="600" height="556"/> <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<animations/> <animations/>
<connections> <connections>
<segue destination="tpK-ou-yEA" kind="embed" id="cjU-nW-cHY"/> <segue destination="tpK-ou-yEA" kind="embed" id="cjU-nW-cHY"/>
@ -134,7 +135,10 @@
</view> </view>
<animations/> <animations/>
<connections> <connections>
<segue destination="hx4-Ze-0Jw" kind="presentation" id="flc-7j-hej"/> <segue destination="hx4-Ze-0Jw" kind="presentation" id="Ila-yL-N8w">
<segue key="commit" inheritsFrom="parent" id="0B7-vE-k6Z"/>
<segue key="preview" inheritsFrom="commit" id="Jd4-q3-dNr"/>
</segue>
</connections> </connections>
</collectionViewCell> </collectionViewCell>
</cells> </cells>
@ -263,4 +267,7 @@
<resources> <resources>
<image name="Settings_Button" width="22" height="22"/> <image name="Settings_Button" width="22" height="22"/>
</resources> </resources>
<inferredMetricsTieBreakers>
<segue reference="Ila-yL-N8w"/>
</inferredMetricsTieBreakers>
</document> </document>

View File

@ -15,10 +15,15 @@ class EmulationViewController: UIViewController
{ {
//MARK: - Properties - //MARK: - Properties -
/** Properties **/ /** Properties **/
/// Should only be set when preparing for segue. Otherwise, should be considered immutable
var game: Game! { var game: Game! {
didSet didSet
{ {
guard oldValue != game else { return }
self.emulatorCore = SNESEmulatorCore(game: game) self.emulatorCore = SNESEmulatorCore(game: game)
self.preferredContentSize = self.emulatorCore.preferredRenderingSize
} }
} }
private(set) var emulatorCore: EmulatorCore! private(set) var emulatorCore: EmulatorCore!
@ -29,16 +34,28 @@ class EmulationViewController: UIViewController
@IBOutlet private var controllerViewHeightConstraint: NSLayoutConstraint! @IBOutlet private var controllerViewHeightConstraint: NSLayoutConstraint!
private var isPreviewing: Bool {
guard let presentationController = self.presentationController else { return false }
return NSStringFromClass(presentationController.dynamicType).containsString("PreviewPresentation")
}
//MARK: - Initializers - //MARK: - Initializers -
/** Initializers **/ /** Initializers **/
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
super.init(coder: aDecoder) super.init(coder: aDecoder)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("updateControllers"), name: ExternalControllerDidConnectNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("updateControllers"), name: ExternalControllerDidConnectNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("updateControllers"), name: ExternalControllerDidDisconnectNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("updateControllers"), name: ExternalControllerDidDisconnectNotification, object: nil)
} }
deinit
{
// To ensure the emulation stops when cancelling a peek/preview gesture
self.emulatorCore.stopEmulation()
}
//MARK: - Overrides //MARK: - Overrides
/** Overrides **/ /** Overrides **/
@ -48,6 +65,10 @@ class EmulationViewController: UIViewController
{ {
super.viewDidLoad() super.viewDidLoad()
// Set this to 0 now and update it in viewDidLayoutSubviews to ensure there are never conflicting constraints
// (such as when peeking and popping)
self.controllerViewHeightConstraint.constant = 0
self.gameView.backgroundColor = UIColor.clearColor() self.gameView.backgroundColor = UIColor.clearColor()
self.emulatorCore.addGameView(self.gameView) self.emulatorCore.addGameView(self.gameView)
@ -66,12 +87,12 @@ class EmulationViewController: UIViewController
self.emulatorCore.startEmulation() self.emulatorCore.startEmulation()
} }
override func viewDidLayoutSubviews() override func viewDidLayoutSubviews()
{ {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
if Settings.localControllerPlayerIndex != nil && self.controllerView.intrinsicContentSize() != CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric) if Settings.localControllerPlayerIndex != nil && self.controllerView.intrinsicContentSize() != CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric) && !self.isPreviewing
{ {
let scale = self.view.bounds.width / self.controllerView.intrinsicContentSize().width let scale = self.view.bounds.width / self.controllerView.intrinsicContentSize().width
self.controllerViewHeightConstraint.constant = self.controllerView.intrinsicContentSize().height * scale self.controllerViewHeightConstraint.constant = self.controllerView.intrinsicContentSize().height * scale
@ -80,7 +101,6 @@ class EmulationViewController: UIViewController
{ {
self.controllerViewHeightConstraint.constant = 0 self.controllerViewHeightConstraint.constant = 0
} }
} }
override func prefersStatusBarHidden() -> Bool override func prefersStatusBarHidden() -> Bool
@ -121,6 +141,21 @@ class EmulationViewController: UIViewController
self.view.setNeedsLayout() self.view.setNeedsLayout()
} }
//MARK: - 3D Touch -
/// 3D Touch
override func previewActionItems() -> [UIPreviewActionItem]
{
let presentingViewController = self.presentingViewController
let launchGameAction = UIPreviewAction(title: NSLocalizedString("Launch \(self.game.name)", comment: ""), style: .Default) { (action, viewController) in
// Delaying until next run loop prevents self from being dismissed immediately
dispatch_async(dispatch_get_main_queue()) {
presentingViewController?.presentViewController(viewController, animated: true, completion: nil)
}
}
return [launchGameAction]
}
} }
//MARK: - <GameControllerReceiver> - //MARK: - <GameControllerReceiver> -

View File

@ -13,6 +13,8 @@ import DeltaCore
class GamesCollectionViewController: UICollectionViewController class GamesCollectionViewController: UICollectionViewController
{ {
weak var segueHandler: UIViewController?
var gameCollection: GameCollection! { var gameCollection: GameCollection! {
didSet didSet
{ {
@ -21,7 +23,7 @@ class GamesCollectionViewController: UICollectionViewController
} }
} }
private let dataSource = GameCollectionViewDataSource() let dataSource = GameCollectionViewDataSource()
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
@ -50,7 +52,7 @@ class GamesCollectionViewController: UICollectionViewController
super.viewWillAppear(animated) super.viewWillAppear(animated)
} }
override func didReceiveMemoryWarning() override func didReceiveMemoryWarning()
{ {
super.didReceiveMemoryWarning() super.didReceiveMemoryWarning()
@ -62,12 +64,7 @@ class GamesCollectionViewController: UICollectionViewController
// In a storyboard-based application, you will often want to do a little preparation before navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{ {
guard let viewController = segue.destinationViewController as? EmulationViewController else { return } self.segueHandler?.prepareForSegue(segue, sender: sender)
let indexPath = self.collectionView?.indexPathsForSelectedItems()?.first
let game = self.dataSource.fetchedResultsController.objectAtIndexPath(indexPath!) as! Game
viewController.game = game
} }
// MARK: - Collection View - // MARK: - Collection View -

View File

@ -111,6 +111,21 @@ class GamesViewController: UIViewController
gamePickerController.delegate = self gamePickerController.delegate = self
self.presentGamePickerController(gamePickerController, animated: true, completion: nil) self.presentGamePickerController(gamePickerController, animated: true, completion: nil)
} }
// MARK: - Navigation -
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
guard let sourceViewController = segue.sourceViewController as? GamesCollectionViewController else { return }
guard let destinationViewController = segue.destinationViewController as? EmulationViewController else { return }
guard let cell = sender as? UICollectionViewCell else { return }
let indexPath = sourceViewController.collectionView?.indexPathForCell(cell)
let game = sourceViewController.dataSource.fetchedResultsController.objectAtIndexPath(indexPath!) as! Game
destinationViewController.game = game
}
} }
private extension GamesViewController private extension GamesViewController
@ -133,6 +148,7 @@ private extension GamesViewController
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController
viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
viewController.segueHandler = self
return viewController return viewController
} }