Refactors previewing GameViewController logic into new PreviewGameViewController
This commit is contained in:
parent
b017be6368
commit
3d16fed35a
@ -1 +1 @@
|
||||
Subproject commit d9b61b60c23286a4758bab06ed4a89de641f2628
|
||||
Subproject commit d4895367427ffed6ef1fd04e60868cf799fb3371
|
||||
@ -13,6 +13,8 @@
|
||||
BF090CF41B490D8300DCAB45 /* UIDevice+Vibration.m in Sources */ = {isa = PBXBuildFile; fileRef = BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */; };
|
||||
BF0CDDAD1C8155D200640168 /* LoadImageOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0CDDAC1C8155D200640168 /* LoadImageOperation.swift */; };
|
||||
BF107EC41BF413F000E0C32C /* GamesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF107EC31BF413F000E0C32C /* GamesViewController.swift */; };
|
||||
BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF13A7551D5D29B0000BB055 /* PreviewGameViewController.swift */; };
|
||||
BF13A7581D5D2FD9000BB055 /* EmulatorCore+Cheats.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF13A7571D5D2FD9000BB055 /* EmulatorCore+Cheats.swift */; };
|
||||
BF172AEB1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF172AEA1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift */; };
|
||||
BF1FB1861C5EE643007E2494 /* SaveState.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1FB1831C5EE643007E2494 /* SaveState.swift */; };
|
||||
BF27CC8E1BC9FEA200A20D89 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF6BB2451BB73FE800CCF94A /* Assets.xcassets */; };
|
||||
@ -99,6 +101,8 @@
|
||||
BF090CF31B490D8300DCAB45 /* UIDevice+Vibration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+Vibration.m"; sourceTree = "<group>"; };
|
||||
BF0CDDAC1C8155D200640168 /* LoadImageOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoadImageOperation.swift; path = Components/LoadImageOperation.swift; sourceTree = "<group>"; };
|
||||
BF107EC31BF413F000E0C32C /* GamesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesViewController.swift; sourceTree = "<group>"; };
|
||||
BF13A7551D5D29B0000BB055 /* PreviewGameViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewGameViewController.swift; sourceTree = "<group>"; };
|
||||
BF13A7571D5D2FD9000BB055 /* EmulatorCore+Cheats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EmulatorCore+Cheats.swift"; sourceTree = "<group>"; };
|
||||
BF172AEA1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Conveniences.swift"; sourceTree = "<group>"; };
|
||||
BF1FB1831C5EE643007E2494 /* SaveState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveState.swift; sourceTree = "<group>"; };
|
||||
BF27CC861BC9E3C600A20D89 /* Delta.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Delta.entitlements; sourceTree = "<group>"; };
|
||||
@ -189,6 +193,7 @@
|
||||
BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */,
|
||||
BF7AE8091C2E8C7600B1B5BC /* UIColor+Delta.swift */,
|
||||
BFCEA67D1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift */,
|
||||
BF13A7571D5D2FD9000BB055 /* EmulatorCore+Cheats.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -412,6 +417,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BF63BDE91D389EEB00FCB040 /* GameViewController.swift */,
|
||||
BF13A7551D5D29B0000BB055 /* PreviewGameViewController.swift */,
|
||||
);
|
||||
path = Emulation;
|
||||
sourceTree = "<group>";
|
||||
@ -573,6 +579,7 @@
|
||||
BF7AE8241C2E984300B1B5BC /* GridCollectionViewLayout.swift in Sources */,
|
||||
BF1FB1861C5EE643007E2494 /* SaveState.swift in Sources */,
|
||||
BFA0D1271D3AE1F600565894 /* GameViewController.swift in Sources */,
|
||||
BF13A7581D5D2FD9000BB055 /* EmulatorCore+Cheats.swift in Sources */,
|
||||
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */,
|
||||
BFB141181BE46934004FBF46 /* GameCollectionViewDataSource.swift in Sources */,
|
||||
BFFC46201D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift in Sources */,
|
||||
@ -605,6 +612,7 @@
|
||||
BF0CDDAD1C8155D200640168 /* LoadImageOperation.swift in Sources */,
|
||||
BF107EC41BF413F000E0C32C /* GamesViewController.swift in Sources */,
|
||||
BF172AEB1C68986300C26774 /* NSManagedObjectContext+Conveniences.swift in Sources */,
|
||||
BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */,
|
||||
BFCEA67E1D56FF640061A534 /* UIViewControllerContextTransitioning+Conveniences.swift in Sources */,
|
||||
BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */,
|
||||
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,
|
||||
|
||||
@ -39,19 +39,10 @@ class GameViewController: DeltaCore.GameViewController
|
||||
self.emulatorCore?.removeObserver(self, forKeyPath: #keyPath(EmulatorCore.state), context: &kvoContext)
|
||||
}
|
||||
didSet {
|
||||
guard let emulatorCore = self.emulatorCore else { return }
|
||||
self.preferredContentSize = emulatorCore.preferredRenderingSize
|
||||
|
||||
emulatorCore.addObserver(self, forKeyPath: #keyPath(EmulatorCore.state), options: [.old], context: &kvoContext)
|
||||
self.emulatorCore?.addObserver(self, forKeyPath: #keyPath(EmulatorCore.state), options: [.old], context: &kvoContext)
|
||||
}
|
||||
}
|
||||
|
||||
// If non-nil, will override the default preview action items returned in previewActionItems()
|
||||
var overridePreviewActionItems: [UIPreviewActionItem]?
|
||||
|
||||
// Set to true to handle automatically updating auto save state
|
||||
var updatesAutoSaveState = false
|
||||
|
||||
//MARK: - Private Properties -
|
||||
private var pauseViewController: PauseViewController?
|
||||
private var pausingGameController: GameController?
|
||||
@ -86,26 +77,6 @@ class GameViewController: DeltaCore.GameViewController
|
||||
private var sustainButtonsBlurView: UIVisualEffectView!
|
||||
private var sustainButtonsBackgroundView: RSTBackgroundView!
|
||||
|
||||
override var previewActionItems: [UIPreviewActionItem]
|
||||
{
|
||||
if let previewActionItems = self.overridePreviewActionItems
|
||||
{
|
||||
return previewActionItems
|
||||
}
|
||||
|
||||
guard let game = self.game as? Game else { return [] }
|
||||
|
||||
let presentingViewController = self.presentingViewController
|
||||
|
||||
let launchGameAction = UIPreviewAction(title: NSLocalizedString("Launch \(game.name)", comment: ""), style: .default) { (action, viewController) in
|
||||
// Delaying until next run loop prevents self from being dismissed immediately
|
||||
DispatchQueue.main.async {
|
||||
presentingViewController?.present(viewController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
return [launchGameAction]
|
||||
}
|
||||
|
||||
required init()
|
||||
{
|
||||
self.reactivateSustainedInputsQueue = OperationQueue()
|
||||
@ -349,7 +320,7 @@ extension GameViewController
|
||||
|
||||
if previousState == .stopped
|
||||
{
|
||||
self.updateCheats()
|
||||
self.emulatorCore?.updateCheats()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -396,9 +367,7 @@ private extension GameViewController
|
||||
extension GameViewController: SaveStatesViewControllerDelegate
|
||||
{
|
||||
private func updateAutoSaveState()
|
||||
{
|
||||
guard self.updatesAutoSaveState else { return }
|
||||
|
||||
{
|
||||
// If pausedSaveState exists and has already been saved, don't update auto save state
|
||||
// This prevents us from filling our auto save state slots with the same save state
|
||||
let savedPausedSaveState = self.pausedSaveState?.isSaved ?? false
|
||||
@ -566,7 +535,7 @@ extension GameViewController: SaveStatesViewControllerDelegate
|
||||
print(error)
|
||||
}
|
||||
|
||||
self.updateCheats()
|
||||
self.emulatorCore?.updateCheats()
|
||||
|
||||
self.pauseViewController?.dismiss()
|
||||
}
|
||||
@ -578,67 +547,13 @@ extension GameViewController: CheatsViewControllerDelegate
|
||||
{
|
||||
func cheatsViewController(_ cheatsViewController: CheatsViewController, activateCheat cheat: Cheat)
|
||||
{
|
||||
self.activate(cheat)
|
||||
self.emulatorCore?.activateCheatWithErrorLogging(cheat)
|
||||
}
|
||||
|
||||
func cheatsViewController(_ cheatsViewController: CheatsViewController, deactivateCheat cheat: Cheat)
|
||||
{
|
||||
self.emulatorCore?.deactivate(cheat)
|
||||
}
|
||||
|
||||
private func activate(_ cheat: Cheat)
|
||||
{
|
||||
do
|
||||
{
|
||||
try self.emulatorCore?.activate(cheat)
|
||||
}
|
||||
catch EmulatorCore.CheatError.invalid
|
||||
{
|
||||
print("Invalid cheat:", cheat.name, cheat.code)
|
||||
}
|
||||
catch let error as NSError
|
||||
{
|
||||
print("Unknown Cheat Error:", error, cheat.name, cheat.code)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateCheats()
|
||||
{
|
||||
guard let game = self.game as? Game else { return }
|
||||
|
||||
let running = (self.emulatorCore?.state == .running)
|
||||
|
||||
if running
|
||||
{
|
||||
// Core MUST be paused when activating cheats, or else race conditions could crash the core
|
||||
self.pauseEmulation()
|
||||
}
|
||||
|
||||
let backgroundContext = DatabaseManager.shared.newBackgroundContext()
|
||||
backgroundContext.performAndWait {
|
||||
|
||||
let predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
|
||||
|
||||
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self)
|
||||
for cheat in cheats
|
||||
{
|
||||
if cheat.enabled
|
||||
{
|
||||
self.activate(cheat)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.emulatorCore?.deactivate(cheat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if running
|
||||
{
|
||||
self.resumeEmulation()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Sustain Buttons -
|
||||
|
||||
176
Delta/Emulation/PreviewGameViewController.swift
Normal file
176
Delta/Emulation/PreviewGameViewController.swift
Normal file
@ -0,0 +1,176 @@
|
||||
//
|
||||
// PreviewGameViewController.swift
|
||||
// Delta
|
||||
//
|
||||
// Created by Riley Testut on 8/11/16.
|
||||
// Copyright © 2016 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import DeltaCore
|
||||
|
||||
private var kvoContext = 0
|
||||
|
||||
class PreviewGameViewController: DeltaCore.GameViewController
|
||||
{
|
||||
// If non-nil, will override the default preview action items returned in previewActionItems()
|
||||
var overridePreviewActionItems: [UIPreviewActionItem]?
|
||||
|
||||
// Save state to be loaded upon preview
|
||||
var previewSaveState: SaveStateProtocol?
|
||||
|
||||
// Initial image to be shown while loading
|
||||
var previewImage: UIImage? {
|
||||
didSet {
|
||||
self.updatePreviewImage()
|
||||
}
|
||||
}
|
||||
|
||||
private var emulatorCoreQueue = DispatchQueue(label: "com.rileytestut.Delta.PreviewGameViewController.emulatorCoreQueue", qos: .userInitiated)
|
||||
|
||||
override var game: GameProtocol? {
|
||||
willSet {
|
||||
self.emulatorCore?.removeObserver(self, forKeyPath: #keyPath(EmulatorCore.state), context: &kvoContext)
|
||||
}
|
||||
didSet {
|
||||
guard let emulatorCore = self.emulatorCore else {
|
||||
self.preferredContentSize = CGSize.zero
|
||||
return
|
||||
}
|
||||
|
||||
emulatorCore.addObserver(self, forKeyPath: #keyPath(EmulatorCore.state), options: [.old], context: &kvoContext)
|
||||
|
||||
self.preferredContentSize = emulatorCore.preferredRenderingSize
|
||||
}
|
||||
}
|
||||
|
||||
override var previewActionItems: [UIPreviewActionItem] {
|
||||
guard let previewActionItems = self.overridePreviewActionItems else { return [] }
|
||||
return previewActionItems
|
||||
}
|
||||
|
||||
deinit
|
||||
{
|
||||
self.emulatorCore?.removeObserver(self, forKeyPath: #keyPath(EmulatorCore.state), context: &kvoContext)
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - UIViewController -
|
||||
/// UIViewController
|
||||
extension PreviewGameViewController
|
||||
{
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
self.controllerView.isHidden = true
|
||||
|
||||
// Temporarily prevent emulatorCore from updating gameView to prevent flicker of black, or other visual glitches
|
||||
self.emulatorCore?.remove(self.gameView)
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.emulatorCoreQueue.async {
|
||||
self.emulatorCore?.resume()
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// Pause in viewWillDisappear and not viewDidDisappear like DeltaCore.GameViewController so the audio cuts off earlier if being dismissed
|
||||
self.emulatorCore?.pause()
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
{
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
// Need to update in viewDidLayoutSubviews() to ensure bounds of gameView are not CGRect.zero
|
||||
self.updatePreviewImage()
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning()
|
||||
{
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: AnyObject?, change: [NSKeyValueChangeKey : AnyObject]?, context: UnsafeMutablePointer<Void>?)
|
||||
{
|
||||
guard context == &kvoContext else { return super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) }
|
||||
|
||||
guard
|
||||
let rawValue = change?[.oldKey] as? Int,
|
||||
let previousState = EmulatorCore.State(rawValue: rawValue),
|
||||
let state = self.emulatorCore?.state
|
||||
else { return }
|
||||
|
||||
if previousState == .stopped, state == .running
|
||||
{
|
||||
self.emulatorCoreQueue.sync {
|
||||
if self.isAppearing
|
||||
{
|
||||
// Pause to prevent it from starting before visible (in case user peeked slowly)
|
||||
self.emulatorCore?.pause()
|
||||
}
|
||||
|
||||
self.preparePreview()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Private -
|
||||
private extension PreviewGameViewController
|
||||
{
|
||||
func updatePreviewImage()
|
||||
{
|
||||
if let previewImage = self.previewImage
|
||||
{
|
||||
self.gameView?.inputImage = CIImage(image: previewImage)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.gameView?.inputImage = nil
|
||||
}
|
||||
}
|
||||
|
||||
func preparePreview()
|
||||
{
|
||||
var previewSaveState = self.previewSaveState
|
||||
|
||||
if let saveState = self.previewSaveState as? SaveState
|
||||
{
|
||||
saveState.managedObjectContext?.performAndWait {
|
||||
previewSaveState = DeltaCore.SaveState(fileURL: saveState.fileURL, gameType: saveState.gameType)
|
||||
}
|
||||
}
|
||||
|
||||
if let saveState = previewSaveState
|
||||
{
|
||||
do
|
||||
{
|
||||
try self.emulatorCore?.load(saveState)
|
||||
}
|
||||
catch EmulatorCore.SaveStateError.doesNotExist
|
||||
{
|
||||
print("Save State does not exist.")
|
||||
}
|
||||
catch
|
||||
{
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
self.emulatorCore?.updateCheats()
|
||||
|
||||
// Re-enable emulatorCore to update gameView again
|
||||
self.emulatorCore?.add(self.gameView)
|
||||
}
|
||||
}
|
||||
66
Delta/Extensions/EmulatorCore+Cheats.swift
Normal file
66
Delta/Extensions/EmulatorCore+Cheats.swift
Normal file
@ -0,0 +1,66 @@
|
||||
//
|
||||
// EmulatorCore+Cheats.swift
|
||||
// Delta
|
||||
//
|
||||
// Created by Riley Testut on 8/11/16.
|
||||
// Copyright © 2016 Riley Testut. All rights reserved.
|
||||
//
|
||||
|
||||
import DeltaCore
|
||||
|
||||
extension EmulatorCore
|
||||
{
|
||||
func activateCheatWithErrorLogging(_ cheat: Cheat)
|
||||
{
|
||||
do
|
||||
{
|
||||
try self.activate(cheat)
|
||||
}
|
||||
catch EmulatorCore.CheatError.invalid
|
||||
{
|
||||
print("Invalid cheat:", cheat.name, cheat.code)
|
||||
}
|
||||
catch
|
||||
{
|
||||
print("Unknown Cheat Error:", error, cheat.name, cheat.code)
|
||||
}
|
||||
}
|
||||
|
||||
func updateCheats()
|
||||
{
|
||||
guard let game = self.game as? Game else { return }
|
||||
|
||||
let running = (self.state == .running)
|
||||
|
||||
if running
|
||||
{
|
||||
// Core MUST be paused when activating cheats, or else race conditions could crash the core
|
||||
self.pause()
|
||||
}
|
||||
|
||||
let backgroundContext = DatabaseManager.shared.newBackgroundContext()
|
||||
backgroundContext.performAndWait {
|
||||
|
||||
let predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, game)
|
||||
|
||||
let cheats = Cheat.instancesWithPredicate(predicate, inManagedObjectContext: backgroundContext, type: Cheat.self)
|
||||
for cheat in cheats
|
||||
{
|
||||
if cheat.enabled
|
||||
{
|
||||
self.activateCheatWithErrorLogging(cheat)
|
||||
}
|
||||
else
|
||||
{
|
||||
self.deactivate(cheat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if running
|
||||
{
|
||||
self.resume()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -43,6 +43,5 @@ class LaunchViewController: UIViewController
|
||||
guard segue.identifier == "embedGameViewController" else { return }
|
||||
|
||||
self.gameViewController = segue.destination as! GameViewController
|
||||
self.gameViewController.updatesAutoSaveState = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,8 +65,6 @@ class SaveStatesViewController: UICollectionViewController
|
||||
|
||||
private let dateFormatter: DateFormatter
|
||||
|
||||
private let previewGameViewController = GameViewController()
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
{
|
||||
self.dateFormatter = DateFormatter()
|
||||
@ -122,9 +120,8 @@ extension SaveStatesViewController
|
||||
|
||||
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SaveStatesViewController.handleLongPressGesture(_:)))
|
||||
self.collectionView?.addGestureRecognizer(longPressGestureRecognizer)
|
||||
|
||||
// Pre-initialize previewGameViewController with game and start/pause emulation to ensure previewingContext(_:viewControllerForLocation:) callback doesn't take too long + break 3D Touch animation
|
||||
self.preparePreviewGameViewController()
|
||||
|
||||
self.prepareEmulatorCoreSaveState()
|
||||
|
||||
self.registerForPreviewing(with: self, sourceView: self.collectionView!)
|
||||
|
||||
@ -286,23 +283,13 @@ private extension SaveStatesViewController
|
||||
|
||||
func updateSaveState(_ saveState: SaveState)
|
||||
{
|
||||
// Stop previewGameViewController.emulatorCore, and switch to self.emulatorCore
|
||||
// Switch back to self.emulatorCore
|
||||
self.prepareEmulatorCore()
|
||||
|
||||
saveState.managedObjectContext?.performAndWait {
|
||||
self.delegate?.saveStatesViewController(self, updateSaveState: saveState)
|
||||
saveState.managedObjectContext?.saveWithErrorLogging()
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// Only restart self.previewGameViewController.emulatorCore if we're not being dismissed
|
||||
if !self.isDisappearing
|
||||
{
|
||||
self.emulatorCore?.stop()
|
||||
self.previewGameViewController.emulatorCore?.start()
|
||||
self.previewGameViewController.emulatorCore?.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadSaveState(_ saveState: SaveStateProtocol)
|
||||
@ -492,9 +479,14 @@ private extension SaveStatesViewController
|
||||
|
||||
func resetEmulatorCoreIfNeeded()
|
||||
{
|
||||
guard let saveState = self.emulatorCoreSaveState else { return }
|
||||
// Kinda hacky, but isMovingFromParentViewController only returns yes when popping off navigation controller, and not being dismissed modally
|
||||
// Because of this, this is only run when the user returns to PauseMenuViewController, and not when they choose a save state to load
|
||||
if self.isMovingFromParentViewController
|
||||
{
|
||||
self.prepareEmulatorCore()
|
||||
}
|
||||
|
||||
defer
|
||||
if let saveState = self.emulatorCoreSaveState
|
||||
{
|
||||
// Remove temporary save state file
|
||||
do
|
||||
@ -506,76 +498,57 @@ private extension SaveStatesViewController
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
self.previewGameViewController.emulatorCore?.stop()
|
||||
|
||||
// Kinda hacky, but isMovingFromParentViewController only returns yes when popping off navigation controller, and not being dismissed modally
|
||||
// Because of this, this is only run when the user returns to PauseMenuViewController, and not when they choose a save state to load
|
||||
if self.isMovingFromParentViewController
|
||||
{
|
||||
self.prepareEmulatorCore()
|
||||
}
|
||||
}
|
||||
|
||||
func prepareEmulatorCore()
|
||||
{
|
||||
self.previewGameViewController.emulatorCore?.stop()
|
||||
|
||||
// We stopped emulation for 3D Touch, so now we must resume emulation and load the save state we made to make it seem like it was never stopped
|
||||
if let emulatorCore = self.emulatorCore
|
||||
guard let emulatorCore = self.emulatorCore else { return }
|
||||
|
||||
// Temporarily disable video rendering to prevent flickers
|
||||
emulatorCore.videoManager.isEnabled = false
|
||||
|
||||
// Load the save state we stored a reference to
|
||||
emulatorCore.start()
|
||||
emulatorCore.pause()
|
||||
|
||||
if let saveState = self.emulatorCoreSaveState
|
||||
{
|
||||
// Temporarily disable video rendering to prevent flickers
|
||||
emulatorCore.videoManager.isEnabled = false
|
||||
|
||||
// Load the save state we stored a reference to
|
||||
emulatorCore.start()
|
||||
emulatorCore.pause()
|
||||
|
||||
if let saveState = self.emulatorCoreSaveState
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
try emulatorCore.load(saveState)
|
||||
}
|
||||
catch EmulatorCore.SaveStateError.doesNotExist
|
||||
{
|
||||
print("Save State does not exist.")
|
||||
}
|
||||
catch let error as NSError
|
||||
{
|
||||
print(error)
|
||||
}
|
||||
try emulatorCore.load(saveState)
|
||||
}
|
||||
catch EmulatorCore.SaveStateError.doesNotExist
|
||||
{
|
||||
print("Save State does not exist.")
|
||||
}
|
||||
catch let error as NSError
|
||||
{
|
||||
print(error)
|
||||
}
|
||||
|
||||
// Re-enable video rendering
|
||||
emulatorCore.videoManager.isEnabled = true
|
||||
}
|
||||
|
||||
// Re-enable video rendering
|
||||
emulatorCore.videoManager.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - 3D Touch -
|
||||
extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
||||
{
|
||||
private func preparePreviewGameViewController()
|
||||
private func prepareEmulatorCoreSaveState()
|
||||
{
|
||||
if let emulatorCore = self.emulatorCore
|
||||
guard let emulatorCore = self.emulatorCore else { return }
|
||||
|
||||
// Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
|
||||
|
||||
let fileURL = FileManager.uniqueTemporaryURL()
|
||||
self.emulatorCoreSaveState = emulatorCore.saveSaveState(to: fileURL)
|
||||
|
||||
if self.emulatorCoreSaveState != nil
|
||||
{
|
||||
// Store reference to current game state before we stop emulation so we can resume it if user decides to not load a save state
|
||||
|
||||
let fileURL = FileManager.uniqueTemporaryURL()
|
||||
self.emulatorCoreSaveState = emulatorCore.saveSaveState(to: fileURL)
|
||||
|
||||
guard self.emulatorCoreSaveState != nil else { return }
|
||||
|
||||
emulatorCore.stop()
|
||||
}
|
||||
|
||||
self.previewGameViewController.loadViewIfNeeded()
|
||||
self.previewGameViewController.controllerView.isHidden = true
|
||||
|
||||
self.previewGameViewController.game = self.game
|
||||
self.previewGameViewController.emulatorCore?.start()
|
||||
self.previewGameViewController.emulatorCore?.pause()
|
||||
}
|
||||
|
||||
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?
|
||||
@ -589,37 +562,28 @@ extension SaveStatesViewController: UIViewControllerPreviewingDelegate
|
||||
previewingContext.sourceRect = layoutAttributes.frame
|
||||
|
||||
let saveState = self.fetchedResultsController.object(at: indexPath) as! SaveState
|
||||
let actions = self.actionsForSaveState(saveState)?.lazy.filter{ $0.style != .cancel }.map{ $0.previewAction } ?? []
|
||||
let previewImage = self.imageCache.object(forKey: saveState.imageFileURL) ?? UIImage(contentsOfFile: saveState.imageFileURL.path)
|
||||
|
||||
do
|
||||
{
|
||||
try self.previewGameViewController.emulatorCore?.load(saveState)
|
||||
|
||||
let actions = self.actionsForSaveState(saveState)?.lazy.filter{ $0.style != .cancel }.map{ $0.previewAction } ?? []
|
||||
self.previewGameViewController.overridePreviewActionItems = Array(actions)
|
||||
|
||||
return self.previewGameViewController
|
||||
}
|
||||
catch EmulatorCore.SaveStateError.doesNotExist
|
||||
{
|
||||
print("Save State \(saveState.name) does not exist.")
|
||||
}
|
||||
catch let error as NSError
|
||||
{
|
||||
print(error)
|
||||
}
|
||||
let previewGameViewController = PreviewGameViewController()
|
||||
previewGameViewController.game = self.game
|
||||
previewGameViewController.overridePreviewActionItems = actions
|
||||
previewGameViewController.previewSaveState = saveState
|
||||
previewGameViewController.previewImage = previewImage
|
||||
|
||||
return nil
|
||||
return previewGameViewController
|
||||
}
|
||||
|
||||
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController)
|
||||
{
|
||||
let gameViewController = viewControllerToCommit as! GameViewController
|
||||
|
||||
let gameViewController = viewControllerToCommit as! PreviewGameViewController
|
||||
gameViewController.emulatorCore?.pause()
|
||||
|
||||
let fileURL = FileManager.uniqueTemporaryURL()
|
||||
if let saveState = gameViewController.emulatorCore?.saveSaveState(to: fileURL)
|
||||
{
|
||||
gameViewController.emulatorCore?.stop()
|
||||
|
||||
self.loadSaveState(saveState)
|
||||
|
||||
do
|
||||
|
||||
Loading…
Reference in New Issue
Block a user