diff --git a/Delta/Base.lproj/Main.storyboard b/Delta/Base.lproj/Main.storyboard index 006350f..fb4bc05 100644 --- a/Delta/Base.lproj/Main.storyboard +++ b/Delta/Base.lproj/Main.storyboard @@ -1,7 +1,8 @@ - + - + + @@ -79,7 +80,7 @@ - + @@ -134,7 +135,10 @@ - + + + + @@ -263,4 +267,7 @@ + + + diff --git a/Delta/Emulation/EmulationViewController.swift b/Delta/Emulation/EmulationViewController.swift index bd8e303..cd04396 100644 --- a/Delta/Emulation/EmulationViewController.swift +++ b/Delta/Emulation/EmulationViewController.swift @@ -15,10 +15,15 @@ class EmulationViewController: UIViewController { //MARK: - Properties - /** Properties **/ + + /// Should only be set when preparing for segue. Otherwise, should be considered immutable var game: Game! { didSet { + guard oldValue != game else { return } + self.emulatorCore = SNESEmulatorCore(game: game) + self.preferredContentSize = self.emulatorCore.preferredRenderingSize } } private(set) var emulatorCore: EmulatorCore! @@ -29,16 +34,28 @@ class EmulationViewController: UIViewController @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 - /** Initializers **/ required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - + NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("updateControllers"), name: ExternalControllerDidConnectNotification, 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 /** Overrides **/ @@ -48,6 +65,10 @@ class EmulationViewController: UIViewController { 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.emulatorCore.addGameView(self.gameView) @@ -66,12 +87,12 @@ class EmulationViewController: UIViewController self.emulatorCore.startEmulation() } - + override func 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 self.controllerViewHeightConstraint.constant = self.controllerView.intrinsicContentSize().height * scale @@ -80,7 +101,6 @@ class EmulationViewController: UIViewController { self.controllerViewHeightConstraint.constant = 0 } - } override func prefersStatusBarHidden() -> Bool @@ -121,6 +141,21 @@ class EmulationViewController: UIViewController 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: - - diff --git a/Delta/Game Selection/GamesCollectionViewController.swift b/Delta/Game Selection/GamesCollectionViewController.swift index 63b9515..5a37656 100644 --- a/Delta/Game Selection/GamesCollectionViewController.swift +++ b/Delta/Game Selection/GamesCollectionViewController.swift @@ -13,6 +13,8 @@ import DeltaCore class GamesCollectionViewController: UICollectionViewController { + weak var segueHandler: UIViewController? + var gameCollection: GameCollection! { didSet { @@ -21,7 +23,7 @@ class GamesCollectionViewController: UICollectionViewController } } - private let dataSource = GameCollectionViewDataSource() + let dataSource = GameCollectionViewDataSource() required init?(coder aDecoder: NSCoder) { @@ -50,7 +52,7 @@ class GamesCollectionViewController: UICollectionViewController super.viewWillAppear(animated) } - + override func 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 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { - guard let viewController = segue.destinationViewController as? EmulationViewController else { return } - - let indexPath = self.collectionView?.indexPathsForSelectedItems()?.first - let game = self.dataSource.fetchedResultsController.objectAtIndexPath(indexPath!) as! Game - - viewController.game = game + self.segueHandler?.prepareForSegue(segue, sender: sender) } // MARK: - Collection View - diff --git a/Delta/Game Selection/GamesViewController.swift b/Delta/Game Selection/GamesViewController.swift index 1840364..82a24cc 100644 --- a/Delta/Game Selection/GamesViewController.swift +++ b/Delta/Game Selection/GamesViewController.swift @@ -111,6 +111,21 @@ class GamesViewController: UIViewController gamePickerController.delegate = self 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 @@ -133,6 +148,7 @@ private extension GamesViewController let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("gamesCollectionViewController") as! GamesCollectionViewController viewController.gameCollection = self.fetchedResultsController.objectAtIndexPath(indexPath) as! GameCollection viewController.collectionView?.contentInset.top = self.topLayoutGuide.length + viewController.segueHandler = self return viewController }