Adds basic UI for selecting sustained button
This commit is contained in:
parent
b2bf15a79c
commit
07da4f3158
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" 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="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="wKV-3d-NIY">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<capability name="Segues with Peek and Pop" minToolsVersion="7.1"/>
|
||||
@ -106,6 +106,55 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</view>
|
||||
<view alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="noi-yo-HIE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
<subviews>
|
||||
<visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pwD-5i-uQ2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="S8Q-YY-Kog">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9Eo-TR-4O4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="8ur-lW-yiV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JRb-Vg-JHA" customClass="RSTBackgroundView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="300"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="JRb-Vg-JHA" firstAttribute="top" secondItem="8ur-lW-yiV" secondAttribute="top" id="613-jP-t8K"/>
|
||||
<constraint firstAttribute="trailing" secondItem="JRb-Vg-JHA" secondAttribute="trailing" id="Ele-t2-Kcg"/>
|
||||
<constraint firstAttribute="bottom" secondItem="JRb-Vg-JHA" secondAttribute="bottom" id="aTp-7v-QFY"/>
|
||||
<constraint firstItem="JRb-Vg-JHA" firstAttribute="leading" secondItem="8ur-lW-yiV" secondAttribute="leading" id="c05-Bl-4Q8"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<vibrancyEffect>
|
||||
<blurEffect style="dark"/>
|
||||
</vibrancyEffect>
|
||||
</visualEffectView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="9Eo-TR-4O4" firstAttribute="top" secondItem="S8Q-YY-Kog" secondAttribute="top" id="EgV-fR-NeD"/>
|
||||
<constraint firstAttribute="bottom" secondItem="9Eo-TR-4O4" secondAttribute="bottom" id="TYE-at-xaY"/>
|
||||
<constraint firstItem="9Eo-TR-4O4" firstAttribute="leading" secondItem="S8Q-YY-Kog" secondAttribute="leading" id="YRo-nB-Hsb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="9Eo-TR-4O4" secondAttribute="trailing" id="rWV-bD-7li"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<blurEffect style="dark"/>
|
||||
</visualEffectView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="pwD-5i-uQ2" firstAttribute="leading" secondItem="noi-yo-HIE" secondAttribute="leading" id="ai3-VH-ZSe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="pwD-5i-uQ2" secondAttribute="trailing" id="fTZ-ah-pgi"/>
|
||||
<constraint firstItem="pwD-5i-uQ2" firstAttribute="top" secondItem="noi-yo-HIE" secondAttribute="top" id="gYf-Oa-jve"/>
|
||||
<constraint firstAttribute="bottom" secondItem="pwD-5i-uQ2" secondAttribute="bottom" id="u3P-PF-gpZ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" placeholderIntrinsicWidth="600" placeholderIntrinsicHeight="300" translatesAutoresizingMaskIntoConstraints="NO" id="2W1-IT-Y2l" customClass="ControllerView" customModule="DeltaCore">
|
||||
<rect key="frame" x="0.0" y="300" width="600" height="300"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@ -121,13 +170,17 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="noi-yo-HIE" firstAttribute="top" secondItem="GfI-Mx-CQT" secondAttribute="top" id="1wY-jJ-o0w"/>
|
||||
<constraint firstItem="2W1-IT-Y2l" firstAttribute="top" secondItem="7ei-Ah-JvQ" secondAttribute="top" id="EF1-5h-FJs"/>
|
||||
<constraint firstAttribute="trailing" secondItem="GfI-Mx-CQT" secondAttribute="trailing" id="EKN-e9-x37"/>
|
||||
<constraint firstItem="noi-yo-HIE" firstAttribute="bottom" secondItem="GfI-Mx-CQT" secondAttribute="bottom" id="IEw-2f-nC4"/>
|
||||
<constraint firstItem="noi-yo-HIE" firstAttribute="leading" secondItem="GfI-Mx-CQT" secondAttribute="leading" id="aE5-xg-A1u"/>
|
||||
<constraint firstItem="GfI-Mx-CQT" firstAttribute="top" secondItem="7ei-Ah-JvQ" secondAttribute="top" id="ala-4P-wQR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="GfI-Mx-CQT" secondAttribute="bottom" id="gFo-XU-4PO">
|
||||
<variation key="heightClass=compact" constant="0.0"/>
|
||||
</constraint>
|
||||
<constraint firstItem="GfI-Mx-CQT" firstAttribute="leading" secondItem="7ei-Ah-JvQ" secondAttribute="leading" id="hck-DY-vlt"/>
|
||||
<constraint firstItem="noi-yo-HIE" firstAttribute="trailing" secondItem="GfI-Mx-CQT" secondAttribute="trailing" id="l7o-xb-Zxa"/>
|
||||
<constraint firstItem="2W1-IT-Y2l" firstAttribute="top" secondItem="GfI-Mx-CQT" secondAttribute="bottom" id="uWb-Cv-NM1"/>
|
||||
<constraint firstAttribute="bottom" secondItem="2W1-IT-Y2l" secondAttribute="bottom" id="vZg-yU-Kqm"/>
|
||||
<constraint firstAttribute="trailing" secondItem="2W1-IT-Y2l" secondAttribute="trailing" id="wcY-Qm-RRC"/>
|
||||
@ -148,9 +201,11 @@
|
||||
</variation>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="backgroundView" destination="JRb-Vg-JHA" id="85O-6W-WOe"/>
|
||||
<outlet property="controllerView" destination="2W1-IT-Y2l" id="WCa-LM-fXF"/>
|
||||
<outlet property="controllerViewHeightConstraint" destination="PEV-zv-Buo" id="1jo-Kg-HpO"/>
|
||||
<outlet property="gameView" destination="GfI-Mx-CQT" id="HmP-OA-mci"/>
|
||||
<outlet property="sustainButtonContentView" destination="noi-yo-HIE" id="7FG-2i-LC2"/>
|
||||
<segue destination="Yrw-9v-Pcr" kind="presentation" identifier="pauseSegue" customClass="PauseStoryboardSegue" customModule="Delta" customModuleProvider="target" id="9cz-mr-lTk"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
import UIKit
|
||||
|
||||
import DeltaCore
|
||||
import Roxas
|
||||
|
||||
class EmulationViewController: UIViewController
|
||||
{
|
||||
@ -43,6 +44,8 @@ class EmulationViewController: UIViewController
|
||||
//MARK: - Private Properties
|
||||
@IBOutlet private var controllerView: ControllerView!
|
||||
@IBOutlet private var gameView: GameView!
|
||||
@IBOutlet private var sustainButtonContentView: UIView!
|
||||
@IBOutlet private var backgroundView: RSTBackgroundView!
|
||||
|
||||
@IBOutlet private var controllerViewHeightConstraint: NSLayoutConstraint!
|
||||
|
||||
@ -51,6 +54,13 @@ class EmulationViewController: UIViewController
|
||||
private var context = CIContext(options: [kCIContextWorkingColorSpace: NSNull()])
|
||||
|
||||
|
||||
private var selectingSustainedButton = false {
|
||||
didSet {
|
||||
self.sustainButtonContentView.alpha = self.selectingSustainedButton ? 1.0 : 0.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//MARK: - Initializers -
|
||||
/** Initializers **/
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
@ -86,6 +96,9 @@ class EmulationViewController: UIViewController
|
||||
self.gameView.backgroundColor = UIColor.clearColor()
|
||||
self.emulatorCore.addGameView(self.gameView)
|
||||
|
||||
self.backgroundView.textLabel.text = NSLocalizedString("Select Button to Sustain", comment: "")
|
||||
self.backgroundView.detailTextLabel.text = NSLocalizedString("Sustained buttons act as though they're being held down, without needing to do so yourself. This is particularly useful for certain games, such as platformers which require you to hold down a button to run.", comment: "")
|
||||
|
||||
let controllerSkin = ControllerSkin.defaultControllerSkinForGameUTI(self.game.typeIdentifier)
|
||||
|
||||
self.controllerView.containerView = self.view
|
||||
@ -113,7 +126,7 @@ class EmulationViewController: UIViewController
|
||||
case .Running: break
|
||||
case .Paused:
|
||||
self.updateCheats()
|
||||
self.emulatorCore.resumeEmulation()
|
||||
self.resumeEmulation()
|
||||
}
|
||||
|
||||
// Toggle audioManager.enabled to reset the audio buffer and ensure the audio isn't delayed from the beginning
|
||||
@ -169,17 +182,13 @@ class EmulationViewController: UIViewController
|
||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
|
||||
{
|
||||
self.emulatorCore.pauseEmulation()
|
||||
self.pauseEmulation()
|
||||
|
||||
if segue.identifier == "pauseSegue"
|
||||
{
|
||||
let pauseViewController = segue.destinationViewController as! PauseViewController
|
||||
pauseViewController.pauseText = self.game.name
|
||||
|
||||
let dismissAction: (PauseItem -> Void) = { item in
|
||||
pauseViewController.dismiss()
|
||||
}
|
||||
|
||||
// Swift has a bug where using unowned references can lead to swift_abortRetainUnowned errors.
|
||||
// Specifically, if you pause a game, open the save states menu, go back, return to menu, select a new game, then try to pause it, it will crash
|
||||
// As a dirty workaround, we just use a weak reference, and force unwrap it if needed
|
||||
@ -196,7 +205,15 @@ class EmulationViewController: UIViewController
|
||||
pauseViewController.presentCheatsViewController(delegate: self)
|
||||
})
|
||||
|
||||
let sustainButtonItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Sustain Button", comment: ""), action: dismissAction)
|
||||
let sustainButtonItem = PauseItem(image: UIImage(named: "SmallPause")!, text: NSLocalizedString("Sustain Button", comment: ""), action: { [unowned self] item in
|
||||
|
||||
if item.selected
|
||||
{
|
||||
self.selectingSustainedButton = true
|
||||
pauseViewController.dismiss()
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
var fastForwardItem = PauseItem(image: UIImage(named: "FastForward")!, text: NSLocalizedString("Fast Forward", comment: ""), action: { [unowned self] item in
|
||||
self.emulatorCore.fastForwarding = item.selected
|
||||
@ -213,14 +230,15 @@ class EmulationViewController: UIViewController
|
||||
{
|
||||
self.pauseViewController = nil
|
||||
|
||||
self.emulatorCore.resumeEmulation()
|
||||
if self.resumeEmulation()
|
||||
{
|
||||
// Temporarily disable audioManager to prevent delayed audio bug when using 3D Touch Peek & Pop
|
||||
self.emulatorCore.audioManager.enabled = false
|
||||
|
||||
// Temporarily disable audioManager to prevent delayed audio bug when using 3D Touch Peek & Pop
|
||||
self.emulatorCore.audioManager.enabled = false
|
||||
|
||||
// Re-enable after delay
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
|
||||
self.emulatorCore.audioManager.enabled = true
|
||||
// Re-enable after delay
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
|
||||
self.emulatorCore.audioManager.enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,8 +263,25 @@ class EmulationViewController: UIViewController
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Controllers -
|
||||
/// Controllers
|
||||
//MARK: - Emulation -
|
||||
/// Emulation
|
||||
private extension EmulationViewController
|
||||
{
|
||||
func pauseEmulation() -> Bool
|
||||
{
|
||||
return self.emulatorCore.pauseEmulation()
|
||||
}
|
||||
|
||||
func resumeEmulation() -> Bool
|
||||
{
|
||||
guard !self.selectingSustainedButton && self.pauseViewController == nil else { return false }
|
||||
|
||||
return self.emulatorCore.resumeEmulation()
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Controllers/Inputs -
|
||||
/// Controllers/Inputs
|
||||
private extension EmulationViewController
|
||||
{
|
||||
@objc func updateControllers()
|
||||
@ -268,6 +303,38 @@ private extension EmulationViewController
|
||||
|
||||
self.view.setNeedsLayout()
|
||||
}
|
||||
|
||||
func setSelectingSustainedButton(selectingSustainedButton: Bool, animated: Bool)
|
||||
{
|
||||
if !animated
|
||||
{
|
||||
self.selectingSustainedButton = selectingSustainedButton
|
||||
}
|
||||
else
|
||||
{
|
||||
UIView.animateWithDuration(0.4) {
|
||||
self.selectingSustainedButton = selectingSustainedButton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sustainInput(input: InputType, gameController: GameControllerType)
|
||||
{
|
||||
if let input = input as? ControllerInput
|
||||
{
|
||||
guard input != ControllerInput.Menu else
|
||||
{
|
||||
self.setSelectingSustainedButton(false, animated: true)
|
||||
self.performSegueWithIdentifier("pauseSegue", sender: gameController)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
self.setSelectingSustainedButton(false, animated: true)
|
||||
|
||||
self.resumeEmulation()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Save States
|
||||
@ -362,7 +429,7 @@ extension EmulationViewController: CheatsViewControllerDelegate
|
||||
if running
|
||||
{
|
||||
// Core MUST be paused when activating cheats, or else race conditions could crash the core
|
||||
self.emulatorCore.pauseEmulation()
|
||||
self.pauseEmulation()
|
||||
}
|
||||
|
||||
let predicate = NSPredicate(format: "%K == %@", Cheat.Attributes.game.rawValue, self.emulatorCore.game as! Game)
|
||||
@ -394,7 +461,7 @@ extension EmulationViewController: CheatsViewControllerDelegate
|
||||
|
||||
if running
|
||||
{
|
||||
self.emulatorCore.resumeEmulation()
|
||||
self.resumeEmulation()
|
||||
}
|
||||
|
||||
}
|
||||
@ -407,15 +474,12 @@ private extension EmulationViewController
|
||||
{
|
||||
@objc func willResignActive(notification: NSNotification)
|
||||
{
|
||||
self.emulatorCore.pauseEmulation()
|
||||
self.pauseEmulation()
|
||||
}
|
||||
|
||||
@objc func didBecomeActive(notification: NSNotification)
|
||||
{
|
||||
if self.pauseViewController == nil
|
||||
{
|
||||
self.emulatorCore.resumeEmulation()
|
||||
}
|
||||
self.resumeEmulation()
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,6 +494,12 @@ extension EmulationViewController: GameControllerReceiverType
|
||||
UIDevice.currentDevice().vibrate()
|
||||
}
|
||||
|
||||
guard !self.selectingSustainedButton else
|
||||
{
|
||||
self.sustainInput(input, gameController: gameController)
|
||||
return
|
||||
}
|
||||
|
||||
guard let input = input as? ControllerInput else { return }
|
||||
|
||||
print("Activated \(input)")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user