Adds ability to assign controller skins per game

This commit is contained in:
Riley Testut 2020-02-07 15:45:34 -08:00
parent cd7e9652ab
commit 0373b757f7
14 changed files with 479 additions and 92 deletions

View File

@ -31,7 +31,7 @@
BF13A7581D5D2FD9000BB055 /* EmulatorCore+Cheats.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF13A7571D5D2FD9000BB055 /* EmulatorCore+Cheats.swift */; };
BF15AF841F54B43B009B6AAB /* ActionInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF15AF831F54B43B009B6AAB /* ActionInput.swift */; };
BF18B61F1E2985F900F70067 /* UIAlertController+Importing.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF18B61E1E2985F900F70067 /* UIAlertController+Importing.swift */; };
BF1DAD5D1D9F576000E752A7 /* SystemControllerSkinsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1DAD5C1D9F576000E752A7 /* SystemControllerSkinsViewController.swift */; };
BF1DAD5D1D9F576000E752A7 /* PreferredControllerSkinsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1DAD5C1D9F576000E752A7 /* PreferredControllerSkinsViewController.swift */; };
BF1F45A421AF274D00EF9895 /* SyncResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1F45A321AF274D00EF9895 /* SyncResultViewController.swift */; };
BF1F45AB21AF4B5800EF9895 /* SyncResultsViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF1F45AA21AF4B5800EF9895 /* SyncResultsViewController.storyboard */; };
BF1F45AD21AF57BA00EF9895 /* HarmonyMetadataKey+Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF1F45AC21AF57BA00EF9895 /* HarmonyMetadataKey+Keys.swift */; };
@ -166,7 +166,7 @@
BF13A7571D5D2FD9000BB055 /* EmulatorCore+Cheats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EmulatorCore+Cheats.swift"; sourceTree = "<group>"; };
BF15AF831F54B43B009B6AAB /* ActionInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionInput.swift; sourceTree = "<group>"; };
BF18B61E1E2985F900F70067 /* UIAlertController+Importing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Importing.swift"; sourceTree = "<group>"; };
BF1DAD5C1D9F576000E752A7 /* SystemControllerSkinsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemControllerSkinsViewController.swift; sourceTree = "<group>"; };
BF1DAD5C1D9F576000E752A7 /* PreferredControllerSkinsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferredControllerSkinsViewController.swift; sourceTree = "<group>"; };
BF1F45A321AF274D00EF9895 /* SyncResultViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncResultViewController.swift; sourceTree = "<group>"; };
BF1F45AA21AF4B5800EF9895 /* SyncResultsViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SyncResultsViewController.storyboard; sourceTree = "<group>"; };
BF1F45AC21AF57BA00EF9895 /* HarmonyMetadataKey+Keys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "HarmonyMetadataKey+Keys.swift"; sourceTree = "<group>"; };
@ -287,6 +287,7 @@
BFDF71DA22F94CDF0074D92E /* DSDeltaCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = DSDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BFE0229F1F5B577D0052D888 /* PopoverMenuButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopoverMenuButton.swift; sourceTree = "<group>"; };
BFE4269D1D9C68E600DC913F /* SaveStatesStoryboardSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SaveStatesStoryboardSegue.swift; sourceTree = "<group>"; };
BFE4275223EDF75300E6B417 /* Delta 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Delta 5.xcdatamodel"; sourceTree = "<group>"; };
BFE56E1823EB7BE00014FECD /* UIImage+SymbolFallback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+SymbolFallback.swift"; sourceTree = "<group>"; };
BFE593C921F3F8B7003412A6 /* GameSave.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameSave.swift; sourceTree = "<group>"; };
BFE593CB21F3F8C2003412A6 /* _GameSave.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _GameSave.swift; sourceTree = "<group>"; };
@ -371,7 +372,7 @@
BF1DAD5B1D9F574900E752A7 /* Controller Skins */ = {
isa = PBXGroup;
children = (
BF1DAD5C1D9F576000E752A7 /* SystemControllerSkinsViewController.swift */,
BF1DAD5C1D9F576000E752A7 /* PreferredControllerSkinsViewController.swift */,
BF04E6FE1DB8625C000F35D3 /* ControllerSkinsViewController.swift */,
BF99A5961DC2F9C400468E9E /* ControllerSkinTableViewCell.swift */,
);
@ -1055,7 +1056,7 @@
BF1F45AD21AF57BA00EF9895 /* HarmonyMetadataKey+Keys.swift in Sources */,
BFD1EF402336BD8800D197CF /* UIDevice+Processor.swift in Sources */,
BF71CF871FE90006001F1613 /* AppIconShortcutsViewController.swift in Sources */,
BF1DAD5D1D9F576000E752A7 /* SystemControllerSkinsViewController.swift in Sources */,
BF1DAD5D1D9F576000E752A7 /* PreferredControllerSkinsViewController.swift in Sources */,
BFE022A01F5B57FF0052D888 /* PopoverMenuButton.swift in Sources */,
BF6BF31C1EB821A0008E83CD /* GamesDatabaseImportOption.swift in Sources */,
BFFA4C091E8A24D600D87934 /* GameTableViewCell.swift in Sources */,
@ -1374,12 +1375,13 @@
BF4828811F9027B600028B97 /* Delta.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
BFE4275223EDF75300E6B417 /* Delta 5.xcdatamodel */,
BF0758DE2202827C005110F2 /* Delta 4.xcdatamodel */,
BF5645092202381000A8EA26 /* Delta 3.xcdatamodel */,
BF4828821F9027B600028B97 /* Delta 2.xcdatamodel */,
BF4828831F9027B600028B97 /* Delta.xcdatamodel */,
);
currentVersion = BF0758DE2202827C005110F2 /* Delta 4.xcdatamodel */;
currentVersion = BFE4275223EDF75300E6B417 /* Delta 5.xcdatamodel */;
path = Delta.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;

