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()
{
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 let index = Settings.localControllerPlayerIndex
// 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 }
{
self.controllerView.playerIndex = index
self.controllerView.isHidden = false
@ -398,32 +401,39 @@ private extension GameViewController
{
self.controllerView.playerIndex = nil
self.controllerView.isHidden = true
}
for gameController in controllers
{
if gameController.playerIndex != nil
{
if let inputMapping = GameControllerInputMapping.inputMapping(for: gameController, gameType: game.type, in: DatabaseManager.shared.viewContext)
{
gameController.addReceiver(self, inputMapping: inputMapping)
gameController.addReceiver(emulatorCore, inputMapping: inputMapping)
}
else
{
gameController.addReceiver(self)
gameController.addReceiver(emulatorCore)
}
}
else
{
gameController.removeReceiver(self)
gameController.removeReceiver(emulatorCore)
}
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
{
if gameController.playerIndex != nil
{
if let inputMapping = GameControllerInputMapping.inputMapping(for: gameController, gameType: game.type, in: DatabaseManager.shared.viewContext)
{
gameController.addReceiver(self, inputMapping: inputMapping)
gameController.addReceiver(emulatorCore, inputMapping: inputMapping)
}
else
{
gameController.addReceiver(self)
gameController.addReceiver(emulatorCore)
}
}
else
{
gameController.removeReceiver(self)
gameController.removeReceiver(emulatorCore)
}
}
}
}
func updateControllerSkin()
@ -751,7 +761,7 @@ extension GameViewController
do
{
if let quickSaveState = try fetchRequest.execute().first
if let quickSaveState = try DatabaseManager.shared.viewContext.fetch(fetchRequest).first
{
self.load(quickSaveState)
}

View File

@ -22,7 +22,6 @@ extension ControllersSettingsViewController
}
}
private class LocalDeviceController: NSObject, GameController
{
var name: String {
@ -49,8 +48,17 @@ class ControllersSettingsViewController: UITableViewController
fileprivate var gameController: GameController? {
didSet {
oldValue?.playerIndex = nil
self.gameController?.playerIndex = self.playerIndex
// 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
self.gameController?.playerIndex = self.playerIndex
}
}
}
@ -150,7 +158,7 @@ private extension ControllersSettingsViewController
cell.accessoryType = .checkmark
}
else
{
{
if let playerIndex = controller.playerIndex
{
cell.detailTextLabel?.text = NSLocalizedString("Player \(playerIndex + 1)", comment: "")
@ -183,14 +191,29 @@ private extension ControllersSettingsViewController
if let index = self.connectedControllers.index(where: { $0 == controller })
{
self.tableView.beginUpdates()
if self.connectedControllers.count == 1
{
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
{
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.tableView.beginUpdates()
if self.connectedControllers.count == 0
{
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
{
self.tableView.deleteRows(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)
}
}
}
@ -240,7 +273,7 @@ extension ControllersSettingsViewController
{
switch Section(rawValue: section)!
{
case .none: return 1
case .none: return 0
case .localDevice: return 1
case .externalControllers: return self.connectedControllers.count
case .customizeControls: return 1
@ -266,6 +299,16 @@ extension ControllersSettingsViewController
case .customizeControls: return nil
}
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
if section == Section.none.rawValue
{
return 1
}
return UITableViewAutomaticDimension
}
}
extension ControllersSettingsViewController
@ -315,8 +358,7 @@ extension ControllersSettingsViewController
}
self.tableView.reloadRows(at: [indexPath], with: .none)
if self.numberOfSections(in: self.tableView) > self.tableView.numberOfSections
{
self.tableView.insertSections(IndexSet(integer: Section.customizeControls.rawValue), with: .fade)

View File

@ -40,12 +40,14 @@ struct Settings
/// Controllers
static var localControllerPlayerIndex: Int? = 0 {
didSet {
guard self.localControllerPlayerIndex != oldValue else { return }
NotificationCenter.default.post(name: .settingsDidChange, object: nil, userInfo: [NotificationUserInfoKey.name: Name.localControllerPlayerIndex])
}
}
static var translucentControllerSkinOpacity: CGFloat {
set {
guard newValue != self.translucentControllerSkinOpacity else { return }
UserDefaults.standard.translucentControllerSkinOpacity = newValue
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)
{
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)
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 previousSelectedRowIndexPath: IndexPath?
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
@ -62,7 +64,7 @@ class SettingsViewController: UITableViewController
{
super.viewWillAppear(animated)
if let indexPath = self.tableView.indexPathForSelectedRow
if let indexPath = self.previousSelectedRowIndexPath
{
if indexPath.section == Section.controllers.rawValue
{
@ -89,6 +91,8 @@ class SettingsViewController: UITableViewController
let indexPath = self.tableView.indexPath(for: cell)
else { return }
self.previousSelectedRowIndexPath = indexPath
switch segueType
{
case Segue.controllers: