Automatically uses external game controllers when connected
This commit is contained in:
parent
61440ef994
commit
a58835e3ad
@ -1 +1 @@
|
||||
Subproject commit ff014bab5c42e5c0a5fcbacb5c3c737ef33564e7
|
||||
Subproject commit 6e0ec5aedac746d1a5ea05d450884f1a9ad7b509
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user