View File

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="6bq-zy-UZU">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="6bq-zy-UZU">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -25,7 +23,7 @@
<navigationItem key="navigationItem" title="Games Database" id="rwF-kd-avR">
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="BnB-5n-Rff">
<connections>
<segue destination="mUU-ug-yNs" kind="unwind" unwindAction="unwindFromGamesDatabaseBrowserWith:" id="zdg-Az-WwQ"/>
<segue destination="mUU-ug-yNs" kind="unwind" unwindAction="unwindToGameCollectionViewController:" id="nzI-4n-kDg"/>
</connections>
</barButtonItem>
</navigationItem>
@ -41,7 +39,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="6bq-zy-UZU" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" id="uzY-vR-coL">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="SPq-Bk-fQl">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="SPq-Bk-fQl">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -83,6 +83,7 @@
<connections>
<segue destination="X2o-q6-XD5" kind="unwind" identifier="unwindFromGames" unwindAction="unwindFromGamesViewControllerWith:" id="k8C-Xn-maU"/>
<segue destination="MPk-bF-nkj" kind="presentation" identifier="saveStates" customClass="SaveStatesStoryboardSegue" customModule="Delta" customModuleProvider="target" id="1Xp-2J-0cq"/>
<segue destination="qdE-gb-V2e" kind="presentation" identifier="preferredControllerSkins" id="i6y-cP-3WM"/>
</connections>
</collectionViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="bW1-t8-idm" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -217,7 +218,7 @@
<nil name="viewControllers"/>
<connections>
<segue destination="Eae-Qk-9MI" kind="relationship" relationship="rootViewController" id="1Jh-Zf-ntp"/>
<segue destination="WQV-Du-4IA" kind="unwind" identifier="unwindFromSaveStates" customClass="SaveStatesStoryboardUnwindSegue" customModule="Delta" customModuleProvider="target" unwindAction="unwindFromSaveStatesViewControllerWith:" id="dwO-iv-XDr"/>
<segue destination="WQV-Du-4IA" kind="unwind" identifier="unwindFromSaveStates" customClass="SaveStatesStoryboardUnwindSegue" customModule="Delta" customModuleProvider="target" unwindAction="unwindToGameCollectionViewController:" id="dwO-iv-XDr"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="htj-tq-2KP" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -225,6 +226,16 @@
</objects>
<point key="canvasLocation" x="2652" y="1718"/>
</scene>
<!--preferredControllerSkins-->
<scene sceneID="aKY-Ld-et6">
<objects>
<viewControllerPlaceholder storyboardName="Settings" referencedIdentifier="preferredControllerSkins" id="dbc-pQ-iun" sceneMemberID="viewController">
<navigationItem key="navigationItem" id="xth-MV-SHp"/>
</viewControllerPlaceholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="za6-AO-ZFe" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3405" y="2394"/>
</scene>
<!--saveStatesViewController-->
<scene sceneID="f1R-Kb-FOU">
<objects>
@ -235,6 +246,25 @@
</objects>
<point key="canvasLocation" x="3409" y="1716"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="eMh-8N-ZGA">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="qdE-gb-V2e" sceneMemberID="viewController">
<toolbarItems/>
<navigationItem key="navigationItem" id="Dg6-He-v5H"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="35T-4Q-Mmp">
<rect key="frame" x="0.0" y="0.0" width="375" height="108"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="dbc-pQ-iun" kind="relationship" relationship="rootViewController" id="oRb-B6-c0J"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="XmB-QY-yA3" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2652" y="2394"/>
</scene>
</scenes>
<resources>
<image name="SettingsButton" width="22" height="22"/>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14868" 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="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ssH-mM-uG6">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -18,7 +18,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<label key="tableFooterView" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Delta 0.6.0" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Str-BY-agW">
<rect key="frame" x="0.0" y="1531.5" width="375" height="44"/>
<rect key="frame" x="0.0" y="1376.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
@ -31,7 +31,7 @@
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jvV-ZB-Rq1" id="AVi-6C-eIS">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Player 1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tls-Hv-Rx2">
@ -42,7 +42,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Riley's iPhone" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vJP-Ie-a9H">
<rect key="frame" x="239" y="13" width="100.5" height="19.5"/>
<rect key="frame" x="239.5" y="13" width="100.5" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -55,7 +55,7 @@
<rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1Fv-H5-0oH" id="kFJ-zK-MLZ">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Player 2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="e3u-x9-IEC">
@ -66,7 +66,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="SteelSeries Stratus" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2OP-A1-VYo">
<rect key="frame" x="201" y="13" width="138.5" height="19.5"/>
<rect key="frame" x="201.5" y="13" width="138.5" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -79,7 +79,7 @@
<rect key="frame" x="0.0" y="143.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="EcC-Be-jV5" id="9ZS-um-scR">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Player 3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Cdn-11-xZe">
@ -90,7 +90,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="MOGA Gamepad" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="wWc-NY-Bsd">
<rect key="frame" x="217.5" y="13" width="122" height="19.5"/>
<rect key="frame" x="218" y="13" width="122" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -103,7 +103,7 @@
<rect key="frame" x="0.0" y="187.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hO9-Ov-vsA" id="MRi-re-XI7">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Player 4" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Hls-3b-EaS">
@ -114,7 +114,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Jayce's iPhone" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hNf-uc-PLR">
<rect key="frame" x="231.5" y="13" width="108" height="19.5"/>
<rect key="frame" x="232" y="13" width="108" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -131,11 +131,11 @@
<rect key="frame" x="0.0" y="287.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ICf-ug-NwS" id="7se-sE-x9e">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="System Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="mBC-YU-BVK">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="16" y="0.0" width="324" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -148,11 +148,11 @@
<rect key="frame" x="0.0" y="331.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Hqy-yc-Jef" id="wJL-kh-qW0">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="System Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Dxs-Me-IVU">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="16" y="0.0" width="324" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -165,11 +165,11 @@
<rect key="frame" x="0.0" y="375.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jFa-Qk-1cj" id="rFR-qL-fNQ">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="System Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="o9x-Kn-6bC">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="16" y="0.0" width="324" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -182,11 +182,11 @@
<rect key="frame" x="0.0" y="419.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vIu-iy-kRM" id="FIZ-uw-fR7">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="System Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="XVO-TO-ncw">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="16" y="0.0" width="324" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -199,11 +199,11 @@
<rect key="frame" x="0.0" y="463.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Dfy-MJ-39n" id="dgi-73-brN">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="System Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vV9-Fk-zd5">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="16" y="0.0" width="324" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -216,11 +216,11 @@
<rect key="frame" x="0.0" y="507.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="p69-Xz-VoS" id="pwB-9y-EUf">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="System Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Etp-g5-W9R">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="16" y="0.0" width="324" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -342,18 +342,18 @@
<rect key="frame" x="0.0" y="930" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bwW-PG-BcV" id="RNA-99-evH">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Service" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="4U1-fe-PIb">
<rect key="frame" x="16" y="13" width="54" height="19.5"/>
<rect key="frame" x="15" y="13" width="54" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Google Drive" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="kLY-5g-v8n">
<rect key="frame" x="245.5" y="13" width="94" height="19.5"/>
<rect key="frame" x="254" y="13" width="94" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -369,11 +369,11 @@
<rect key="frame" x="0.0" y="974" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="JPg-6O-DRe" id="zcZ-QR-Nno">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Sync Status" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="1u0-gh-zP7">
<rect key="frame" x="16" y="0.0" width="323.5" height="44"/>
<rect key="frame" x="15" y="0.0" width="333" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -393,11 +393,11 @@
<rect key="frame" x="0.0" y="1102" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="SSL-t4-QZj" id="hQB-Iy-bzy">
<rect key="frame" x="0.0" y="0.0" width="355.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="App Icon Shortcuts" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="c5i-qG-ir9">
<rect key="frame" x="15" y="0.0" width="332.5" height="44"/>
<rect key="frame" x="15" y="0.0" width="333" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -417,11 +417,11 @@
<rect key="frame" x="0.0" y="1209.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4it-3L-j8P" id="7dE-36-hzp">
<rect key="frame" x="0.0" y="0.0" width="355.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Join the beta" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="faT-qa-JP0">
<rect key="frame" x="15" y="0.0" width="332.5" height="44"/>
<rect key="frame" x="15" y="0.0" width="333" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -438,7 +438,7 @@
<rect key="frame" x="0.0" y="1337.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="BU4-ee-DGz" id="fWf-gm-1sf">
<rect key="frame" x="0.0" y="0.0" width="355.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Riley Testut" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Pum-dL-hGn">
@ -449,7 +449,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Developer" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="WQ6-m7-zhh">
<rect key="frame" x="273.5" y="13" width="74" height="19.5"/>
<rect key="frame" x="274" y="13" width="74" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -462,7 +462,7 @@
<rect key="frame" x="0.0" y="1381.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8qc-0t-Nte" id="jUL-fL-i0n">
<rect key="frame" x="0.0" y="0.0" width="355.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Caroline Moore" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="gWx-Xn-5Nf">
@ -473,7 +473,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Graphic Designer" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="09x-GX-cpy">
<rect key="frame" x="221.5" y="13" width="126" height="19.5"/>
<rect key="frame" x="222" y="13" width="126" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -486,7 +486,7 @@
<rect key="frame" x="0.0" y="1425.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Zh9-JJ-jEQ" id="VCc-oJ-ODB">
<rect key="frame" x="0.0" y="0.0" width="355.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Grant Gliner" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="zro-BX-EY9">
@ -497,7 +497,7 @@
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Icon Guy" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="e45-FD-ug2">
<rect key="frame" x="283" y="13" width="64.5" height="19.5"/>
<rect key="frame" x="283.5" y="13" width="64.5" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -510,11 +510,11 @@
<rect key="frame" x="0.0" y="1469.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="j7p-ZK-mHq" id="BqT-yP-OpS">
<rect key="frame" x="0.0" y="0.0" width="355.5" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="356" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Licenses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2K3-IL-94S">
<rect key="frame" x="15" y="0.0" width="332.5" height="44"/>
<rect key="frame" x="15" y="0.0" width="333" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -706,7 +706,7 @@
<!--Game Boy Advance-->
<scene sceneID="pkL-Te-puh">
<objects>
<tableViewController id="56e-ul-z6v" customClass="SystemControllerSkinsViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
<tableViewController storyboardIdentifier="preferredControllerSkins" id="56e-ul-z6v" customClass="PreferredControllerSkinsViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="fdQ-n7-kUL">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -764,7 +764,13 @@
<outlet property="delegate" destination="56e-ul-z6v" id="08A-GG-8bs"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Game Boy Advance" id="2GJ-l7-DgY"/>
<navigationItem key="navigationItem" title="Game Boy Advance" id="2GJ-l7-DgY">
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="3iE-lg-bkA">
<connections>
<segue destination="eMT-K0-PiM" kind="unwind" unwindAction="unwindToGameCollectionViewController:" id="fFx-zM-kfa"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="landscapeImageView" destination="XY1-es-oZe" id="d6S-ez-jh2"/>
<outlet property="portraitImageView" destination="5r7-OQ-i7w" id="C5r-uX-SlN"/>
@ -772,6 +778,7 @@
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Nx1-Ly-oRu" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="eMT-K0-PiM" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="2513" y="466"/>
</scene>
@ -863,6 +870,14 @@
<outlet property="delegate" destination="pG9-hI-tRE" id="8NO-ha-J5E"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Controller Skins" largeTitleDisplayMode="never" id="Ful-dk-I0G">
<barButtonItem key="rightBarButtonItem" title="Reset" style="done" id="XU0-TI-SPi">
<color key="tintColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<action selector="resetControllerSkin:" destination="pG9-hI-tRE" id="EOa-FJ-zOp"/>
</connections>
</barButtonItem>
</navigationItem>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="54U-JB-wBG" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
@ -1118,11 +1133,11 @@
<rect key="frame" x="0.0" y="55.5" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="wpv-cf-duw" id="ehC-Qx-Zx4">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="AWh-ik-Gvu">
<rect key="frame" x="16" y="0.0" width="323.5" height="43.5"/>
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
@ -1138,11 +1153,11 @@
<rect key="frame" x="0.0" y="99" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="tdO-nZ-AtU" id="Ecj-ul-03q">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Previous Sync" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Piz-MQ-rK5">
<rect key="frame" x="16" y="0.0" width="323.5" height="43.5"/>
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" name="Purple"/>
@ -1186,11 +1201,11 @@
<rect key="frame" x="0.0" y="55.5" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="q5G-Db-MXt" id="Ric-Km-AWj">
<rect key="frame" x="0.0" y="0.0" width="347.5" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="348" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Game" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RWL-4W-NpH">
<rect key="frame" x="16" y="0.0" width="323.5" height="43.5"/>
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
@ -1534,7 +1549,7 @@
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" layoutMarginsFollowReadableWidth="YES" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Lw6-5a-pvQ">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<edgeInsets key="layoutMargins" top="8" left="30" bottom="8" right="30"/>
<mutableString key="text">Delta and AltStore LLC are in no way affiliated with Nintendo Co., Ltd.
<string key="text">Delta and AltStore LLC are in no way affiliated with Nintendo Co., Ltd.
Stephen Celis (SQLite.swift)
Copyright (c) 2014-2015 Stephen Celis (&lt;stephen@stephencelis.com&gt;)
@ -1624,7 +1639,7 @@ Gambatte
visualboyadvance-m
DeSmuME
Delta uses OpenVGDB to provide automatic artwork for imported games.</mutableString>
Delta uses OpenVGDB to provide automatic artwork for imported games.</string>
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>

