Automatically uses external game controllers when connected

This commit is contained in:
Riley Testut 2017-10-12 10:27:56 -07:00
parent 61440ef994
commit a58835e3ad
5 changed files with 97 additions and 36 deletions

@ -1 +1 @@
Subproject commit ff014bab5c42e5c0a5fcbacb5c3c737ef33564e7 Subproject commit 6e0ec5aedac746d1a5ea05d450884f1a9ad7b509

View File

@ -385,11 +385,14 @@ private extension GameViewController
{ {
@objc func updateControllers() @objc func updateControllers()
{ {
guard let emulatorCore = self.emulatorCore, let game = self.game else { return } let isExternalGameControllerConnected = ExternalGameControllerManager.shared.connectedControllers.contains(where: { $0.playerIndex != nil })
if !isExternalGameControllerConnected && Settings.localControllerPlayerIndex == nil
{
Settings.localControllerPlayerIndex = 0
}
let controllers = [self.controllerView as GameController] + ExternalGameControllerManager.shared.connectedControllers // If Settings.localControllerPlayerIndex is non-nil, and there isn't a connected controller with same playerIndex, show controller view.
if let index = Settings.localControllerPlayerIndex, !ExternalGameControllerManager.shared.connectedControllers.contains { $0.playerIndex == index }
if let index = Settings.localControllerPlayerIndex
{ {
self.controllerView.playerIndex = index self.controllerView.playerIndex = index
self.controllerView.isHidden = false self.controllerView.isHidden = false
@ -398,8 +401,17 @@ private extension GameViewController
{ {
self.controllerView.playerIndex = nil self.controllerView.playerIndex = nil
self.controllerView.isHidden = true self.controllerView.isHidden = true
Settings.localControllerPlayerIndex = nil
} }
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
if let emulatorCore = self.emulatorCore, let game = self.game
{
let controllers = [self.controllerView as GameController] + ExternalGameControllerManager.shared.connectedControllers
for gameController in controllers for gameController in controllers
{ {
if gameController.playerIndex != nil if gameController.playerIndex != nil
@ -421,9 +433,7 @@ private extension GameViewController
gameController.removeReceiver(emulatorCore) gameController.removeReceiver(emulatorCore)
} }
} }
}
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
} }
func updateControllerSkin() func updateControllerSkin()
@ -751,7 +761,7 @@ extension GameViewController
do do
{ {
if let quickSaveState = try fetchRequest.execute().first if let quickSaveState = try DatabaseManager.shared.viewContext.fetch(fetchRequest).first
{ {
self.load(quickSaveState) self.load(quickSaveState)
} }

View File

@ -22,7 +22,6 @@ extension ControllersSettingsViewController
} }
} }
private class LocalDeviceController: NSObject, GameController private class LocalDeviceController: NSObject, GameController
{ {
var name: String { var name: String {
@ -49,10 +48,19 @@ class ControllersSettingsViewController: UITableViewController
fileprivate var gameController: GameController? { fileprivate var gameController: GameController? {
didSet { didSet {
// Order matters since localDeviceController changes Settings.localControllerPlayerIndex, which sends out NSNotification.
if oldValue == self.localDeviceController
{
self.gameController?.playerIndex = self.playerIndex
oldValue?.playerIndex = nil
}
else
{
oldValue?.playerIndex = nil oldValue?.playerIndex = nil
self.gameController?.playerIndex = self.playerIndex self.gameController?.playerIndex = self.playerIndex
} }
} }
}
fileprivate var connectedControllers = ExternalGameControllerManager.shared.connectedControllers.sorted(by: { $0.playerIndex ?? NSIntegerMax < $1.playerIndex ?? NSIntegerMax }) fileprivate var connectedControllers = ExternalGameControllerManager.shared.connectedControllers.sorted(by: { $0.playerIndex ?? NSIntegerMax < $1.playerIndex ?? NSIntegerMax })
@ -183,14 +191,29 @@ private extension ControllersSettingsViewController
if let index = self.connectedControllers.index(where: { $0 == controller }) if let index = self.connectedControllers.index(where: { $0 == controller })
{ {
self.tableView.beginUpdates()
if self.connectedControllers.count == 1 if self.connectedControllers.count == 1
{ {
self.tableView.insertSections(IndexSet(integer: Section.externalControllers.rawValue), with: .fade) self.tableView.insertSections(IndexSet(integer: Section.externalControllers.rawValue), with: .fade)
if self.connectedControllers.first?.playerIndex == self.playerIndex
{
self.tableView.insertSections(IndexSet(integer: Section.customizeControls.rawValue), with: .fade)
}
} }
else else
{ {
self.tableView.insertRows(at: [IndexPath(row: index, section: Section.externalControllers.rawValue)], with: .automatic) self.tableView.insertRows(at: [IndexPath(row: index, section: Section.externalControllers.rawValue)], with: .automatic)
} }
self.tableView.endUpdates()
}
if controller.playerIndex == self.playerIndex
{
self.tableView.reloadSections(IndexSet(integer: Section.none.rawValue), with: .none)
self.tableView.reloadSections(IndexSet(integer: Section.localDevice.rawValue), with: .none)
} }
} }
@ -202,19 +225,29 @@ private extension ControllersSettingsViewController
{ {
self.connectedControllers.remove(at: index) self.connectedControllers.remove(at: index)
self.tableView.beginUpdates()
if self.connectedControllers.count == 0 if self.connectedControllers.count == 0
{ {
self.tableView.deleteSections(IndexSet(integer: Section.externalControllers.rawValue), with: .fade) self.tableView.deleteSections(IndexSet(integer: Section.externalControllers.rawValue), with: .fade)
if controller.playerIndex != nil
{
self.tableView.deleteSections(IndexSet(integer: Section.customizeControls.rawValue), with: .fade)
}
} }
else else
{ {
self.tableView.deleteRows(at: [IndexPath(row: index, section: Section.externalControllers.rawValue)], with: .automatic) self.tableView.deleteRows(at: [IndexPath(row: index, section: Section.externalControllers.rawValue)], with: .automatic)
} }
self.tableView.endUpdates()
} }
if controller.playerIndex == self.playerIndex if controller.playerIndex == self.playerIndex
{ {
self.tableView.reloadSections(IndexSet(integer: Section.none.rawValue), with: .none) self.tableView.reloadSections(IndexSet(integer: Section.none.rawValue), with: .none)
self.tableView.reloadSections(IndexSet(integer: Section.localDevice.rawValue), with: .none)
} }
} }
} }
@ -240,7 +273,7 @@ extension ControllersSettingsViewController
{ {
switch Section(rawValue: section)! switch Section(rawValue: section)!
{ {
case .none: return 1 case .none: return 0
case .localDevice: return 1 case .localDevice: return 1
case .externalControllers: return self.connectedControllers.count case .externalControllers: return self.connectedControllers.count
case .customizeControls: return 1 case .customizeControls: return 1
@ -266,6 +299,16 @@ extension ControllersSettingsViewController
case .customizeControls: return nil case .customizeControls: return nil
} }
} }
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
if section == Section.none.rawValue
{
return 1
}
return UITableViewAutomaticDimension
}
} }
extension ControllersSettingsViewController extension ControllersSettingsViewController
@ -316,7 +359,6 @@ extension ControllersSettingsViewController
self.tableView.reloadRows(at: [indexPath], with: .none) self.tableView.reloadRows(at: [indexPath], with: .none)
if self.numberOfSections(in: self.tableView) > self.tableView.numberOfSections if self.numberOfSections(in: self.tableView) > self.tableView.numberOfSections
{ {
self.tableView.insertSections(IndexSet(integer: Section.customizeControls.rawValue), with: .fade) self.tableView.insertSections(IndexSet(integer: Section.customizeControls.rawValue), with: .fade)

View File

@ -40,12 +40,14 @@ struct Settings
/// Controllers /// Controllers
static var localControllerPlayerIndex: Int? = 0 { static var localControllerPlayerIndex: Int? = 0 {
didSet { didSet {
guard self.localControllerPlayerIndex != oldValue else { return }
NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.localControllerPlayerIndex]) NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.localControllerPlayerIndex])
} }
} }
static var translucentControllerSkinOpacity: CGFloat { static var translucentControllerSkinOpacity: CGFloat {
set { set {
guard newValue != self.translucentControllerSkinOpacity else { return }
UserDefaults.standard.translucentControllerSkinOpacity = newValue UserDefaults.standard.translucentControllerSkinOpacity = newValue
NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.translucentControllerSkinOpacity]) NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.translucentControllerSkinOpacity])
} }
@ -113,6 +115,9 @@ struct Settings
static func setPreferredControllerSkin(_ controllerSkin: ControllerSkin, for system: System, traits: DeltaCore.ControllerSkin.Traits) static func setPreferredControllerSkin(_ controllerSkin: ControllerSkin, for system: System, traits: DeltaCore.ControllerSkin.Traits)
{ {
guard let userDefaultKey = self.preferredControllerSkinKey(for: system, traits: traits) else { return } guard let userDefaultKey = self.preferredControllerSkinKey(for: system, traits: traits) else { return }
guard UserDefaults.standard.string(forKey: userDefaultKey) != controllerSkin.identifier else { return }
UserDefaults.standard.set(controllerSkin.identifier, forKey: userDefaultKey) UserDefaults.standard.set(controllerSkin.identifier, forKey: userDefaultKey)
NotificationCenter.default.post(name: .settingsDidChange, object: controllerSkin, userInfo: [NotificationUserInfoKey.name: Name.preferredControllerSkin, NotificationUserInfoKey.system: system, NotificationUserInfoKey.traits: traits]) NotificationCenter.default.post(name: .settingsDidChange, object: controllerSkin, userInfo: [NotificationUserInfoKey.name: Name.preferredControllerSkin, NotificationUserInfoKey.system: system, NotificationUserInfoKey.traits: traits])

View File

@ -42,6 +42,8 @@ class SettingsViewController: UITableViewController
fileprivate var selectionFeedbackGenerator: UISelectionFeedbackGenerator? fileprivate var selectionFeedbackGenerator: UISelectionFeedbackGenerator?
fileprivate var previousSelectedRowIndexPath: IndexPath?
required init?(coder aDecoder: NSCoder) required init?(coder aDecoder: NSCoder)
{ {
super.init(coder: aDecoder) super.init(coder: aDecoder)
@ -62,7 +64,7 @@ class SettingsViewController: UITableViewController
{ {
super.viewWillAppear(animated) super.viewWillAppear(animated)
if let indexPath = self.tableView.indexPathForSelectedRow if let indexPath = self.previousSelectedRowIndexPath
{ {
if indexPath.section == Section.controllers.rawValue if indexPath.section == Section.controllers.rawValue
{ {
@ -89,6 +91,8 @@ class SettingsViewController: UITableViewController
let indexPath = self.tableView.indexPath(for: cell) let indexPath = self.tableView.indexPath(for: cell)
else { return } else { return }
self.previousSelectedRowIndexPath = indexPath
switch segueType switch segueType
{ {
case Segue.controllers: case Segue.controllers: