Merge branch 'feature/iphone_x' into develop
This commit is contained in:
commit
d30f4db894
@ -1 +1 @@
|
|||||||
Subproject commit d7213260852683ea5a3f6c2274733bbd65d2ec92
|
Subproject commit 6658b7a7557278c9b846466a0599462c1aeb870b
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 7babfcf93a32916ad06989c9a63681acf7f07d50
|
Subproject commit 54d064d34a4d856fd34a49308f42f1aefac8eaad
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 9d714254ace7bd5d63805d434f4ccd1f2a947951
|
Subproject commit 9c295a2a287821544fec4b29d2b3f1205f965275
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit a354c3700fc4576bbefb6a8324bcd7a121d9b934
|
Subproject commit a3f0547bc57c14b548105020136a9ead56f73470
|
||||||
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13528" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ssH-mM-uG6">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ssH-mM-uG6">
|
||||||
<device id="retina4_7" orientation="portrait">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13526"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@ -200,7 +200,7 @@
|
|||||||
<action selector="didFinishChangingControllerOpacityWith:" destination="eHi-aO-uGS" eventType="touchUpOutside" id="xBn-FJ-5S0"/>
|
<action selector="didFinishChangingControllerOpacityWith:" destination="eHi-aO-uGS" eventType="touchUpOutside" id="xBn-FJ-5S0"/>
|
||||||
</connections>
|
</connections>
|
||||||
</slider>
|
</slider>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="50%" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zaz-yD-CYG">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="50%" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zaz-yD-CYG">
|
||||||
<rect key="frame" x="16" y="11" width="46" height="21"/>
|
<rect key="frame" x="16" y="11" width="46" height="21"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="21" id="ACD-qY-k0J"/>
|
<constraint firstAttribute="height" constant="21" id="ACD-qY-k0J"/>
|
||||||
@ -387,7 +387,7 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5r7-OQ-i7w">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5r7-OQ-i7w">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
@ -410,7 +410,7 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="XY1-es-oZe">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="XY1-es-oZe">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
|||||||
@ -23,22 +23,52 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
// If only one row, distribute the items equally horizontally
|
// If only one row, distribute the items equally horizontally
|
||||||
var usesEqualHorizontalSpacingDistributionForSingleRow = false
|
var usesEqualHorizontalSpacingDistributionForSingleRow = false
|
||||||
|
|
||||||
|
private var contentInset: UIEdgeInsets {
|
||||||
|
guard let collectionView = self.collectionView else { return .zero }
|
||||||
|
|
||||||
|
var contentInset = collectionView.contentInset
|
||||||
|
if #available(iOS 11, *)
|
||||||
|
{
|
||||||
|
contentInset.left += collectionView.safeAreaInsets.left
|
||||||
|
contentInset.right += collectionView.safeAreaInsets.right
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentInset
|
||||||
|
}
|
||||||
|
|
||||||
|
private var contentWidth: CGFloat {
|
||||||
|
guard let collectionView = self.collectionView else { return 0.0 }
|
||||||
|
|
||||||
|
let contentWidth = collectionView.bounds.width - (self.contentInset.left + self.contentInset.right)
|
||||||
|
return contentWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
private var maximumItemsPerRow: Int {
|
||||||
|
let maximumItemsPerRow = Int(floor((self.contentWidth - self.minimumInteritemSpacing) / (self.itemWidth + self.minimumInteritemSpacing)))
|
||||||
|
return maximumItemsPerRow
|
||||||
|
}
|
||||||
|
|
||||||
|
private var interitemSpacing: CGFloat {
|
||||||
|
let interitemSpacing = (self.contentWidth - CGFloat(self.maximumItemsPerRow) * self.itemWidth) / CGFloat(self.maximumItemsPerRow + 1)
|
||||||
|
return interitemSpacing
|
||||||
|
}
|
||||||
|
|
||||||
override var estimatedItemSize: CGSize {
|
override var estimatedItemSize: CGSize {
|
||||||
didSet {
|
didSet {
|
||||||
fatalError("GridCollectionViewLayout does not support self-sizing cells.")
|
fatalError("GridCollectionViewLayout does not support self-sizing cells.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func prepare()
|
||||||
|
{
|
||||||
|
super.prepare()
|
||||||
|
|
||||||
|
self.sectionInset.left = self.interitemSpacing + self.contentInset.left
|
||||||
|
self.sectionInset.right = self.interitemSpacing + self.contentInset.right
|
||||||
|
}
|
||||||
|
|
||||||
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
|
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
|
||||||
{
|
{
|
||||||
guard let collectionView = self.collectionView else { return nil }
|
|
||||||
|
|
||||||
let maximumItemsPerRow = floor((collectionView.bounds.width - self.minimumInteritemSpacing) / (self.itemWidth + self.minimumInteritemSpacing))
|
|
||||||
let interitemSpacing = (collectionView.bounds.width - maximumItemsPerRow * self.itemWidth) / (maximumItemsPerRow + 1)
|
|
||||||
|
|
||||||
self.sectionInset.left = interitemSpacing
|
|
||||||
self.sectionInset.right = interitemSpacing
|
|
||||||
|
|
||||||
let layoutAttributes = super.layoutAttributesForElements(in: rect)?.map({ $0.copy() }) as! [UICollectionViewLayoutAttributes]
|
let layoutAttributes = super.layoutAttributesForElements(in: rect)?.map({ $0.copy() }) as! [UICollectionViewLayoutAttributes]
|
||||||
|
|
||||||
var minimumY: CGFloat? = nil
|
var minimumY: CGFloat? = nil
|
||||||
@ -58,7 +88,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
|
|
||||||
if abs(attributes.frame.minX - self.sectionInset.left) > 1
|
if abs(attributes.frame.minX - self.sectionInset.left) > 1
|
||||||
{
|
{
|
||||||
attributes.frame.origin.x = previousLayoutAttributes.frame.maxX + interitemSpacing
|
attributes.frame.origin.x = previousLayoutAttributes.frame.maxX + self.interitemSpacing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +100,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
{
|
{
|
||||||
isSingleRow = false
|
isSingleRow = false
|
||||||
|
|
||||||
self.alignLayoutAttributes(tempLayoutAttributes, toMinimumY: minY)
|
self.align(tempLayoutAttributes, toMinimumY: minY)
|
||||||
|
|
||||||
// Reset tempLayoutAttributes
|
// Reset tempLayoutAttributes
|
||||||
tempLayoutAttributes.removeAll()
|
tempLayoutAttributes.removeAll()
|
||||||
@ -97,15 +127,15 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
// Handle the remaining tempLayoutAttributes
|
// Handle the remaining tempLayoutAttributes
|
||||||
if let minimumY = minimumY
|
if let minimumY = minimumY
|
||||||
{
|
{
|
||||||
self.alignLayoutAttributes(tempLayoutAttributes, toMinimumY: minimumY)
|
self.align(tempLayoutAttributes, toMinimumY: minimumY)
|
||||||
|
|
||||||
if isSingleRow && self.usesEqualHorizontalSpacingDistributionForSingleRow
|
if isSingleRow && self.usesEqualHorizontalSpacingDistributionForSingleRow
|
||||||
{
|
{
|
||||||
let spacing = (collectionView.bounds.width - (self.itemWidth * CGFloat(tempLayoutAttributes.count))) / (CGFloat(tempLayoutAttributes.count) + 1.0)
|
let spacing = (self.contentWidth - (self.itemWidth * CGFloat(tempLayoutAttributes.count))) / (CGFloat(tempLayoutAttributes.count) + 1.0)
|
||||||
|
|
||||||
for (index, layoutAttributes) in tempLayoutAttributes.enumerated()
|
for (index, layoutAttributes) in tempLayoutAttributes.enumerated()
|
||||||
{
|
{
|
||||||
layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index)
|
layoutAttributes.frame.origin.x = spacing + (spacing + self.itemWidth) * CGFloat(index) + self.contentInset.left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +147,7 @@ class GridCollectionViewLayout: UICollectionViewFlowLayout
|
|||||||
|
|
||||||
private extension GridCollectionViewLayout
|
private extension GridCollectionViewLayout
|
||||||
{
|
{
|
||||||
func alignLayoutAttributes(_ layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
|
func align(_ layoutAttributes: [UICollectionViewLayoutAttributes], toMinimumY minimumY: CGFloat)
|
||||||
{
|
{
|
||||||
for attributes in layoutAttributes
|
for attributes in layoutAttributes
|
||||||
{
|
{
|
||||||
|
|||||||
@ -65,12 +65,12 @@ class LoadControllerSkinImageOperation: RSTLoadOperation<UIImage, ControllerSkin
|
|||||||
|
|
||||||
override func loadResult(completion: @escaping (UIImage?, Swift.Error?) -> Void)
|
override func loadResult(completion: @escaping (UIImage?, Swift.Error?) -> Void)
|
||||||
{
|
{
|
||||||
guard self.controllerSkin.supports(self.traits) else {
|
guard let traits = self.controllerSkin.supportedTraits(for: self.traits) else {
|
||||||
completion(nil, Error.unsupportedTraits)
|
completion(nil, Error.unsupportedTraits)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let image = self.controllerSkin.image(for: self.traits, preferredSize: self.size) else {
|
guard let image = self.controllerSkin.image(for: traits, preferredSize: self.size) else {
|
||||||
completion(nil, Error.doesNotExist)
|
completion(nil, Error.doesNotExist)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,37 +14,14 @@ extension ControllerSkinConfigurations
|
|||||||
{
|
{
|
||||||
init(traits: DeltaCore.ControllerSkin.Traits)
|
init(traits: DeltaCore.ControllerSkin.Traits)
|
||||||
{
|
{
|
||||||
switch traits.deviceType
|
switch (traits.displayType, traits.orientation)
|
||||||
{
|
{
|
||||||
case .iphone:
|
case (.standard, .portrait): self = .standardPortrait
|
||||||
|
case (.standard, .landscape): self = .standardLandscape
|
||||||
switch traits.orientation
|
case (.edgeToEdge, .portrait): self = .edgeToEdgePortrait
|
||||||
{
|
case (.edgeToEdge, .landscape): self = .edgeToEdgeLandscape
|
||||||
case .portrait: self = .fullScreenPortrait
|
case (.splitView, .portrait): self = .splitViewPortrait
|
||||||
case .landscape: self = .fullScreenLandscape
|
case (.splitView, .landscape): self = .splitViewLandscape
|
||||||
}
|
|
||||||
|
|
||||||
case .ipad:
|
|
||||||
|
|
||||||
switch traits.displayMode
|
|
||||||
{
|
|
||||||
case .fullScreen:
|
|
||||||
|
|
||||||
switch traits.orientation
|
|
||||||
{
|
|
||||||
case .portrait: self = .fullScreenPortrait
|
|
||||||
case .landscape: self = .fullScreenLandscape
|
|
||||||
}
|
|
||||||
|
|
||||||
case .splitView:
|
|
||||||
|
|
||||||
switch traits.orientation
|
|
||||||
{
|
|
||||||
case .portrait: self = .splitViewPortrait
|
|
||||||
case .landscape: self = .splitViewLandscape
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,11 +11,14 @@
|
|||||||
|
|
||||||
typedef NS_OPTIONS(int16_t, ControllerSkinConfigurations)
|
typedef NS_OPTIONS(int16_t, ControllerSkinConfigurations)
|
||||||
{
|
{
|
||||||
ControllerSkinConfigurationFullScreenPortrait = 1 << 0,
|
ControllerSkinConfigurationStandardPortrait = 1 << 0,
|
||||||
ControllerSkinConfigurationFullScreenLandscape = 1 << 1,
|
ControllerSkinConfigurationStandardLandscape = 1 << 1,
|
||||||
|
|
||||||
ControllerSkinConfigurationSplitViewPortrait = 1 << 2,
|
ControllerSkinConfigurationSplitViewPortrait = 1 << 2,
|
||||||
ControllerSkinConfigurationSplitViewLandscape = 1 << 3,
|
ControllerSkinConfigurationSplitViewLandscape = 1 << 3,
|
||||||
|
|
||||||
|
ControllerSkinConfigurationEdgeToEdgePortrait = 1 << 4,
|
||||||
|
ControllerSkinConfigurationEdgeToEdgeLandscape = 1 << 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ControllerSkinConfigurations_h */
|
#endif /* ControllerSkinConfigurations_h */
|
||||||
|
|||||||
@ -192,6 +192,8 @@ extension GameViewController
|
|||||||
|
|
||||||
let gameViewContainerView = self.gameView.superview!
|
let gameViewContainerView = self.gameView.superview!
|
||||||
|
|
||||||
|
self.controllerView.translucentControllerSkinOpacity = Settings.translucentControllerSkinOpacity
|
||||||
|
|
||||||
self.sustainButtonsContentView = UIView(frame: CGRect(x: 0, y: 0, width: self.gameView.bounds.width, height: self.gameView.bounds.height))
|
self.sustainButtonsContentView = UIView(frame: CGRect(x: 0, y: 0, width: self.gameView.bounds.width, height: self.gameView.bounds.height))
|
||||||
self.sustainButtonsContentView.translatesAutoresizingMaskIntoConstraints = false
|
self.sustainButtonsContentView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
self.sustainButtonsContentView.isHidden = true
|
self.sustainButtonsContentView.isHidden = true
|
||||||
@ -438,21 +440,12 @@ private extension GameViewController
|
|||||||
|
|
||||||
func updateControllerSkin()
|
func updateControllerSkin()
|
||||||
{
|
{
|
||||||
guard let game = self.game, let system = System(gameType: game.type) else { return }
|
guard let game = self.game, let system = System(gameType: game.type), let window = self.view.window else { return }
|
||||||
|
|
||||||
let traits = DeltaCore.ControllerSkin.Traits.defaults(for: self.view)
|
let traits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
|
||||||
|
|
||||||
let controllerSkin = Settings.preferredControllerSkin(for: system, traits: traits)
|
let controllerSkin = Settings.preferredControllerSkin(for: system, traits: traits)
|
||||||
self.controllerView.controllerSkin = controllerSkin
|
self.controllerView.controllerSkin = controllerSkin
|
||||||
|
|
||||||
if controllerSkin?.isTranslucent(for: traits) ?? false
|
|
||||||
{
|
|
||||||
self.controllerView.alpha = Settings.translucentControllerSkinOpacity
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.controllerView.alpha = 1.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,21 +846,13 @@ private extension GameViewController
|
|||||||
let system = notification.userInfo?[Settings.NotificationUserInfoKey.system] as? System,
|
let system = notification.userInfo?[Settings.NotificationUserInfoKey.system] as? System,
|
||||||
let traits = notification.userInfo?[Settings.NotificationUserInfoKey.traits] as? DeltaCore.ControllerSkin.Traits
|
let traits = notification.userInfo?[Settings.NotificationUserInfoKey.traits] as? DeltaCore.ControllerSkin.Traits
|
||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
let currentTraits = DeltaCore.ControllerSkin.Traits.defaults(for: self.view)
|
if system.gameType == self.game?.type && traits.orientation == self.controllerView.controllerSkinTraits?.orientation
|
||||||
if system.gameType == self.game?.type && traits == currentTraits
|
|
||||||
{
|
{
|
||||||
self.updateControllerSkin()
|
self.updateControllerSkin()
|
||||||
}
|
}
|
||||||
|
|
||||||
case .translucentControllerSkinOpacity:
|
case .translucentControllerSkinOpacity: self.controllerView.translucentControllerSkinOpacity = Settings.translucentControllerSkinOpacity
|
||||||
if let traits = self.controllerView.controllerSkinTraits
|
|
||||||
{
|
|
||||||
if self.controllerView.controllerSkin?.isTranslucent(for: traits) ?? false
|
|
||||||
{
|
|
||||||
self.controllerView.alpha = Settings.translucentControllerSkinOpacity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,54 +20,18 @@ extension ControllerSkin
|
|||||||
|
|
||||||
var configurations = ControllerSkinConfigurations()
|
var configurations = ControllerSkinConfigurations()
|
||||||
|
|
||||||
if UIDevice.current.userInterfaceIdiom == .pad
|
let device: DeltaCore.ControllerSkin.Device = (UIDevice.current.userInterfaceIdiom == .pad) ? .ipad : .iphone
|
||||||
|
|
||||||
|
let traitCollections: [(displayType: DeltaCore.ControllerSkin.DisplayType, orientation: DeltaCore.ControllerSkin.Orientation)] =
|
||||||
|
[(.standard, .portrait), (.standard, .landscape), (.edgeToEdge, .portrait), (.edgeToEdge, .landscape), (.splitView, .portrait), (.splitView, .landscape)]
|
||||||
|
|
||||||
|
for collection in traitCollections
|
||||||
{
|
{
|
||||||
var portraitTraits = DeltaCore.ControllerSkin.Traits(deviceType: .ipad, displayMode: .fullScreen, orientation: .portrait)
|
let traits = DeltaCore.ControllerSkin.Traits(device: device, displayType: collection.displayType, orientation: collection.orientation)
|
||||||
|
if skin.supports(traits)
|
||||||
var landscapeTraits = portraitTraits
|
|
||||||
landscapeTraits.orientation = .landscape
|
|
||||||
|
|
||||||
|
|
||||||
if skin.supports(portraitTraits)
|
|
||||||
{
|
{
|
||||||
configurations.formUnion(.fullScreenPortrait)
|
let configuration = ControllerSkinConfigurations(traits: traits)
|
||||||
}
|
configurations.formUnion(configuration)
|
||||||
|
|
||||||
if skin.supports(landscapeTraits)
|
|
||||||
{
|
|
||||||
configurations.formUnion(.fullScreenLandscape)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
portraitTraits.displayMode = .splitView
|
|
||||||
landscapeTraits.displayMode = .splitView
|
|
||||||
|
|
||||||
|
|
||||||
if skin.supports(portraitTraits)
|
|
||||||
{
|
|
||||||
configurations.formUnion(.splitViewPortrait)
|
|
||||||
}
|
|
||||||
|
|
||||||
if skin.supports(landscapeTraits)
|
|
||||||
{
|
|
||||||
configurations.formUnion(.splitViewLandscape)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
let portraitTraits = DeltaCore.ControllerSkin.Traits(deviceType: .iphone, displayMode: .fullScreen, orientation: .portrait)
|
|
||||||
|
|
||||||
var landscapeTraits = portraitTraits
|
|
||||||
landscapeTraits.orientation = .landscape
|
|
||||||
|
|
||||||
if skin.supports(portraitTraits)
|
|
||||||
{
|
|
||||||
configurations.formUnion(.fullScreenPortrait)
|
|
||||||
}
|
|
||||||
|
|
||||||
if skin.supports(landscapeTraits)
|
|
||||||
{
|
|
||||||
configurations.formUnion(.fullScreenLandscape)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,10 @@ class LaunchViewController: UIViewController
|
|||||||
return self.gameViewController?.prefersStatusBarHidden ?? false
|
return self.gameViewController?.prefersStatusBarHidden ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func childViewControllerForHomeIndicatorAutoHidden() -> UIViewController? {
|
||||||
|
return self.gameViewController
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool)
|
override func viewDidAppear(_ animated: Bool)
|
||||||
{
|
{
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class PausePresentationController: UIPresentationController
|
|||||||
{
|
{
|
||||||
guard let containerView = self.containerView else { return super.frameOfPresentedViewInContainerView }
|
guard let containerView = self.containerView else { return super.frameOfPresentedViewInContainerView }
|
||||||
|
|
||||||
let frame: CGRect
|
var frame: CGRect
|
||||||
let contentHeight = self.presentedViewController.preferredContentSize.height
|
let contentHeight = self.presentedViewController.preferredContentSize.height
|
||||||
|
|
||||||
if contentHeight == 0
|
if contentHeight == 0
|
||||||
@ -44,6 +44,11 @@ class PausePresentationController: UIPresentationController
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
frame = CGRect(x: 0, y: containerView.bounds.height - contentHeight, width: containerView.bounds.width, height: containerView.bounds.height)
|
frame = CGRect(x: 0, y: containerView.bounds.height - contentHeight, width: containerView.bounds.width, height: containerView.bounds.height)
|
||||||
|
|
||||||
|
if #available(iOS 11.0, *)
|
||||||
|
{
|
||||||
|
frame.origin.y -= containerView.safeAreaInsets.bottom
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame
|
return frame
|
||||||
|
|||||||
@ -101,7 +101,7 @@ extension SaveStatesViewController
|
|||||||
|
|
||||||
// Use dimensions that allow two cells to fill the screen horizontally with padding in portrait mode
|
// Use dimensions that allow two cells to fill the screen horizontally with padding in portrait mode
|
||||||
// We'll keep the same size for landscape orientation, which will allow more to fit
|
// We'll keep the same size for landscape orientation, which will allow more to fit
|
||||||
collectionViewLayout.itemWidth = (portraitScreenWidth - (averageHorizontalInset * 3)) / 2
|
collectionViewLayout.itemWidth = floor((portraitScreenWidth - (averageHorizontalInset * 3)) / 2)
|
||||||
|
|
||||||
switch self.mode
|
switch self.mode
|
||||||
{
|
{
|
||||||
|
|||||||
@ -100,7 +100,24 @@ private extension ControllerSkinsViewController
|
|||||||
let configuration = ControllerSkinConfigurations(traits: traits)
|
let configuration = ControllerSkinConfigurations(traits: traits)
|
||||||
|
|
||||||
let fetchRequest: NSFetchRequest<ControllerSkin> = ControllerSkin.fetchRequest()
|
let fetchRequest: NSFetchRequest<ControllerSkin> = ControllerSkin.fetchRequest()
|
||||||
fetchRequest.predicate = NSPredicate(format: "%K == %@ AND (%K & %d) == %d", #keyPath(ControllerSkin.gameType), system.gameType.rawValue, #keyPath(ControllerSkin.supportedConfigurations), configuration.rawValue, configuration.rawValue)
|
|
||||||
|
if traits.device == .iphone && traits.displayType == .edgeToEdge
|
||||||
|
{
|
||||||
|
let fallbackConfiguration: ControllerSkinConfigurations = (traits.orientation == .landscape) ? .standardLandscape : .standardPortrait
|
||||||
|
|
||||||
|
// Allow selecting skins that only support standard display types as well.
|
||||||
|
fetchRequest.predicate = NSPredicate(format: "%K == %@ AND ((%K & %d) != 0 OR (%K & %d) != 0)",
|
||||||
|
#keyPath(ControllerSkin.gameType), system.gameType.rawValue,
|
||||||
|
#keyPath(ControllerSkin.supportedConfigurations), configuration.rawValue,
|
||||||
|
#keyPath(ControllerSkin.supportedConfigurations), fallbackConfiguration.rawValue)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fetchRequest.predicate = NSPredicate(format: "%K == %@ AND (%K & %d) != 0",
|
||||||
|
#keyPath(ControllerSkin.gameType), system.gameType.rawValue,
|
||||||
|
#keyPath(ControllerSkin.supportedConfigurations), configuration.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(ControllerSkin.isStandard), ascending: false), NSSortDescriptor(key: #keyPath(ControllerSkin.name), ascending: true)]
|
fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(ControllerSkin.isStandard), ascending: false), NSSortDescriptor(key: #keyPath(ControllerSkin.name), ascending: true)]
|
||||||
|
|
||||||
self.dataSource.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext, sectionNameKeyPath: #keyPath(ControllerSkin.name), cacheName: nil)
|
self.dataSource.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext, sectionNameKeyPath: #keyPath(ControllerSkin.name), cacheName: nil)
|
||||||
@ -130,11 +147,11 @@ extension ControllerSkinsViewController
|
|||||||
{
|
{
|
||||||
let controllerSkin = self.dataSource.item(at: indexPath)
|
let controllerSkin = self.dataSource.item(at: indexPath)
|
||||||
|
|
||||||
guard let size = controllerSkin.aspectRatio(for: self.traits) else { return 150 }
|
guard let traits = controllerSkin.supportedTraits(for: self.traits), let size = controllerSkin.aspectRatio(for: traits) else { return 150 }
|
||||||
|
|
||||||
let scale = (self.view.bounds.width / size.width)
|
let scale = (self.view.bounds.width / size.width)
|
||||||
|
|
||||||
let height = size.height * scale
|
let height = min(size.height * scale, self.view.bounds.height - self.topLayoutGuide.length - self.bottomLayoutGuide.length - 30)
|
||||||
|
|
||||||
return height
|
return height
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,8 @@ class SystemControllerSkinsViewController: UITableViewController
|
|||||||
|
|
||||||
@IBOutlet private var portraitImageView: UIImageView!
|
@IBOutlet private var portraitImageView: UIImageView!
|
||||||
@IBOutlet private var landscapeImageView: UIImageView!
|
@IBOutlet private var landscapeImageView: UIImageView!
|
||||||
|
|
||||||
|
private var _previousBoundsSize: CGSize?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SystemControllerSkinsViewController
|
extension SystemControllerSkinsViewController
|
||||||
@ -35,27 +37,31 @@ extension SystemControllerSkinsViewController
|
|||||||
|
|
||||||
self.title = self.system.localizedShortName
|
self.title = self.system.localizedShortName
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool)
|
|
||||||
{
|
|
||||||
self.updateControllerSkins()
|
|
||||||
|
|
||||||
super.viewWillAppear(animated)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func didReceiveMemoryWarning()
|
override func didReceiveMemoryWarning()
|
||||||
{
|
{
|
||||||
super.didReceiveMemoryWarning()
|
super.didReceiveMemoryWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidLayoutSubviews()
|
||||||
|
{
|
||||||
|
super.viewDidLayoutSubviews()
|
||||||
|
|
||||||
|
if self.view.bounds.size != self._previousBoundsSize
|
||||||
|
{
|
||||||
|
self.updateControllerSkins()
|
||||||
|
self.tableView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
||||||
{
|
{
|
||||||
guard let cell = sender as? UITableViewCell, let indexPath = self.tableView.indexPath(for: cell) else { return }
|
guard let cell = sender as? UITableViewCell, let indexPath = self.tableView.indexPath(for: cell), let window = self.view.window else { return }
|
||||||
|
|
||||||
let controllerSkinsViewController = segue.destination as! ControllerSkinsViewController
|
let controllerSkinsViewController = segue.destination as! ControllerSkinsViewController
|
||||||
controllerSkinsViewController.system = self.system
|
controllerSkinsViewController.system = self.system
|
||||||
|
|
||||||
var traits = DeltaCore.ControllerSkin.Traits.defaults(for: self.view)
|
var traits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
|
||||||
|
|
||||||
let section = Section(rawValue: indexPath.section)!
|
let section = Section(rawValue: indexPath.section)!
|
||||||
switch section
|
switch section
|
||||||
@ -86,7 +92,7 @@ extension SystemControllerSkinsViewController
|
|||||||
|
|
||||||
let scale = (self.view.bounds.width / unwrappedImageSize.width)
|
let scale = (self.view.bounds.width / unwrappedImageSize.width)
|
||||||
|
|
||||||
let height = unwrappedImageSize.height * scale
|
let height = min(unwrappedImageSize.height * scale, self.view.bounds.height - self.topLayoutGuide.length - self.bottomLayoutGuide.length - 30)
|
||||||
return height
|
return height
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +108,17 @@ private extension SystemControllerSkinsViewController
|
|||||||
{
|
{
|
||||||
func updateControllerSkins()
|
func updateControllerSkins()
|
||||||
{
|
{
|
||||||
let portraitTraits = DeltaCore.ControllerSkin.Traits(deviceType: .iphone, displayMode: DeltaCore.ControllerSkin.DisplayMode.fullScreen, orientation: .portrait)
|
guard let window = self.view.window else { return }
|
||||||
let landscapeTraits = DeltaCore.ControllerSkin.Traits(deviceType: .iphone, displayMode: DeltaCore.ControllerSkin.DisplayMode.fullScreen, orientation: .landscape)
|
|
||||||
|
self._previousBoundsSize = self.view.bounds.size
|
||||||
|
|
||||||
|
let defaultTraits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
|
||||||
|
|
||||||
|
var portraitTraits = defaultTraits
|
||||||
|
portraitTraits.orientation = .portrait
|
||||||
|
|
||||||
|
var landscapeTraits = defaultTraits
|
||||||
|
landscapeTraits.orientation = .landscape
|
||||||
|
|
||||||
let portraitControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: portraitTraits)
|
let portraitControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: portraitTraits)
|
||||||
let landscapeControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: landscapeTraits)
|
let landscapeControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: landscapeTraits)
|
||||||
|
|||||||
@ -145,15 +145,16 @@ private extension Settings
|
|||||||
case .landscape: orientation = "landscape"
|
case .landscape: orientation = "landscape"
|
||||||
}
|
}
|
||||||
|
|
||||||
let displayMode: String
|
let displayType: String
|
||||||
|
|
||||||
switch traits.displayMode
|
switch traits.displayType
|
||||||
{
|
{
|
||||||
case .fullScreen: displayMode = "fullscreen"
|
case .standard: displayType = "standard"
|
||||||
case .splitView: displayMode = "splitview"
|
case .edgeToEdge: displayType = "standard" // In this context, standard and edge-to-edge skins are treated the same.
|
||||||
|
case .splitView: displayType = "splitview"
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = systemName + "-" + orientation + "-" + displayMode + "-controller"
|
let key = systemName + "-" + orientation + "-" + displayType + "-controller"
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user