View File

@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Delta 4.xcdatamodel</string>
<string>Delta 5.xcdatamodel</string>
</dict>
</plist>

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="19C57" minimumToolsVersion="Xcode 7.0" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="1.0">
<entity name="Cheat" representedClassName="Cheat" syncable="YES">
<attribute name="code" attributeType="String" syncable="YES"/>
<attribute name="creationDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="isEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="NO" syncable="YES"/>
<attribute name="modifiedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="name" attributeType="String" syncable="YES"/>
<attribute name="type" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="CheatType"/>
</userInfo>
</attribute>
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="cheats" inverseEntity="Game" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="identifier"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="ControllerSkin" representedClassName="ControllerSkin" syncable="YES">
<attribute name="filename" attributeType="String" syncable="YES"/>
<attribute name="gameType" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="GameType"/>
</userInfo>
</attribute>
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="isStandard" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="name" attributeType="String" syncable="YES"/>
<attribute name="supportedConfigurations" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES" syncable="YES">
<userInfo>
<entry key="attributeValueScalarType" value="ControllerSkinConfigurations"/>
</userInfo>
</attribute>
<relationship name="preferredLandscapeSkinByGames" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="preferredLandscapeSkin" inverseEntity="Game" syncable="YES"/>
<relationship name="preferredPortraitSkinByGames" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="preferredPortraitSkin" inverseEntity="Game" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="identifier"/>
<constraint value="gameType"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="Game" representedClassName="Game" syncable="YES">
<attribute name="artworkURL" optional="YES" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="URL"/>
</userInfo>
</attribute>
<attribute name="filename" attributeType="String" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="NSURL"/>
</userInfo>
</attribute>
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="name" attributeType="String" syncable="YES"/>
<attribute name="playedDate" optional="YES" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="type" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="GameType"/>
</userInfo>
</attribute>
<relationship name="cheats" toMany="YES" deletionRule="Cascade" destinationEntity="Cheat" inverseName="game" inverseEntity="Cheat" syncable="YES"/>
<relationship name="gameCollection" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="GameCollection" inverseName="games" inverseEntity="GameCollection" syncable="YES"/>
<relationship name="gameSave" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="GameSave" inverseName="game" inverseEntity="GameSave" syncable="YES"/>
<relationship name="preferredLandscapeSkin" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ControllerSkin" inverseName="preferredLandscapeSkinByGames" inverseEntity="ControllerSkin" syncable="YES"/>
<relationship name="preferredPortraitSkin" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ControllerSkin" inverseName="preferredPortraitSkinByGames" inverseEntity="ControllerSkin" syncable="YES"/>
<relationship name="previewSaveState" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SaveState" inverseName="previewGame" inverseEntity="SaveState" syncable="YES"/>
<relationship name="saveStates" toMany="YES" deletionRule="Cascade" destinationEntity="SaveState" inverseName="game" inverseEntity="SaveState" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="identifier"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="GameCollection" representedClassName="GameCollection" syncable="YES">
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="index" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
<relationship name="games" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="gameCollection" inverseEntity="Game" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="identifier"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="GameControllerInputMapping" representedClassName="GameControllerInputMapping" syncable="YES">
<attribute name="deltaCoreInputMapping" attributeType="Transformable" valueTransformerName="GameControllerInputMappingTransformer" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="Any"/>
</userInfo>
</attribute>
<attribute name="gameControllerInputType" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="GameControllerInputType"/>
</userInfo>
</attribute>
<attribute name="gameType" attributeType="Transformable" valueTransformerName="NSSecureUnarchiveFromData" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="GameType"/>
</userInfo>
</attribute>
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="playerIndex" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="gameControllerInputType"/>
<constraint value="gameType"/>
<constraint value="playerIndex"/>
</uniquenessConstraint>
<uniquenessConstraint>
<constraint value="identifier"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="GameSave" representedClassName="GameSave" syncable="YES">
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="modifiedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="gameSave" inverseEntity="Game" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="identifier"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="SaveState" representedClassName="SaveState" versionHashModifier="quick" syncable="YES">
<attribute name="creationDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="filename" attributeType="String" syncable="YES">
<userInfo>
<entry key="attributeValueClassName" value="NSURL"/>
</userInfo>
</attribute>
<attribute name="identifier" attributeType="String" syncable="YES"/>
<attribute name="modifiedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="type" attributeType="Integer 16" defaultValueString="2" usesScalarValueType="NO" syncable="YES">
<userInfo>
<entry key="attributeValueScalarType" value="SaveStateType"/>
</userInfo>
</attribute>
<relationship name="game" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="saveStates" inverseEntity="Game" syncable="YES"/>
<relationship name="previewGame" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Game" inverseName="previewSaveState" inverseEntity="Game" syncable="YES"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="identifier"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<elements>
<element name="Cheat" positionX="-198" positionY="-63" width="128" height="165"/>
<element name="ControllerSkin" positionX="-387" positionY="90" width="128" height="163"/>
<element name="Game" positionX="-378" positionY="-54" width="128" height="238"/>
<element name="GameCollection" positionX="-585" positionY="-27" width="128" height="90"/>
<element name="GameControllerInputMapping" positionX="-387" positionY="90" width="128" height="120"/>
<element name="GameSave" positionX="-387" positionY="90" width="128" height="90"/>
<element name="SaveState" positionX="-198" positionY="113" width="128" height="165"/>
</elements>
</model>

