diff --git a/Delta/AppDelegate.swift b/Delta/AppDelegate.swift index 0d91868..6a56585 100644 --- a/Delta/AppDelegate.swift +++ b/Delta/AppDelegate.swift @@ -19,6 +19,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + Settings.registerDefaults() + Delta.register(SNES.core) Delta.register(GBA.core) diff --git a/Delta/Emulation/GameViewController.swift b/Delta/Emulation/GameViewController.swift index ce0e3f7..bfabdf1 100644 --- a/Delta/Emulation/GameViewController.swift +++ b/Delta/Emulation/GameViewController.swift @@ -112,7 +112,7 @@ class GameViewController: DeltaCore.GameViewController NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.updateControllers), name: .externalControllerDidConnect, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.updateControllers), name: .externalControllerDidDisconnect, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.didEnterBackground(with:)), name: .UIApplicationDidEnterBackground, object: UIApplication.shared) - NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.preferredControllerSkinDidUpdate(with:)), name: .preferredControllerSkinDidUpdate, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.settingsDidChange(with:)), name: .settingsDidChange, object: nil) } deinit @@ -197,15 +197,8 @@ extension GameViewController { super.viewWillTransition(to: size, with: coordinator) - guard let game = self.game else { return } - - var traits = DeltaCore.ControllerSkin.Traits.defaults(for: self.view) - traits.orientation = (size.width > size.height) ? .landscape : .portrait - - let controllerSkin = Settings.preferredControllerSkin(for: game.type, traits: traits) - coordinator.animate(alongsideTransition: { (context) in - self.controllerView.controllerSkin = controllerSkin + self.updateControllerSkin() }, completion: nil) } @@ -389,6 +382,15 @@ private extension GameViewController let controllerSkin = Settings.preferredControllerSkin(for: game.type, traits: traits) self.controllerView.controllerSkin = controllerSkin + + if controllerSkin?.isTranslucent(for: traits) ?? false + { + self.controllerView.alpha = Settings.translucentControllerSkinOpacity + } + else + { + self.controllerView.alpha = 1.0 + } } } @@ -762,17 +764,35 @@ private extension GameViewController } } - @objc func preferredControllerSkinDidUpdate(with notification: Notification) + @objc func settingsDidChange(with notification: Notification) { - guard - let gameType = notification.userInfo?[Settings.NotificationUserInfoKey.gameType.rawValue] as? GameType, - let traits = notification.userInfo?[Settings.NotificationUserInfoKey.traits.rawValue] as? DeltaCore.ControllerSkin.Traits - else { return } + guard let settingsName = notification.userInfo?[Settings.NotificationUserInfoKey.name] as? Settings.Name else { return } - let currentTraits = DeltaCore.ControllerSkin.Traits.defaults(for: self.view) - if gameType == self.game?.type && traits == currentTraits + switch settingsName { - self.updateControllerSkin() + case .preferredControllerSkin: + guard + let gameType = notification.userInfo?[Settings.NotificationUserInfoKey.gameType] as? GameType, + let traits = notification.userInfo?[Settings.NotificationUserInfoKey.traits] as? DeltaCore.ControllerSkin.Traits + else { return } + + let currentTraits = DeltaCore.ControllerSkin.Traits.defaults(for: self.view) + if gameType == self.game?.type && traits == currentTraits + { + self.updateControllerSkin() + } + + case .translucentControllerSkinOpacity: + if let traits = self.controllerView.controllerSkinTraits + { + if self.controllerView.controllerSkin?.isTranslucent(for: traits) ?? false + { + self.controllerView.alpha = Settings.translucentControllerSkinOpacity + } + } + + + default: break } } } diff --git a/Delta/Settings/Settings.storyboard b/Delta/Settings/Settings.storyboard index 7f4993b..adcb1d9 100644 --- a/Delta/Settings/Settings.storyboard +++ b/Delta/Settings/Settings.storyboard @@ -1,11 +1,12 @@ - + - + + @@ -21,7 +22,7 @@ - + @@ -45,7 +46,7 @@ - + @@ -69,7 +70,7 @@ - + @@ -93,7 +94,7 @@ - + @@ -121,7 +122,7 @@ - + @@ -138,7 +139,7 @@ - + @@ -156,6 +157,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -170,6 +211,8 @@ + + diff --git a/Delta/Settings/Settings.swift b/Delta/Settings/Settings.swift index 5507e1e..1ba1b67 100644 --- a/Delta/Settings/Settings.swift +++ b/Delta/Settings/Settings.swift @@ -16,22 +16,49 @@ import Roxas extension Notification.Name { - static let preferredControllerSkinDidUpdate = Notification.Name("PreferredControllerSkinDidUpdateNotification") + static let settingsDidChange = Notification.Name("SettingsDidChangeNotification") } extension Settings { enum NotificationUserInfoKey: String { + case name + case gameType case traits } + + enum Name: String + { + case localControllerPlayerIndex + case translucentControllerSkinOpacity + case preferredControllerSkin + } } struct Settings { /// Controllers - static var localControllerPlayerIndex: Int? = 0 + static var localControllerPlayerIndex: Int? = 0 { + didSet { + NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.localControllerPlayerIndex]) + } + } + + static var translucentControllerSkinOpacity: CGFloat { + set { + UserDefaults.standard.translucentControllerSkinOpacity = newValue + NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.translucentControllerSkinOpacity]) + } + get { return UserDefaults.standard.translucentControllerSkinOpacity } + } + + static func registerDefaults() + { + let defaults = [#keyPath(UserDefaults.translucentControllerSkinOpacity): 1.0] + UserDefaults.standard.register(defaults: defaults) + } static func preferredControllerSkin(for gameType: GameType, traits: DeltaCore.ControllerSkin.Traits) -> ControllerSkin? { @@ -78,7 +105,7 @@ struct Settings guard let userDefaultKey = self.preferredControllerSkinKey(for: gameType, traits: traits) else { return } UserDefaults.standard.set(controllerSkin.identifier, forKey: userDefaultKey) - NotificationCenter.default.post(name: .preferredControllerSkinDidUpdate, object: controllerSkin, userInfo: [NotificationUserInfoKey.gameType.rawValue: gameType, NotificationUserInfoKey.traits.rawValue: traits]) + NotificationCenter.default.post(name: .settingsDidChange, object: controllerSkin, userInfo: [NotificationUserInfoKey.name: Name.preferredControllerSkin, NotificationUserInfoKey.gameType: gameType, NotificationUserInfoKey.traits: traits]) } } @@ -115,3 +142,8 @@ private extension Settings return key } } + +private extension UserDefaults +{ + @NSManaged var translucentControllerSkinOpacity: CGFloat +} diff --git a/Delta/Settings/SettingsViewController.swift b/Delta/Settings/SettingsViewController.swift index 32a585c..ced5b25 100644 --- a/Delta/Settings/SettingsViewController.swift +++ b/Delta/Settings/SettingsViewController.swift @@ -15,6 +15,7 @@ extension SettingsViewController { case controllers case controllerSkins + case controllerOpacity } fileprivate enum Segue: String @@ -26,6 +27,9 @@ extension SettingsViewController class SettingsViewController: UITableViewController { + @IBOutlet fileprivate var controllerOpacityLabel: UILabel! + @IBOutlet fileprivate var controllerOpacitySlider: UISlider! + required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) @@ -37,6 +41,9 @@ class SettingsViewController: UITableViewController override func viewDidLoad() { super.viewDidLoad() + + self.controllerOpacitySlider.value = Float(Settings.translucentControllerSkinOpacity) + self.updateControllerOpacityLabel() } override func viewWillAppear(_ animated: Bool) @@ -82,6 +89,15 @@ class SettingsViewController: UITableViewController } } +private extension SettingsViewController +{ + func updateControllerOpacityLabel() + { + let percentage = String(format: "%.f", Settings.translucentControllerSkinOpacity * 100) + "%" + self.controllerOpacityLabel.text = percentage + } +} + private extension SettingsViewController { @IBAction func unwindFromControllersSettingsViewController(_ segue: UIStoryboardSegue) @@ -94,6 +110,22 @@ private extension SettingsViewController } } +private extension SettingsViewController +{ + @IBAction func changeControllerOpacity(with sender: UISlider) + { + let roundedValue = (sender.value / 0.05).rounded() * 0.05 + Settings.translucentControllerSkinOpacity = CGFloat(roundedValue) + + self.updateControllerOpacityLabel() + } + + @IBAction func didFinishChangingControllerOpacity(with sender: UISlider) + { + sender.value = Float(Settings.translucentControllerSkinOpacity) + } +} + private extension SettingsViewController { dynamic func externalControllerDidConnect(_ notification: Notification) @@ -142,6 +174,7 @@ extension SettingsViewController { case Section.controllers: self.performSegue(withIdentifier: Segue.controllers.rawValue, sender: cell) case Section.controllerSkins: self.performSegue(withIdentifier: Segue.controllerSkins.rawValue, sender: cell) + case Section.controllerOpacity: break } } }