diff --git a/Cores/DeltaCore b/Cores/DeltaCore index 97e51f6..3373709 160000 --- a/Cores/DeltaCore +++ b/Cores/DeltaCore @@ -1 +1 @@ -Subproject commit 97e51f6ea5935d3ce2d15be796b189bcc70dbbb3 +Subproject commit 3373709956dc2be70563582ba7e308677bb964fa diff --git a/Cores/GBADeltaCore b/Cores/GBADeltaCore index acbcf2b..6c763da 160000 --- a/Cores/GBADeltaCore +++ b/Cores/GBADeltaCore @@ -1 +1 @@ -Subproject commit acbcf2baf8f01302f2a7c6e60783b887160aa163 +Subproject commit 6c763da1513fbe762edbca2cf33cec556ce9536e diff --git a/Cores/GBCDeltaCore b/Cores/GBCDeltaCore index c8084ce..4dcb34a 160000 --- a/Cores/GBCDeltaCore +++ b/Cores/GBCDeltaCore @@ -1 +1 @@ -Subproject commit c8084cee111501c0daffd113f5892050d7738519 +Subproject commit 4dcb34a47e71b81a099bff4dc0ebd28c217ef85b diff --git a/Cores/NESDeltaCore b/Cores/NESDeltaCore index 7ed452b..4dc0f28 160000 --- a/Cores/NESDeltaCore +++ b/Cores/NESDeltaCore @@ -1 +1 @@ -Subproject commit 7ed452b7dff25a68cd503610bee1f3e36216a871 +Subproject commit 4dc0f283116aadf6397c88c1f7fdabcac32367a6 diff --git a/Cores/SNESDeltaCore b/Cores/SNESDeltaCore index d794f67..dc0ec5b 160000 --- a/Cores/SNESDeltaCore +++ b/Cores/SNESDeltaCore @@ -1 +1 @@ -Subproject commit d794f67cdba072f8a9977fb76e8ccaaac09946c0 +Subproject commit dc0ec5b74c0e47e0e35912dfd63dd70f2a3d932e diff --git a/Delta/Base.lproj/Settings.storyboard b/Delta/Base.lproj/Settings.storyboard index a2b7c9f..1174492 100644 --- a/Delta/Base.lproj/Settings.storyboard +++ b/Delta/Base.lproj/Settings.storyboard @@ -372,7 +372,7 @@ - + diff --git a/Delta/Database/Model/Human/ControllerSkin.swift b/Delta/Database/Model/Human/ControllerSkin.swift index 6bd7b4d..c63d2cd 100644 --- a/Delta/Database/Model/Human/ControllerSkin.swift +++ b/Delta/Database/Model/Human/ControllerSkin.swift @@ -66,6 +66,11 @@ extension ControllerSkin: ControllerSkinProtocol return self.controllerSkin?.image(for: traits, preferredSize: preferredSize) } + public func thumbstick(for item: DeltaCore.ControllerSkin.Item, traits: DeltaCore.ControllerSkin.Traits, preferredSize: DeltaCore.ControllerSkin.Size) -> (UIImage, CGSize)? + { + return self.controllerSkin?.thumbstick(for: item, traits: traits, preferredSize: preferredSize) + } + public func inputs(for traits: DeltaCore.ControllerSkin.Traits, at point: CGPoint) -> [Input]? { return self.controllerSkin?.inputs(for: traits, at: point) diff --git a/Delta/Emulation/GameViewController.swift b/Delta/Emulation/GameViewController.swift index 18c3aba..19fdd5d 100644 --- a/Delta/Emulation/GameViewController.swift +++ b/Delta/Emulation/GameViewController.swift @@ -114,9 +114,7 @@ class GameViewController: DeltaCore.GameViewController } private var _isLoadingSaveState = false - - private var context = CIContext(options: [.workingColorSpace: NSNull()]) - + // Sustain Buttons private var isSelectingSustainedButtons = false private var sustainInputsMapping: SustainInputsMapping? @@ -124,6 +122,7 @@ class GameViewController: DeltaCore.GameViewController private var sustainButtonsContentView: UIView! private var sustainButtonsBlurView: UIVisualEffectView! private var sustainButtonsBackgroundView: RSTPlaceholderView! + private var inputsToSustain = [AnyInput: Double]() private var isGyroActive = false private var presentedGyroAlert = false @@ -168,9 +167,9 @@ class GameViewController: DeltaCore.GameViewController } // MARK: - GameControllerReceiver - - override func gameController(_ gameController: GameController, didActivate input: Input) + override func gameController(_ gameController: GameController, didActivate input: Input, value: Double) { - super.gameController(gameController, didActivate: input) + super.gameController(gameController, didActivate: input, value: value) if self.isSelectingSustainedButtons { @@ -178,7 +177,7 @@ class GameViewController: DeltaCore.GameViewController if input != StandardGameControllerInput.menu { - gameController.sustain(input) + self.inputsToSustain[AnyInput(input)] = value } } else if self.emulatorCore?.state == .running @@ -198,15 +197,23 @@ class GameViewController: DeltaCore.GameViewController { super.gameController(gameController, didDeactivate: input) - guard !self.isSelectingSustainedButtons else { return } - - guard let actionInput = ActionInput(input: input) else { return } - - switch actionInput + if self.isSelectingSustainedButtons { - case .quickSave: break - case .quickLoad: break - case .fastForward: self.performFastForwardAction(activate: false) + if input.isContinuous + { + self.inputsToSustain[AnyInput(input)] = nil + } + } + else + { + guard let actionInput = ActionInput(input: input) else { return } + + switch actionInput + { + case .quickSave: break + case .quickLoad: break + case .fastForward: self.performFastForwardAction(activate: false) + } } } } @@ -320,7 +327,7 @@ extension GameViewController pauseViewController.sustainButtonsItem?.isSelected = gameController.sustainedInputs.count > 0 pauseViewController.sustainButtonsItem?.action = { [unowned self, unowned pauseViewController] item in - for input in gameController.sustainedInputs + for input in gameController.sustainedInputs.keys { gameController.unsustain(input) } @@ -650,10 +657,7 @@ extension GameViewController: SaveStatesViewControllerDelegate self.emulatorCore?.saveSaveState(to: saveState.fileURL) } - if - let outputImage = self.gameView.outputImage, - let quartzImage = self.context.createCGImage(outputImage, from: outputImage.extent), - let data = UIImage(cgImage: quartzImage).pngData() + if let snapshot = self.gameView.snapshot(), let data = snapshot.pngData() { do { @@ -803,10 +807,10 @@ private extension GameViewController self.updateControllers() self.sustainInputsMapping = nil - // Reactivate all sustained inputs, since they will now be mapped to game inputs. - for input in gameController.sustainedInputs + // Activate all sustained inputs, since they will now be mapped to game inputs. + for (input, value) in self.inputsToSustain { - gameController.activate(input) + gameController.sustain(input, value: value) } let blurEffect = self.sustainButtonsBlurView.effect @@ -818,6 +822,8 @@ private extension GameViewController self.sustainButtonsContentView.isHidden = true self.sustainButtonsBlurView.effect = blurEffect } + + self.inputsToSustain = [:] } } diff --git a/Delta/Settings/Controllers/ControllerInputsViewController.swift b/Delta/Settings/Controllers/ControllerInputsViewController.swift index c7bc2ba..b4a8cb3 100644 --- a/Delta/Settings/Controllers/ControllerInputsViewController.swift +++ b/Delta/Settings/Controllers/ControllerInputsViewController.swift @@ -123,6 +123,7 @@ private extension ControllerInputsViewController // Update controller view's controller skin. self.gameViewController.controllerView.controllerSkin = DeltaCore.ControllerSkin.standardControllerSkin(for: self.system.gameType) + self.gameViewController.view.setNeedsUpdateConstraints() // Fetch input mapping if it hasn't already been fetched. if let gameController = self.gameController, let playerIndex = gameController.playerIndex, self.inputMappings[self.system] == nil @@ -417,31 +418,32 @@ private extension ControllerInputsViewController { case .standard: itemFrame = item.frame case let .directional(up, down, left, right): + let frame = (item.kind == .thumbstick) ? item.extendedFrame : item.frame switch input.stringValue { case up.stringValue: - itemFrame = CGRect(x: item.frame.minX + item.frame.width / 3, - y: item.frame.minY, - width: item.frame.width / 3, - height: item.frame.height / 3) + itemFrame = CGRect(x: frame.minX + frame.width / 3, + y: frame.minY, + width: frame.width / 3, + height: frame.height / 3) case down.stringValue: - itemFrame = CGRect(x: item.frame.minX + item.frame.width / 3, - y: item.frame.minY + (item.frame.height / 3) * 2, - width: item.frame.width / 3, - height: item.frame.height / 3) + itemFrame = CGRect(x: frame.minX + frame.width / 3, + y: frame.minY + (frame.height / 3) * 2, + width: frame.width / 3, + height: frame.height / 3) case left.stringValue: - itemFrame = CGRect(x: item.frame.minX, - y: item.frame.minY + (item.frame.height / 3), - width: item.frame.width / 3, - height: item.frame.height / 3) + itemFrame = CGRect(x: frame.minX, + y: frame.minY + (frame.height / 3), + width: frame.width / 3, + height: frame.height / 3) case right.stringValue: - itemFrame = CGRect(x: item.frame.minX + (item.frame.width / 3) * 2, - y: item.frame.minY + (item.frame.height / 3), - width: item.frame.width / 3, - height: item.frame.height / 3) + itemFrame = CGRect(x: frame.minX + (frame.width / 3) * 2, + y: frame.minY + (frame.height / 3), + width: frame.width / 3, + height: frame.height / 3) default: itemFrame = nil } @@ -478,7 +480,7 @@ private extension ControllerInputsViewController extension ControllerInputsViewController: GameControllerReceiver { - func gameController(_ gameController: GameController, didActivate controllerInput: DeltaCore.Input) + func gameController(_ gameController: GameController, didActivate controllerInput: DeltaCore.Input, value: Double) { guard self.isViewLoaded else { return }