View File

@ -28,5 +28,9 @@ public class _ControllerSkin: NSManagedObject
// MARK: - Relationships
@NSManaged public var preferredLandscapeSkinByGames: Set<Game>
@NSManaged public var preferredPortraitSkinByGames: Set<Game>
}

View File

@ -34,6 +34,10 @@ public class _Game: NSManagedObject
@NSManaged public var gameSave: GameSave?
@NSManaged public var preferredLandscapeSkin: ControllerSkin?
@NSManaged public var preferredPortraitSkin: ControllerSkin?
@NSManaged public var previewSaveState: SaveState?
@NSManaged public var saveStates: Set<SaveState>

View File

@ -556,14 +556,14 @@ private extension GameViewController
func updateControllerSkin()
{
guard let game = self.game, let system = System(gameType: game.type), let window = self.view.window else { return }
guard let game = self.game as? Game, let window = self.view.window else { return }
let traits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
let controllerSkin = Settings.preferredControllerSkin(for: system, traits: traits)
let controllerSkin = Settings.preferredControllerSkin(for: game, traits: traits)
self.controllerView.controllerSkin = controllerSkin
self.view.setNeedsUpdateConstraints()
self.view.setNeedsLayout()
}
}

View File

@ -148,6 +148,12 @@ extension GameCollectionViewController
saveStatesViewController.game = game
saveStatesViewController.mode = .loading
saveStatesViewController.theme = self.theme
case "preferredControllerSkins":
let game = sender as! Game
let preferredControllerSkinsViewController = (segue.destination as! UINavigationController).topViewController as! PreferredControllerSkinsViewController
preferredControllerSkinsViewController.game = game
case "unwindFromGames":
let destinationViewController = segue.destination as! GameViewController
@ -191,11 +197,7 @@ extension GameCollectionViewController
}
}
@IBAction private func unwindFromSaveStatesViewController(with segue: UIStoryboardSegue)
{
}
@IBAction private func unwindFromGamesDatabaseBrowser(with segue: UIStoryboardSegue)
@IBAction private func unwindToGameCollectionViewController(_ segue: UIStoryboardSegue)
{
}
}
@ -394,6 +396,10 @@ private extension GameCollectionViewController
self.changeArtwork(for: game)
}
let changeControllerSkinAction = Action(title: NSLocalizedString("Change Controller Skin", comment: ""), style: .default, image: UIImage(symbolNameIfAvailable: "gamecontroller")) { [unowned self] _ in
self.changePreferredControllerSkin(for: game)
}
let shareAction = Action(title: NSLocalizedString("Share", comment: ""), style: .default, image: UIImage(symbolNameIfAvailable: "square.and.arrow.up"), action: { [unowned self] action in
self.share(game)
})
@ -413,7 +419,7 @@ private extension GameCollectionViewController
switch game.type
{
case GameType.unknown: return [cancelAction, renameAction, changeArtworkAction, shareAction, deleteAction]
default: return [cancelAction, renameAction, changeArtworkAction, shareAction, saveStatesAction, importSaveFile, deleteAction]
default: return [cancelAction, renameAction, changeArtworkAction, changeControllerSkinAction, shareAction, saveStatesAction, importSaveFile, deleteAction]
}
}
@ -655,6 +661,11 @@ private extension GameCollectionViewController
}
}
func changePreferredControllerSkin(for game: Game)
{
self.performSegue(withIdentifier: "preferredControllerSkins", sender: game)
}
@objc func textFieldTextDidChange(_ textField: UITextField)
{
let text = textField.text ?? ""

View File

@ -12,8 +12,16 @@ import DeltaCore
import Roxas
protocol ControllerSkinsViewControllerDelegate: AnyObject
{
func controllerSkinsViewController(_ controllerSkinsViewController: ControllerSkinsViewController, didChooseControllerSkin controllerSkin: ControllerSkin)
func controllerSkinsViewControllerDidResetControllerSkin(_ controllerSkinsViewController: ControllerSkinsViewController)
}
class ControllerSkinsViewController: UITableViewController
{
weak var delegate: ControllerSkinsViewControllerDelegate?
var system: System! {
didSet {
self.updateDataSource()
@ -26,6 +34,8 @@ class ControllerSkinsViewController: UITableViewController
}
}
var isResetButtonVisible: Bool = true
private let dataSource: RSTFetchedResultsTableViewPrefetchingDataSource<ControllerSkin, UIImage>
required init?(coder aDecoder: NSCoder)
@ -46,6 +56,11 @@ extension ControllerSkinsViewController
self.tableView.dataSource = self.dataSource
self.tableView.prefetchDataSource = self.dataSource
if !self.isResetButtonVisible
{
self.navigationItem.rightBarButtonItem = nil
}
}
override func didReceiveMemoryWarning()
@ -114,6 +129,16 @@ private extension ControllerSkinsViewController
self.dataSource.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext, sectionNameKeyPath: #keyPath(ControllerSkin.name), cacheName: nil)
}
@IBAction func resetControllerSkin(_ sender: UIBarButtonItem)
{
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
alertController.addAction(.cancel)
alertController.addAction(UIAlertAction(title: NSLocalizedString("Reset Controller Skin to Default", comment: ""), style: .destructive, handler: { (action) in
self.delegate?.controllerSkinsViewControllerDidResetControllerSkin(self)
}))
self.present(alertController, animated: true, completion: nil)
}
}
extension ControllerSkinsViewController
@ -155,9 +180,7 @@ extension ControllerSkinsViewController
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let controllerSkin = self.dataSource.item(at: indexPath)
Settings.setPreferredControllerSkin(controllerSkin, for: self.system, traits: self.traits)
_ = self.navigationController?.popViewController(animated: true)
self.delegate?.controllerSkinsViewController(self, didChooseControllerSkin: controllerSkin)
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat

View File

@ -1,5 +1,5 @@
//
// SystemControllerSkinsViewController.swift
// PreferredControllerSkinsViewController.swift
// Delta
//
// Created by Riley Testut on 9/30/16.
@ -10,7 +10,7 @@ import UIKit
import DeltaCore
extension SystemControllerSkinsViewController
extension PreferredControllerSkinsViewController
{
private enum Section: Int
{
@ -19,10 +19,17 @@ extension SystemControllerSkinsViewController
}
}
class SystemControllerSkinsViewController: UITableViewController
class PreferredControllerSkinsViewController: UITableViewController
{
var system: System!
var game: Game? {
didSet {
guard let game = self.game, let system = System(gameType: game.type) else { return }
self.system = system
}
}
@IBOutlet private var portraitImageView: UIImageView!
@IBOutlet private var landscapeImageView: UIImageView!
@ -31,13 +38,19 @@ class SystemControllerSkinsViewController: UITableViewController
private var landscapeControllerSkin: ControllerSkin?
}
extension SystemControllerSkinsViewController
extension PreferredControllerSkinsViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
self.title = self.system.localizedShortName
self.title = self.game?.name ?? self.system.localizedShortName
if self.navigationController?.viewControllers.first != self
{
// Hide Done button since we are not root view controller.
self.navigationItem.rightBarButtonItem = nil
}
}
override func viewDidDisappear(_ animated: Bool)
@ -68,6 +81,7 @@ extension SystemControllerSkinsViewController
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
controllerSkinsViewController.delegate = self
controllerSkinsViewController.system = self.system
var traits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
@ -80,10 +94,31 @@ extension SystemControllerSkinsViewController
}
controllerSkinsViewController.traits = traits
let isResetButtonVisible: Bool
if let game = self.game
{
switch section
{
case .portrait: isResetButtonVisible = (game.preferredPortraitSkin != nil)
case .landscape: isResetButtonVisible = (game.preferredLandscapeSkin != nil)
}
}
else
{
switch section
{
case .portrait: isResetButtonVisible = !(self.portraitControllerSkin?.isStandard ?? false)
case .landscape: isResetButtonVisible = !(self.portraitControllerSkin?.isStandard ?? false)
}
}
controllerSkinsViewController.isResetButtonVisible = isResetButtonVisible
}
}
extension SystemControllerSkinsViewController
extension PreferredControllerSkinsViewController
{
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
@ -115,7 +150,7 @@ extension SystemControllerSkinsViewController
}
}
private extension SystemControllerSkinsViewController
private extension PreferredControllerSkinsViewController
{
func updateControllerSkins()
{
@ -126,7 +161,25 @@ private extension SystemControllerSkinsViewController
let portraitTraits = self.makeTraits(orientation: .portrait, in: window)
let landscapeTraits = self.makeTraits(orientation: .landscape, in: window)
let portraitControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: portraitTraits)
var portraitControllerSkin: ControllerSkin?
var landscapeControllerSkin: ControllerSkin?
if let game = self.game
{
portraitControllerSkin = Settings.preferredControllerSkin(for: game, traits: portraitTraits)
landscapeControllerSkin = Settings.preferredControllerSkin(for: game, traits: landscapeTraits)
}
if portraitControllerSkin == nil
{
portraitControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: portraitTraits)
}
if landscapeControllerSkin == nil
{
landscapeControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: landscapeTraits)
}
if portraitControllerSkin != self.portraitControllerSkin
{
self.portraitImageView.image = nil
@ -135,7 +188,6 @@ private extension SystemControllerSkinsViewController
self.portraitControllerSkin = portraitControllerSkin
}
let landscapeControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: landscapeTraits)
if landscapeControllerSkin != self.landscapeControllerSkin
{
self.landscapeImageView.image = nil
@ -186,3 +238,34 @@ private extension SystemControllerSkinsViewController
return traits
}
}
extension PreferredControllerSkinsViewController: ControllerSkinsViewControllerDelegate
{
func controllerSkinsViewController(_ controllerSkinsViewController: ControllerSkinsViewController, didChooseControllerSkin controllerSkin: ControllerSkin)
{
if let game = self.game
{
Settings.setPreferredControllerSkin(controllerSkin, for: game, traits: controllerSkinsViewController.traits)
}
else
{
Settings.setPreferredControllerSkin(controllerSkin, for: self.system, traits: controllerSkinsViewController.traits)
}
_ = self.navigationController?.popViewController(animated: true)
}
func controllerSkinsViewControllerDidResetControllerSkin(_ controllerSkinsViewController: ControllerSkinsViewController)
{
if let game = self.game
{
Settings.setPreferredControllerSkin(nil, for: game, traits: controllerSkinsViewController.traits)
}
else
{
Settings.setPreferredControllerSkin(nil, for: self.system, traits: controllerSkinsViewController.traits)
}
_ = self.navigationController?.popViewController(animated: true)
}
}

View File

@ -217,16 +217,74 @@ extension Settings
return nil
}
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 UserDefaults.standard.string(forKey: userDefaultKey) != controllerSkin.identifier 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])
}
static func preferredControllerSkin(for game: Game, traits: DeltaCore.ControllerSkin.Traits) -> ControllerSkin?
{
let preferredControllerSkin: ControllerSkin?
switch traits.orientation
{
case .portrait: preferredControllerSkin = game.preferredPortraitSkin
case .landscape: preferredControllerSkin = game.preferredLandscapeSkin
}
if let controllerSkin = preferredControllerSkin, controllerSkin.supports(traits)
{
return controllerSkin
}
if let system = System(gameType: game.type)
{
// Fall back to using preferred controller skin for the system.
let controllerSkin = Settings.preferredControllerSkin(for: system, traits: traits)
return controllerSkin
}
return nil
}
static func setPreferredControllerSkin(_ controllerSkin: ControllerSkin?, for game: Game, traits: DeltaCore.ControllerSkin.Traits)
{
let context = DatabaseManager.shared.newBackgroundContext()
context.performAndWait {
let game = context.object(with: game.objectID) as! Game
let skin: ControllerSkin?
if let controllerSkin = controllerSkin, let contextSkin = context.object(with: controllerSkin.objectID) as? ControllerSkin
{
skin = contextSkin
}
else
{
skin = nil
}
switch traits.orientation
{
case .portrait: game.preferredPortraitSkin = skin
case .landscape: game.preferredLandscapeSkin = skin
}
context.saveWithErrorLogging()
}
game.managedObjectContext?.refresh(game, mergeChanges: false)
if let system = System(gameType: game.type)
{
NotificationCenter.default.post(name: .settingsDidChange, object: controllerSkin, userInfo: [NotificationUserInfoKey.name: Name.preferredControllerSkin, NotificationUserInfoKey.system: system, NotificationUserInfoKey.traits: traits])
}
}
}
private extension Settings

View File

@ -139,10 +139,10 @@ class SettingsViewController: UITableViewController
controllersSettingsViewController.playerIndex = indexPath.row
case Segue.controllerSkins:
let systemControllerSkinsViewController = segue.destination as! SystemControllerSkinsViewController
let preferredControllerSkinsViewController = segue.destination as! PreferredControllerSkinsViewController
let system = System.registeredSystems[indexPath.row]
systemControllerSkinsViewController.system = system
preferredControllerSkinsViewController.system = system
}
}
}