Adds support for selecting game artwork from clipboard and photo library
This commit is contained in:
parent
1dcbb9c656
commit
78c47015a5
@ -70,6 +70,12 @@
|
|||||||
BF5E7F461B9A652600AE44F8 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF5E7F451B9A652600AE44F8 /* Settings.storyboard */; };
|
BF5E7F461B9A652600AE44F8 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF5E7F451B9A652600AE44F8 /* Settings.storyboard */; };
|
||||||
BF6866171DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6866161DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift */; };
|
BF6866171DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6866161DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift */; };
|
||||||
BF696B801D9B2B02009639E0 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF696B7F1D9B2B02009639E0 /* Theme.swift */; };
|
BF696B801D9B2B02009639E0 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF696B7F1D9B2B02009639E0 /* Theme.swift */; };
|
||||||
|
BF6BF3131EB7E47F008E83CD /* ImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF3121EB7E47F008E83CD /* ImportOption.swift */; };
|
||||||
|
BF6BF3181EB82111008E83CD /* iTunesImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF3171EB82111008E83CD /* iTunesImportOption.swift */; };
|
||||||
|
BF6BF31A1EB82146008E83CD /* ClipboardImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF3191EB82146008E83CD /* ClipboardImportOption.swift */; };
|
||||||
|
BF6BF31C1EB821A0008E83CD /* GamesDatabaseImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF31B1EB821A0008E83CD /* GamesDatabaseImportOption.swift */; };
|
||||||
|
BF6BF3211EB82362008E83CD /* GamesDatabase.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF6BF31F1EB82362008E83CD /* GamesDatabase.storyboard */; };
|
||||||
|
BF6BF3271EB87EB8008E83CD /* PhotoLibraryImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF3261EB87EB8008E83CD /* PhotoLibraryImportOption.swift */; };
|
||||||
BF70798C1B6B464B0019077C /* ZipZap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; };
|
BF70798C1B6B464B0019077C /* ZipZap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; };
|
||||||
BF70798D1B6B464B0019077C /* ZipZap.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
BF70798D1B6B464B0019077C /* ZipZap.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */; };
|
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */; };
|
||||||
@ -174,7 +180,7 @@
|
|||||||
BF5942841E09BC8B0051894B /* _GameCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = _GameCollection.swift; path = Database/Model/Machine/_GameCollection.swift; sourceTree = "<group>"; };
|
BF5942841E09BC8B0051894B /* _GameCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = _GameCollection.swift; path = Database/Model/Machine/_GameCollection.swift; sourceTree = "<group>"; };
|
||||||
BF5942851E09BC8B0051894B /* _SaveState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = _SaveState.swift; path = Database/Model/Machine/_SaveState.swift; sourceTree = "<group>"; };
|
BF5942851E09BC8B0051894B /* _SaveState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = _SaveState.swift; path = Database/Model/Machine/_SaveState.swift; sourceTree = "<group>"; };
|
||||||
BF59428B1E09BC930051894B /* ControllerSkinConfigurations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ControllerSkinConfigurations.h; path = Database/Model/Misc/ControllerSkinConfigurations.h; sourceTree = "<group>"; };
|
BF59428B1E09BC930051894B /* ControllerSkinConfigurations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ControllerSkinConfigurations.h; path = Database/Model/Misc/ControllerSkinConfigurations.h; sourceTree = "<group>"; };
|
||||||
BF59428D1E09BCFB0051894B /* ImportController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImportController.swift; path = Components/Importing/ImportController.swift; sourceTree = "<group>"; };
|
BF59428D1E09BCFB0051894B /* ImportController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImportController.swift; path = Importing/ImportController.swift; sourceTree = "<group>"; };
|
||||||
BF59428F1E09BD1A0051894B /* NSFetchedResultsController+Conveniences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFetchedResultsController+Conveniences.h"; sourceTree = "<group>"; };
|
BF59428F1E09BD1A0051894B /* NSFetchedResultsController+Conveniences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFetchedResultsController+Conveniences.h"; sourceTree = "<group>"; };
|
||||||
BF5942901E09BD1A0051894B /* NSFetchedResultsController+Conveniences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFetchedResultsController+Conveniences.m"; sourceTree = "<group>"; };
|
BF5942901E09BD1A0051894B /* NSFetchedResultsController+Conveniences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSFetchedResultsController+Conveniences.m"; sourceTree = "<group>"; };
|
||||||
BF5942911E09BD1A0051894B /* NSManagedObject+Conveniences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Conveniences.swift"; sourceTree = "<group>"; };
|
BF5942911E09BD1A0051894B /* NSManagedObject+Conveniences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObject+Conveniences.swift"; sourceTree = "<group>"; };
|
||||||
@ -185,6 +191,12 @@
|
|||||||
BF6866161DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ControllerSkin+Configuring.swift"; sourceTree = "<group>"; };
|
BF6866161DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ControllerSkin+Configuring.swift"; sourceTree = "<group>"; };
|
||||||
BF696B7F1D9B2B02009639E0 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = Theming/Theme.swift; sourceTree = "<group>"; };
|
BF696B7F1D9B2B02009639E0 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Theme.swift; path = Theming/Theme.swift; sourceTree = "<group>"; };
|
||||||
BF6BB2451BB73FE800CCF94A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
BF6BB2451BB73FE800CCF94A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
BF6BF3121EB7E47F008E83CD /* ImportOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImportOption.swift; path = Importing/ImportOption.swift; sourceTree = "<group>"; };
|
||||||
|
BF6BF3171EB82111008E83CD /* iTunesImportOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iTunesImportOption.swift; path = "Importing/Import Options/iTunesImportOption.swift"; sourceTree = "<group>"; };
|
||||||
|
BF6BF3191EB82146008E83CD /* ClipboardImportOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ClipboardImportOption.swift; path = "Importing/Import Options/ClipboardImportOption.swift"; sourceTree = "<group>"; };
|
||||||
|
BF6BF31B1EB821A0008E83CD /* GamesDatabaseImportOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GamesDatabaseImportOption.swift; path = "Importing/Import Options/GamesDatabaseImportOption.swift"; sourceTree = "<group>"; };
|
||||||
|
BF6BF3201EB82362008E83CD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/GamesDatabase.storyboard; sourceTree = "<group>"; };
|
||||||
|
BF6BF3261EB87EB8008E83CD /* PhotoLibraryImportOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PhotoLibraryImportOption.swift; path = "Importing/Import Options/PhotoLibraryImportOption.swift"; sourceTree = "<group>"; };
|
||||||
BF70798B1B6B464B0019077C /* ZipZap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ZipZap.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BF70798B1B6B464B0019077C /* ZipZap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ZipZap.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UILabel+FontSize.swift"; sourceTree = "<group>"; };
|
BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UILabel+FontSize.swift"; sourceTree = "<group>"; };
|
||||||
BF7AE8041C2E858400B1B5BC /* PauseMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseMenuViewController.swift; path = "Pause Menu/PauseMenuViewController.swift"; sourceTree = "<group>"; };
|
BF7AE8041C2E858400B1B5BC /* PauseMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PauseMenuViewController.swift; path = "Pause Menu/PauseMenuViewController.swift"; sourceTree = "<group>"; };
|
||||||
@ -203,7 +215,7 @@
|
|||||||
BFE4269D1D9C68E600DC913F /* SaveStatesStoryboardSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesStoryboardSegue.swift; path = Segues/SaveStatesStoryboardSegue.swift; sourceTree = "<group>"; };
|
BFE4269D1D9C68E600DC913F /* SaveStatesStoryboardSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SaveStatesStoryboardSegue.swift; path = Segues/SaveStatesStoryboardSegue.swift; sourceTree = "<group>"; };
|
||||||
BFEC732C1AAECC4A00650035 /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFEC732C1AAECC4A00650035 /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GBCDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GBCDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InputStreamOutputWriter.swift; path = Components/Importing/InputStreamOutputWriter.swift; sourceTree = "<group>"; };
|
BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InputStreamOutputWriter.swift; path = Database/InputStreamOutputWriter.swift; sourceTree = "<group>"; };
|
||||||
BFFA4C081E8A24D600D87934 /* GameMetadataTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GameMetadataTableViewCell.swift; path = Database/OpenVGDB/GameMetadataTableViewCell.swift; sourceTree = "<group>"; };
|
BFFA4C081E8A24D600D87934 /* GameMetadataTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GameMetadataTableViewCell.swift; path = Database/OpenVGDB/GameMetadataTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
BFFA71D71AAC406100EE9DD1 /* Delta.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Delta.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFFA71D71AAC406100EE9DD1 /* Delta.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Delta.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFFA71DB1AAC406100EE9DD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
BFFA71DB1AAC406100EE9DD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
@ -304,7 +316,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF5942581E09BB810051894B /* Action.swift */,
|
BF5942581E09BB810051894B /* Action.swift */,
|
||||||
BF59428C1E09BCE50051894B /* Importing */,
|
|
||||||
BF5942671E09BBB70051894B /* Collection View */,
|
BF5942671E09BBB70051894B /* Collection View */,
|
||||||
BF5942601E09BBA80051894B /* Loading */,
|
BF5942601E09BBA80051894B /* Loading */,
|
||||||
);
|
);
|
||||||
@ -333,6 +344,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF59426D1E09BC5D0051894B /* DatabaseManager.swift */,
|
BF59426D1E09BC5D0051894B /* DatabaseManager.swift */,
|
||||||
|
BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */,
|
||||||
BF5942711E09BC690051894B /* Model */,
|
BF5942711E09BC690051894B /* Model */,
|
||||||
BF95E2751E49763D0030E7AD /* OpenVGDB */,
|
BF95E2751E49763D0030E7AD /* OpenVGDB */,
|
||||||
);
|
);
|
||||||
@ -386,7 +398,8 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF59428D1E09BCFB0051894B /* ImportController.swift */,
|
BF59428D1E09BCFB0051894B /* ImportController.swift */,
|
||||||
BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */,
|
BF6BF3121EB7E47F008E83CD /* ImportOption.swift */,
|
||||||
|
BF6BF3161EB820F4008E83CD /* Import Options */,
|
||||||
);
|
);
|
||||||
name = Importing;
|
name = Importing;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -399,6 +412,17 @@
|
|||||||
name = Theming;
|
name = Theming;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
BF6BF3161EB820F4008E83CD /* Import Options */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BF6BF3171EB82111008E83CD /* iTunesImportOption.swift */,
|
||||||
|
BF6BF3191EB82146008E83CD /* ClipboardImportOption.swift */,
|
||||||
|
BF6BF3261EB87EB8008E83CD /* PhotoLibraryImportOption.swift */,
|
||||||
|
BF6BF31B1EB821A0008E83CD /* GamesDatabaseImportOption.swift */,
|
||||||
|
);
|
||||||
|
name = "Import Options";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
BF7AE7FA1C2E851F00B1B5BC /* Pause Menu */ = {
|
BF7AE7FA1C2E851F00B1B5BC /* Pause Menu */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -434,6 +458,7 @@
|
|||||||
BF95E2751E49763D0030E7AD /* OpenVGDB */ = {
|
BF95E2751E49763D0030E7AD /* OpenVGDB */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
BF6BF31F1EB82362008E83CD /* GamesDatabase.storyboard */,
|
||||||
BF59426E1E09BC5D0051894B /* GamesDatabase.swift */,
|
BF59426E1E09BC5D0051894B /* GamesDatabase.swift */,
|
||||||
BF95E2761E4977BF0030E7AD /* GameMetadata.swift */,
|
BF95E2761E4977BF0030E7AD /* GameMetadata.swift */,
|
||||||
BF95E2781E4982A10030E7AD /* GamesDatabaseBrowserViewController.swift */,
|
BF95E2781E4982A10030E7AD /* GamesDatabaseBrowserViewController.swift */,
|
||||||
@ -522,6 +547,7 @@
|
|||||||
BF7AE7FA1C2E851F00B1B5BC /* Pause Menu */,
|
BF7AE7FA1C2E851F00B1B5BC /* Pause Menu */,
|
||||||
BFAA1FEB1B8AA4E800495943 /* Settings */,
|
BFAA1FEB1B8AA4E800495943 /* Settings */,
|
||||||
BF59426C1E09BC450051894B /* Database */,
|
BF59426C1E09BC450051894B /* Database */,
|
||||||
|
BF59428C1E09BCE50051894B /* Importing */,
|
||||||
BF930FFB1EB6D6EC00E8DBA0 /* Systems */,
|
BF930FFB1EB6D6EC00E8DBA0 /* Systems */,
|
||||||
BF5942571E09BB5D0051894B /* Components */,
|
BF5942571E09BB5D0051894B /* Components */,
|
||||||
BF696B7E1D9B2AE6009639E0 /* Theming */,
|
BF696B7E1D9B2AE6009639E0 /* Theming */,
|
||||||
@ -656,6 +682,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BFFA71E21AAC406100EE9DD1 /* Main.storyboard in Resources */,
|
BFFA71E21AAC406100EE9DD1 /* Main.storyboard in Resources */,
|
||||||
|
BF6BF3211EB82362008E83CD /* GamesDatabase.storyboard in Resources */,
|
||||||
BF3540001C5DA3C500C1184C /* PausePresentationControllerContentView.xib in Resources */,
|
BF3540001C5DA3C500C1184C /* PausePresentationControllerContentView.xib in Resources */,
|
||||||
BF5E7F461B9A652600AE44F8 /* Settings.storyboard in Resources */,
|
BF5E7F461B9A652600AE44F8 /* Settings.storyboard in Resources */,
|
||||||
BF02D5DA1DDEBB3000A5E131 /* openvgdb.sqlite in Resources */,
|
BF02D5DA1DDEBB3000A5E131 /* openvgdb.sqlite in Resources */,
|
||||||
@ -735,6 +762,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BF59426A1E09BBD00051894B /* GridCollectionViewCell.swift in Sources */,
|
BF59426A1E09BBD00051894B /* GridCollectionViewCell.swift in Sources */,
|
||||||
|
BF6BF3181EB82111008E83CD /* iTunesImportOption.swift in Sources */,
|
||||||
BF59427C1E09BC830051894B /* Cheat.swift in Sources */,
|
BF59427C1E09BC830051894B /* Cheat.swift in Sources */,
|
||||||
BFBAB2E31EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift in Sources */,
|
BFBAB2E31EB685A2004E0B0E /* DeltaCoreProtocol+Delta.swift in Sources */,
|
||||||
BF3540081C5DAFAD00C1184C /* PauseTransitionCoordinator.swift in Sources */,
|
BF3540081C5DAFAD00C1184C /* PauseTransitionCoordinator.swift in Sources */,
|
||||||
@ -746,6 +774,7 @@
|
|||||||
BF59428E1E09BCFB0051894B /* ImportController.swift in Sources */,
|
BF59428E1E09BCFB0051894B /* ImportController.swift in Sources */,
|
||||||
BF930FFD1EB6D6FF00E8DBA0 /* System.swift in Sources */,
|
BF930FFD1EB6D6FF00E8DBA0 /* System.swift in Sources */,
|
||||||
BF13A7581D5D2FD9000BB055 /* EmulatorCore+Cheats.swift in Sources */,
|
BF13A7581D5D2FD9000BB055 /* EmulatorCore+Cheats.swift in Sources */,
|
||||||
|
BF6BF3131EB7E47F008E83CD /* ImportOption.swift in Sources */,
|
||||||
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */,
|
BF31878B1D489AAA00BD020D /* CheatValidator.swift in Sources */,
|
||||||
BFFC46201D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift in Sources */,
|
BFFC46201D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift in Sources */,
|
||||||
BF5942731E09BC700051894B /* Model.xcdatamodel in Sources */,
|
BF5942731E09BC700051894B /* Model.xcdatamodel in Sources */,
|
||||||
@ -760,6 +789,7 @@
|
|||||||
BF5942891E09BC8B0051894B /* _GameCollection.swift in Sources */,
|
BF5942891E09BC8B0051894B /* _GameCollection.swift in Sources */,
|
||||||
BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */,
|
BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */,
|
||||||
BF1DAD5D1D9F576000E752A7 /* SystemControllerSkinsViewController.swift in Sources */,
|
BF1DAD5D1D9F576000E752A7 /* SystemControllerSkinsViewController.swift in Sources */,
|
||||||
|
BF6BF31C1EB821A0008E83CD /* GamesDatabaseImportOption.swift in Sources */,
|
||||||
BFFA4C091E8A24D600D87934 /* GameMetadataTableViewCell.swift in Sources */,
|
BFFA4C091E8A24D600D87934 /* GameMetadataTableViewCell.swift in Sources */,
|
||||||
BFFC46231D5984A000AF2CC6 /* LaunchViewController.swift in Sources */,
|
BFFC46231D5984A000AF2CC6 /* LaunchViewController.swift in Sources */,
|
||||||
BF5942701E09BC5D0051894B /* GamesDatabase.swift in Sources */,
|
BF5942701E09BC5D0051894B /* GamesDatabase.swift in Sources */,
|
||||||
@ -791,11 +821,13 @@
|
|||||||
BF5942861E09BC8B0051894B /* _Cheat.swift in Sources */,
|
BF5942861E09BC8B0051894B /* _Cheat.swift in Sources */,
|
||||||
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,
|
BF5E7F441B9A650B00AE44F8 /* SettingsViewController.swift in Sources */,
|
||||||
BF5942931E09BD1A0051894B /* NSFetchedResultsController+Conveniences.m in Sources */,
|
BF5942931E09BD1A0051894B /* NSFetchedResultsController+Conveniences.m in Sources */,
|
||||||
|
BF6BF3271EB87EB8008E83CD /* PhotoLibraryImportOption.swift in Sources */,
|
||||||
BF5942661E09BBB10051894B /* LoadImageURLOperation.swift in Sources */,
|
BF5942661E09BBB10051894B /* LoadImageURLOperation.swift in Sources */,
|
||||||
BF353FF21C5D7FB000C1184C /* PauseViewController.swift in Sources */,
|
BF353FF21C5D7FB000C1184C /* PauseViewController.swift in Sources */,
|
||||||
BF59425C1E09BB810051894B /* Action.swift in Sources */,
|
BF59425C1E09BB810051894B /* Action.swift in Sources */,
|
||||||
BF696B801D9B2B02009639E0 /* Theme.swift in Sources */,
|
BF696B801D9B2B02009639E0 /* Theme.swift in Sources */,
|
||||||
BF7AE8081C2E858400B1B5BC /* PauseMenuViewController.swift in Sources */,
|
BF7AE8081C2E858400B1B5BC /* PauseMenuViewController.swift in Sources */,
|
||||||
|
BF6BF31A1EB82146008E83CD /* ClipboardImportOption.swift in Sources */,
|
||||||
BFF93AA01E0FB036005EC865 /* InputStreamOutputWriter.swift in Sources */,
|
BFF93AA01E0FB036005EC865 /* InputStreamOutputWriter.swift in Sources */,
|
||||||
BF59427F1E09BC830051894B /* GameCollection.swift in Sources */,
|
BF59427F1E09BC830051894B /* GameCollection.swift in Sources */,
|
||||||
);
|
);
|
||||||
@ -812,6 +844,14 @@
|
|||||||
name = PauseMenu.storyboard;
|
name = PauseMenu.storyboard;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
BF6BF31F1EB82362008E83CD /* GamesDatabase.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
BF6BF3201EB82362008E83CD /* Base */,
|
||||||
|
);
|
||||||
|
name = GamesDatabase.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
BFFA71E01AAC406100EE9DD1 /* Main.storyboard */ = {
|
BFFA71E01AAC406100EE9DD1 /* Main.storyboard */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|||||||
107
Delta/Base.lproj/GamesDatabase.storyboard
Normal file
107
Delta/Base.lproj/GamesDatabase.storyboard
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" 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>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
|
||||||
|
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Games Database-->
|
||||||
|
<scene sceneID="S7I-gw-igt">
|
||||||
|
<objects>
|
||||||
|
<tableViewController id="SB6-jW-dhZ" customClass="GamesDatabaseBrowserViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="97" sectionHeaderHeight="28" sectionFooterHeight="28" id="bJf-Sa-ZOX">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<prototypes>
|
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="4cJ-4B-Kgt" customClass="GameMetadataTableViewCell" customModule="Delta" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="28" width="375" height="97"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4cJ-4B-Kgt" id="7ze-s0-mpI">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="96.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DSH-Hk-snb" userLabel="Selected Background View">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="97.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="BoxArt" translatesAutoresizingMaskIntoConstraints="NO" id="tNY-2F-llo">
|
||||||
|
<rect key="frame" x="15" y="8" width="80" height="80"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" secondItem="tNY-2F-llo" secondAttribute="height" multiplier="1:1" id="f4E-bV-L96"/>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Super Mario World" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DND-Fv-FyB">
|
||||||
|
<rect key="frame" x="110" y="38.5" width="250" height="20.5"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="DND-Fv-FyB" firstAttribute="leading" secondItem="tNY-2F-llo" secondAttribute="trailing" constant="15" id="71e-t3-7Av"/>
|
||||||
|
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="DND-Fv-FyB" secondAttribute="bottom" constant="1" id="9No-RE-0xx"/>
|
||||||
|
<constraint firstItem="DND-Fv-FyB" firstAttribute="top" relation="greaterThanOrEqual" secondItem="7ze-s0-mpI" secondAttribute="top" constant="1" id="F9q-6H-sqC"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="DND-Fv-FyB" secondAttribute="trailing" constant="15" id="KFv-7n-LrD"/>
|
||||||
|
<constraint firstItem="DND-Fv-FyB" firstAttribute="centerY" secondItem="7ze-s0-mpI" secondAttribute="centerY" id="YBX-t4-jkR"/>
|
||||||
|
<constraint firstItem="tNY-2F-llo" firstAttribute="top" secondItem="7ze-s0-mpI" secondAttribute="top" constant="8" id="bYX-gA-QvB"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="tNY-2F-llo" secondAttribute="bottom" constant="8" id="fxr-wr-I6X"/>
|
||||||
|
<constraint firstItem="tNY-2F-llo" firstAttribute="leading" secondItem="7ze-s0-mpI" secondAttribute="leading" constant="15" id="hX2-Gr-Bnz"/>
|
||||||
|
</constraints>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
<connections>
|
||||||
|
<outlet property="artworkImageView" destination="tNY-2F-llo" id="GqY-jv-rso"/>
|
||||||
|
<outlet property="artworkImageViewLeadingConstraint" destination="hX2-Gr-Bnz" id="be8-dr-c8K"/>
|
||||||
|
<outlet property="artworkImageViewTrailingConstraint" destination="71e-t3-7Av" id="y62-KO-y1r"/>
|
||||||
|
<outlet property="nameLabel" destination="DND-Fv-FyB" id="LhN-cA-8Hy"/>
|
||||||
|
<outlet property="selectedBackgroundView" destination="DSH-Hk-snb" id="hLY-4k-VxU"/>
|
||||||
|
</connections>
|
||||||
|
</tableViewCell>
|
||||||
|
</prototypes>
|
||||||
|
<connections>
|
||||||
|
<outlet property="dataSource" destination="SB6-jW-dhZ" id="2aq-ZA-84E"/>
|
||||||
|
<outlet property="delegate" destination="SB6-jW-dhZ" id="WgY-cp-m7K"/>
|
||||||
|
</connections>
|
||||||
|
</tableView>
|
||||||
|
<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"/>
|
||||||
|
</connections>
|
||||||
|
</barButtonItem>
|
||||||
|
</navigationItem>
|
||||||
|
</tableViewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="f3a-hX-Qnu" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
<exit id="mUU-ug-yNs" userLabel="Exit" sceneMemberID="exit"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="2652" y="1001.649175412294"/>
|
||||||
|
</scene>
|
||||||
|
<!--Navigation Controller-->
|
||||||
|
<scene sceneID="REv-V5-eEz">
|
||||||
|
<objects>
|
||||||
|
<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="0.0" width="375" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
</navigationBar>
|
||||||
|
<nil name="viewControllers"/>
|
||||||
|
<connections>
|
||||||
|
<segue destination="SB6-jW-dhZ" kind="relationship" relationship="rootViewController" id="b0w-Fq-hrk"/>
|
||||||
|
</connections>
|
||||||
|
</navigationController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="Hr9-N6-XXA" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="1854" y="1002"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="BoxArt" width="100" height="100"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
@ -1,12 +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="11762" systemVersion="16C68" 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="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="SPq-Bk-fQl">
|
||||||
<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="11757"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
|
||||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
|
||||||
<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>
|
||||||
<scenes>
|
<scenes>
|
||||||
@ -49,86 +48,11 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
</navigationItem>
|
</navigationItem>
|
||||||
<connections>
|
|
||||||
<segue destination="6bq-zy-UZU" kind="presentation" identifier="gamesDatabaseBrowser" id="7TT-mP-bjt"/>
|
|
||||||
</connections>
|
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="JYx-xE-nis" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="JYx-xE-nis" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="1036" y="1002"/>
|
<point key="canvasLocation" x="1036" y="1002"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Games Database-->
|
|
||||||
<scene sceneID="S7I-gw-igt">
|
|
||||||
<objects>
|
|
||||||
<tableViewController id="SB6-jW-dhZ" customClass="GamesDatabaseBrowserViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
|
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="97" sectionHeaderHeight="28" sectionFooterHeight="28" id="bJf-Sa-ZOX">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
|
||||||
<prototypes>
|
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="4cJ-4B-Kgt" customClass="GameMetadataTableViewCell" customModule="Delta" customModuleProvider="target">
|
|
||||||
<rect key="frame" x="0.0" y="28" width="375" height="97"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4cJ-4B-Kgt" id="7ze-s0-mpI">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="96"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<subviews>
|
|
||||||
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DSH-Hk-snb" userLabel="Selected Background View">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="97"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
|
||||||
</view>
|
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="BoxArt" translatesAutoresizingMaskIntoConstraints="NO" id="tNY-2F-llo">
|
|
||||||
<rect key="frame" x="15" y="8" width="80" height="80"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="width" secondItem="tNY-2F-llo" secondAttribute="height" multiplier="1:1" id="f4E-bV-L96"/>
|
|
||||||
</constraints>
|
|
||||||
</imageView>
|
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Super Mario World" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DND-Fv-FyB">
|
|
||||||
<rect key="frame" x="110" y="38.5" width="250" height="20.5"/>
|
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="DND-Fv-FyB" firstAttribute="leading" secondItem="tNY-2F-llo" secondAttribute="trailing" constant="15" id="71e-t3-7Av"/>
|
|
||||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="DND-Fv-FyB" secondAttribute="bottom" constant="1" id="9No-RE-0xx"/>
|
|
||||||
<constraint firstItem="DND-Fv-FyB" firstAttribute="top" relation="greaterThanOrEqual" secondItem="7ze-s0-mpI" secondAttribute="top" constant="1" id="F9q-6H-sqC"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="DND-Fv-FyB" secondAttribute="trailing" constant="15" id="KFv-7n-LrD"/>
|
|
||||||
<constraint firstItem="DND-Fv-FyB" firstAttribute="centerY" secondItem="7ze-s0-mpI" secondAttribute="centerY" id="YBX-t4-jkR"/>
|
|
||||||
<constraint firstItem="tNY-2F-llo" firstAttribute="top" secondItem="7ze-s0-mpI" secondAttribute="top" constant="8" id="bYX-gA-QvB"/>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="tNY-2F-llo" secondAttribute="bottom" constant="8" id="fxr-wr-I6X"/>
|
|
||||||
<constraint firstItem="tNY-2F-llo" firstAttribute="leading" secondItem="7ze-s0-mpI" secondAttribute="leading" constant="15" id="hX2-Gr-Bnz"/>
|
|
||||||
</constraints>
|
|
||||||
</tableViewCellContentView>
|
|
||||||
<connections>
|
|
||||||
<outlet property="artworkImageView" destination="tNY-2F-llo" id="GqY-jv-rso"/>
|
|
||||||
<outlet property="artworkImageViewLeadingConstraint" destination="hX2-Gr-Bnz" id="be8-dr-c8K"/>
|
|
||||||
<outlet property="artworkImageViewTrailingConstraint" destination="71e-t3-7Av" id="y62-KO-y1r"/>
|
|
||||||
<outlet property="nameLabel" destination="DND-Fv-FyB" id="LhN-cA-8Hy"/>
|
|
||||||
<outlet property="selectedBackgroundView" destination="DSH-Hk-snb" id="hLY-4k-VxU"/>
|
|
||||||
</connections>
|
|
||||||
</tableViewCell>
|
|
||||||
</prototypes>
|
|
||||||
<connections>
|
|
||||||
<outlet property="dataSource" destination="SB6-jW-dhZ" id="2aq-ZA-84E"/>
|
|
||||||
<outlet property="delegate" destination="SB6-jW-dhZ" id="WgY-cp-m7K"/>
|
|
||||||
</connections>
|
|
||||||
</tableView>
|
|
||||||
<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"/>
|
|
||||||
</connections>
|
|
||||||
</barButtonItem>
|
|
||||||
</navigationItem>
|
|
||||||
</tableViewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="f3a-hX-Qnu" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
||||||
<exit id="mUU-ug-yNs" userLabel="Exit" sceneMemberID="exit"/>
|
|
||||||
</objects>
|
|
||||||
<point key="canvasLocation" x="2652" y="1001.649175412294"/>
|
|
||||||
</scene>
|
|
||||||
<!--Game Collection View Controller-->
|
<!--Game Collection View Controller-->
|
||||||
<scene sceneID="qNA-NP-TiF">
|
<scene sceneID="qNA-NP-TiF">
|
||||||
<objects>
|
<objects>
|
||||||
@ -161,7 +85,6 @@
|
|||||||
<connections>
|
<connections>
|
||||||
<segue destination="X2o-q6-XD5" kind="unwind" identifier="unwindFromGames" unwindAction="unwindFromGamesViewControllerWith:" id="k8C-Xn-maU"/>
|
<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="MPk-bF-nkj" kind="presentation" identifier="saveStates" customClass="SaveStatesStoryboardSegue" customModule="Delta" customModuleProvider="target" id="1Xp-2J-0cq"/>
|
||||||
<segue destination="6bq-zy-UZU" kind="presentation" identifier="gamesDatabaseBrowser" id="mzX-Bb-MaX"/>
|
|
||||||
</connections>
|
</connections>
|
||||||
</collectionViewController>
|
</collectionViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="bW1-t8-idm" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="bW1-t8-idm" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
@ -314,31 +237,11 @@
|
|||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="3409" y="1716"/>
|
<point key="canvasLocation" x="3409" y="1716"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Navigation Controller-->
|
|
||||||
<scene sceneID="REv-V5-eEz">
|
|
||||||
<objects>
|
|
||||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="6bq-zy-UZU" sceneMemberID="viewController">
|
|
||||||
<toolbarItems/>
|
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" misplaced="YES" barStyle="black" id="uzY-vR-coL">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
</navigationBar>
|
|
||||||
<nil name="viewControllers"/>
|
|
||||||
<connections>
|
|
||||||
<segue destination="SB6-jW-dhZ" kind="relationship" relationship="rootViewController" id="b0w-Fq-hrk"/>
|
|
||||||
</connections>
|
|
||||||
</navigationController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Hr9-N6-XXA" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
<point key="canvasLocation" x="1854" y="1002"/>
|
|
||||||
</scene>
|
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="BoxArt" width="100" height="100"/>
|
|
||||||
<image name="Settings_Button" width="22" height="22"/>
|
<image name="Settings_Button" width="22" height="22"/>
|
||||||
</resources>
|
</resources>
|
||||||
<inferredMetricsTieBreakers>
|
<inferredMetricsTieBreakers>
|
||||||
<segue reference="mzX-Bb-MaX"/>
|
|
||||||
<segue reference="Tey-6Z-UHp"/>
|
<segue reference="Tey-6Z-UHp"/>
|
||||||
</inferredMetricsTieBreakers>
|
</inferredMetricsTieBreakers>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@ -1,184 +0,0 @@
|
|||||||
//
|
|
||||||
// ImportController.swift
|
|
||||||
// Delta
|
|
||||||
//
|
|
||||||
// Created by Riley Testut on 10/10/15.
|
|
||||||
// Copyright © 2015 Riley Testut. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import ObjectiveC
|
|
||||||
|
|
||||||
import DeltaCore
|
|
||||||
|
|
||||||
import MobileCoreServices
|
|
||||||
|
|
||||||
protocol ImportControllerDelegate
|
|
||||||
{
|
|
||||||
func importController(_ importController: ImportController, didImport games: Set<Game>, with errors: Set<DatabaseManager.ImportError>)
|
|
||||||
func importController(_ importController: ImportController, didImport controllerSkins: Set<ControllerSkin>, with errors: Set<DatabaseManager.ImportError>)
|
|
||||||
|
|
||||||
/** Optional **/
|
|
||||||
func importControllerDidCancel(_ importController: ImportController)
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ImportControllerDelegate
|
|
||||||
{
|
|
||||||
func importControllerDidCancel(_ importController: ImportController)
|
|
||||||
{
|
|
||||||
// Empty Implementation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ImportController: NSObject
|
|
||||||
{
|
|
||||||
var delegate: ImportControllerDelegate?
|
|
||||||
|
|
||||||
fileprivate weak var presentingViewController: UIViewController?
|
|
||||||
|
|
||||||
fileprivate func presentImportController(from presentingViewController: UIViewController, animated: Bool, completion: ((Void) -> Void)?)
|
|
||||||
{
|
|
||||||
self.presentingViewController = presentingViewController
|
|
||||||
|
|
||||||
var documentTypes = System.supportedSystems.map { $0.gameType.rawValue }
|
|
||||||
documentTypes.append(kUTTypeDeltaControllerSkin as String)
|
|
||||||
documentTypes.append(kUTTypeZipArchive as String)
|
|
||||||
|
|
||||||
// Add GBA4iOS's exported UTIs in case user has GBA4iOS installed (which may override Delta's UTI declarations)
|
|
||||||
documentTypes.append("com.rileytestut.gba")
|
|
||||||
documentTypes.append("com.rileytestut.gbc")
|
|
||||||
documentTypes.append("com.rileytestut.gb")
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
let documentMenuController = UIDocumentMenuViewController(documentTypes: documentTypes, in: .import)
|
|
||||||
documentMenuController.delegate = self
|
|
||||||
documentMenuController.addOption(withTitle: NSLocalizedString("iTunes", comment: ""), image: nil, order: .first) { self.importFromiTunes(nil) }
|
|
||||||
self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
|
|
||||||
#else
|
|
||||||
self.importFromiTunes(completion)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private func importFromiTunes(_ completion: ((Void) -> Void)?)
|
|
||||||
{
|
|
||||||
let alertController = UIAlertController(title: NSLocalizedString("Import from iTunes?", comment: ""), message: NSLocalizedString("Delta will import the games and controller skins copied over via iTunes.", comment: ""), preferredStyle: .alert)
|
|
||||||
|
|
||||||
let importAction = UIAlertAction(title: NSLocalizedString("Import", comment: ""), style: .default) { action in
|
|
||||||
|
|
||||||
let documentsDirectoryURL = DatabaseManager.defaultDirectoryURL().deletingLastPathComponent()
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
let contents = try FileManager.default.contentsOfDirectory(at: documentsDirectoryURL, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
|
|
||||||
|
|
||||||
DatabaseManager.shared.performBackgroundTask { (context) in
|
|
||||||
let controllerSkinURLs = contents.filter { $0.pathExtension.lowercased() == "deltaskin" }
|
|
||||||
self.importControllerSkins(at: Set(controllerSkinURLs))
|
|
||||||
|
|
||||||
let gameURLs = contents.filter { GameType(fileExtension: $0.pathExtension) != nil || $0.pathExtension.lowercased() == "zip" }
|
|
||||||
self.importGames(at: Set(gameURLs))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch let error as NSError
|
|
||||||
{
|
|
||||||
print(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.presentingViewController?.importController = nil
|
|
||||||
|
|
||||||
}
|
|
||||||
alertController.addAction(importAction)
|
|
||||||
|
|
||||||
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { action in
|
|
||||||
self.delegate?.importControllerDidCancel(self)
|
|
||||||
self.presentingViewController?.importController = nil
|
|
||||||
}
|
|
||||||
alertController.addAction(cancelAction)
|
|
||||||
|
|
||||||
self.presentingViewController?.present(alertController, animated: true, completion: completion)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate func importGames(at urls: Set<URL>)
|
|
||||||
{
|
|
||||||
DatabaseManager.shared.importGames(at: urls) { (games, errors) in
|
|
||||||
self.delegate?.importController(self, didImport: games, with: errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate func importControllerSkins(at urls: Set<URL>)
|
|
||||||
{
|
|
||||||
DatabaseManager.shared.importControllerSkins(at: urls) { (controllerSkins, errors) in
|
|
||||||
self.delegate?.importController(self, didImport: controllerSkins, with: errors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
|
|
||||||
extension ImportController: UIDocumentMenuDelegate
|
|
||||||
{
|
|
||||||
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
|
|
||||||
{
|
|
||||||
documentPicker.delegate = self
|
|
||||||
self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
|
|
||||||
{
|
|
||||||
self.delegate?.importControllerDidCancel(self)
|
|
||||||
|
|
||||||
self.presentingViewController?.importController = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ImportController: UIDocumentPickerDelegate
|
|
||||||
{
|
|
||||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
|
|
||||||
{
|
|
||||||
if url.pathExtension.lowercased() == "deltaskin"
|
|
||||||
{
|
|
||||||
self.importControllerSkins(at: [url])
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.importGames(at: [url])
|
|
||||||
}
|
|
||||||
|
|
||||||
self.presentingViewController?.importController = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
|
|
||||||
{
|
|
||||||
self.delegate?.importControllerDidCancel(self)
|
|
||||||
|
|
||||||
self.presentingViewController?.importController = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private var ImportControllerKey: UInt8 = 0
|
|
||||||
|
|
||||||
extension UIViewController
|
|
||||||
{
|
|
||||||
fileprivate(set) var importController: ImportController?
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
objc_setAssociatedObject(self, &ImportControllerKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
|
||||||
}
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return objc_getAssociatedObject(self, &ImportControllerKey) as? ImportController
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func present(_ importController: ImportController, animated: Bool, completion: ((Void) -> Void)?)
|
|
||||||
{
|
|
||||||
self.importController = importController
|
|
||||||
|
|
||||||
importController.presentImportController(from: self, animated: animated, completion: completion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -74,14 +74,12 @@ class LoadImageURLOperation: RSTLoadOperation<UIImage, NSURL>
|
|||||||
|
|
||||||
private func loadLocalImage(completion: @escaping (UIImage?, Error?) -> Void)
|
private func loadLocalImage(completion: @escaping (UIImage?, Error?) -> Void)
|
||||||
{
|
{
|
||||||
let options: NSDictionary = [kCGImageSourceShouldCache as NSString: true]
|
guard let imageSource = CGImageSourceCreateWithURL(self.url as CFURL, nil) else {
|
||||||
|
|
||||||
guard let imageSource = CGImageSourceCreateWithURL(self.url as CFURL, options) else {
|
|
||||||
completion(nil, .doesNotExist)
|
completion(nil, .doesNotExist)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options) else {
|
guard let quartzImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) else {
|
||||||
completion(nil, .invalid)
|
completion(nil, .invalid)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,6 @@ extension DatabaseManager
|
|||||||
case (.saveFailed, _): return false
|
case (.saveFailed, _): return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,6 +493,14 @@ extension DatabaseManager
|
|||||||
|
|
||||||
return gameTypeDirectoryURL
|
return gameTypeDirectoryURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class func artworkURL(for game: Game) -> URL
|
||||||
|
{
|
||||||
|
let gameURL = game.fileURL
|
||||||
|
|
||||||
|
let artworkURL = gameURL.deletingPathExtension().appendingPathExtension("jpg")
|
||||||
|
return artworkURL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - Private -
|
//MARK: - Private -
|
||||||
|
|||||||
@ -22,6 +22,37 @@ public class Game: _Game, GameProtocol
|
|||||||
|
|
||||||
return fileURL
|
return fileURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override var artworkURL: URL? {
|
||||||
|
get {
|
||||||
|
self.willAccessValue(forKey: #keyPath(Game.artworkURL))
|
||||||
|
var artworkURL = self.primitiveValue(forKey: #keyPath(Game.artworkURL)) as? URL
|
||||||
|
self.didAccessValue(forKey: #keyPath(Game.artworkURL))
|
||||||
|
|
||||||
|
if let unwrappedArtworkURL = artworkURL, unwrappedArtworkURL.isFileURL
|
||||||
|
{
|
||||||
|
// Recreate the stored URL relative to current sandbox location.
|
||||||
|
artworkURL = URL(fileURLWithPath: unwrappedArtworkURL.relativePath, relativeTo: DatabaseManager.gamesDirectoryURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
return artworkURL
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
self.willChangeValue(forKey: #keyPath(Game.artworkURL))
|
||||||
|
|
||||||
|
var artworkURL = newValue
|
||||||
|
|
||||||
|
if let newValue = newValue, newValue.isFileURL
|
||||||
|
{
|
||||||
|
// Store a relative URL, since the sandbox location changes.
|
||||||
|
artworkURL = URL(fileURLWithPath: newValue.lastPathComponent, relativeTo: DatabaseManager.gamesDirectoryURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setPrimitiveValue(artworkURL, forKey: #keyPath(Game.artworkURL))
|
||||||
|
|
||||||
|
self.didChangeValue(forKey: #keyPath(Game.artworkURL))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Game
|
extension Game
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
import DeltaCore
|
import DeltaCore
|
||||||
|
|
||||||
@ -47,10 +48,14 @@ class GameCollectionViewController: UICollectionViewController
|
|||||||
fileprivate let dataSource = RSTFetchedResultsCollectionViewDataSource<Game>(fetchedResultsController: NSFetchedResultsController())
|
fileprivate let dataSource = RSTFetchedResultsCollectionViewDataSource<Game>(fetchedResultsController: NSFetchedResultsController())
|
||||||
fileprivate let prototypeCell = GridCollectionViewCell()
|
fileprivate let prototypeCell = GridCollectionViewCell()
|
||||||
|
|
||||||
|
fileprivate let imageOperationQueue = RSTOperationQueue()
|
||||||
|
fileprivate let imageCache = NSCache<NSURL, UIImage>()
|
||||||
|
|
||||||
fileprivate var _performing3DTouchTransition = false
|
fileprivate var _performing3DTouchTransition = false
|
||||||
fileprivate weak var _destination3DTouchTransitionViewController: UIViewController?
|
fileprivate weak var _destination3DTouchTransitionViewController: UIViewController?
|
||||||
|
|
||||||
fileprivate var _renameAction: UIAlertAction?
|
fileprivate var _renameAction: UIAlertAction?
|
||||||
|
fileprivate var _changingArtworkGame: Game?
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - UIViewController -
|
//MARK: - UIViewController -
|
||||||
@ -123,24 +128,6 @@ extension GameCollectionViewController
|
|||||||
saveStatesViewController.mode = .loading
|
saveStatesViewController.mode = .loading
|
||||||
saveStatesViewController.theme = self.theme
|
saveStatesViewController.theme = self.theme
|
||||||
|
|
||||||
case "gamesDatabaseBrowser":
|
|
||||||
let game = sender as! Game
|
|
||||||
|
|
||||||
let gamesDatabaseBrowserViewController = (segue.destination as! UINavigationController).topViewController as! GamesDatabaseBrowserViewController
|
|
||||||
gamesDatabaseBrowserViewController.selectionHandler = { (metadata) in
|
|
||||||
|
|
||||||
DatabaseManager.shared.performBackgroundTask({ (context) in
|
|
||||||
let temporaryGame = context.object(with: game.objectID) as! Game
|
|
||||||
temporaryGame.artworkURL = metadata.artworkURL
|
|
||||||
context.saveWithErrorLogging()
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
gamesDatabaseBrowserViewController.dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
case "unwindFromGames":
|
case "unwindFromGames":
|
||||||
let destinationViewController = segue.destination as! GameViewController
|
let destinationViewController = segue.destination as! GameViewController
|
||||||
let cell = sender as! UICollectionViewCell
|
let cell = sender as! UICollectionViewCell
|
||||||
@ -222,28 +209,28 @@ private extension GameCollectionViewController
|
|||||||
cell.isImageViewVibrancyEnabled = true
|
cell.isImageViewVibrancyEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell.imageView.image = #imageLiteral(resourceName: "BoxArt")
|
||||||
|
|
||||||
cell.maximumImageSize = CGSize(width: 90, height: 90)
|
cell.maximumImageSize = CGSize(width: 90, height: 90)
|
||||||
cell.textLabel.text = game.name
|
cell.textLabel.text = game.name
|
||||||
cell.textLabel.textColor = UIColor.gray
|
cell.textLabel.textColor = UIColor.gray
|
||||||
|
|
||||||
if let artworkURL = game.artworkURL, !ignoreImageOperations
|
if let artworkURL = game.artworkURL, !ignoreImageOperations
|
||||||
{
|
{
|
||||||
cell.imageView.sd_setImage(with: artworkURL, placeholderImage: #imageLiteral(resourceName: "BoxArt"), options: .continueInBackground) { (image, error, type, url) in
|
let imageOperation = LoadImageURLOperation(url: artworkURL)
|
||||||
|
imageOperation.resultsCache = self.imageCache
|
||||||
|
imageOperation.resultHandler = { (image, error) in
|
||||||
|
|
||||||
if let error = error
|
if let image = image
|
||||||
{
|
|
||||||
print(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if image != nil
|
|
||||||
{
|
{
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
cell.imageView.image = image
|
||||||
cell.isImageViewVibrancyEnabled = false
|
cell.isImageViewVibrancyEnabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
self.imageOperationQueue.addOperation(imageOperation, forKey: indexPath as NSCopying)
|
||||||
cell.imageView.image = #imageLiteral(resourceName: "BoxArt")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +343,16 @@ private extension GameCollectionViewController
|
|||||||
|
|
||||||
func changeArtwork(for game: Game)
|
func changeArtwork(for game: Game)
|
||||||
{
|
{
|
||||||
self.performSegue(withIdentifier: "gamesDatabaseBrowser", sender: game)
|
self._changingArtworkGame = game
|
||||||
|
|
||||||
|
let clipboardImportOption = ClipboardImportOption()
|
||||||
|
let photoLibraryImportOption = PhotoLibraryImportOption(presentingViewController: self)
|
||||||
|
let gamesDatabaseImportOption = GamesDatabaseImportOption(presentingViewController: self)
|
||||||
|
|
||||||
|
let importController = ImportController(documentTypes: [kUTTypeImage as String])
|
||||||
|
importController.delegate = self
|
||||||
|
importController.importOptions = [clipboardImportOption, photoLibraryImportOption, gamesDatabaseImportOption]
|
||||||
|
self.present(importController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func share(_ game: Game)
|
func share(_ game: Game)
|
||||||
@ -493,6 +489,94 @@ extension GameCollectionViewController: SaveStatesViewControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - ImportControllerDelegate -
|
||||||
|
/// ImportControllerDelegate
|
||||||
|
extension GameCollectionViewController: ImportControllerDelegate
|
||||||
|
{
|
||||||
|
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>)
|
||||||
|
{
|
||||||
|
guard let game = self._changingArtworkGame else { return }
|
||||||
|
|
||||||
|
var imageURL: URL?
|
||||||
|
|
||||||
|
if let url = urls.first
|
||||||
|
{
|
||||||
|
if url.isFileURL
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let imageData = try Data(contentsOf: url)
|
||||||
|
|
||||||
|
if let image = UIImage(data: imageData)
|
||||||
|
{
|
||||||
|
let resizedImage = image.resizing(toFit: CGSize(width: 300, height: 300))
|
||||||
|
|
||||||
|
if let resizedData = UIImageJPEGRepresentation(resizedImage, 0.85)
|
||||||
|
{
|
||||||
|
let destinationURL = DatabaseManager.artworkURL(for: game)
|
||||||
|
try resizedData.write(to: destinationURL, options: .atomic)
|
||||||
|
|
||||||
|
imageURL = destinationURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
imageURL = url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let imageURL = imageURL
|
||||||
|
{
|
||||||
|
if let previousArtworkURL = game.artworkURL as NSURL?
|
||||||
|
{
|
||||||
|
// Remove previous artwork from cache.
|
||||||
|
self.imageCache.removeObject(forKey: previousArtworkURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseManager.shared.performBackgroundTask { (context) in
|
||||||
|
let temporaryGame = context.object(with: game.objectID) as! Game
|
||||||
|
temporaryGame.artworkURL = imageURL
|
||||||
|
context.saveWithErrorLogging()
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.presentedViewController?.dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func presentAlertController()
|
||||||
|
{
|
||||||
|
let alertController = UIAlertController(title: NSLocalizedString("Unable to Change Artwork", comment: ""), message: NSLocalizedString("The image might be corrupted or in an unsupported format.", comment: ""), preferredStyle: .alert)
|
||||||
|
alertController.addAction(UIAlertAction(title: RSTSystemLocalizedString("OK"), style: .cancel, handler: nil))
|
||||||
|
self.present(alertController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let presentedViewController = self.presentedViewController
|
||||||
|
{
|
||||||
|
presentedViewController.dismiss(animated: true) {
|
||||||
|
presentAlertController()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
presentAlertController()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func importControllerDidCancel(_ importController: ImportController)
|
||||||
|
{
|
||||||
|
self.presentedViewController?.dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//MARK: - UICollectionViewDelegate -
|
//MARK: - UICollectionViewDelegate -
|
||||||
/// UICollectionViewDelegate
|
/// UICollectionViewDelegate
|
||||||
extension GameCollectionViewController
|
extension GameCollectionViewController
|
||||||
@ -545,8 +629,8 @@ extension GameCollectionViewController
|
|||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
|
override func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
|
||||||
{
|
{
|
||||||
let cell = cell as! GridCollectionViewCell
|
let operation = self.imageOperationQueue[indexPath as NSCopying]
|
||||||
cell.imageView.sd_cancelCurrentImageLoad()
|
operation?.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import CoreData
|
import CoreData
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
import DeltaCore
|
import DeltaCore
|
||||||
|
|
||||||
@ -266,14 +267,26 @@ extension GamesViewController: ImportControllerDelegate
|
|||||||
{
|
{
|
||||||
@IBAction fileprivate func importFiles()
|
@IBAction fileprivate func importFiles()
|
||||||
{
|
{
|
||||||
let importController = ImportController()
|
var documentTypes = Set(System.supportedSystems.map { $0.gameType.rawValue })
|
||||||
|
documentTypes.insert(kUTTypeZipArchive as String)
|
||||||
|
|
||||||
|
// Add GBA4iOS's exported UTIs in case user has GBA4iOS installed (which may override Delta's UTI declarations)
|
||||||
|
documentTypes.insert("com.rileytestut.gba")
|
||||||
|
documentTypes.insert("com.rileytestut.gbc")
|
||||||
|
documentTypes.insert("com.rileytestut.gb")
|
||||||
|
|
||||||
|
let itunesImportOption = iTunesImportOption(presentingViewController: self)
|
||||||
|
|
||||||
|
let importController = ImportController(documentTypes: documentTypes)
|
||||||
importController.delegate = self
|
importController.delegate = self
|
||||||
|
importController.importOptions = [itunesImportOption]
|
||||||
self.present(importController, animated: true, completion: nil)
|
self.present(importController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - ImportControllerDelegate
|
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>)
|
||||||
@nonobjc func importController(_ importController: ImportController, didImport games: Set<Game>, with errors: Set<DatabaseManager.ImportError>)
|
|
||||||
{
|
{
|
||||||
|
let gameURLs = urls.filter { $0.pathExtension.lowercased() != "deltaskin" }
|
||||||
|
DatabaseManager.shared.importGames(at: Set(gameURLs)) { (games, errors) in
|
||||||
if errors.count > 0
|
if errors.count > 0
|
||||||
{
|
{
|
||||||
let alertController = UIAlertController.alertController(for: .games, with: errors)
|
let alertController = UIAlertController.alertController(for: .games, with: errors)
|
||||||
@ -286,8 +299,8 @@ extension GamesViewController: ImportControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@nonobjc func importController(_ importController: ImportController, didImport controllerSkins: Set<ControllerSkin>, with errors: Set<DatabaseManager.ImportError>)
|
let controllerSkinURLs = urls.filter { $0.pathExtension.lowercased() == "deltaskin" }
|
||||||
{
|
DatabaseManager.shared.importControllerSkins(at: Set(controllerSkinURLs)) { (controllerSkins, errors) in
|
||||||
if errors.count > 0
|
if errors.count > 0
|
||||||
{
|
{
|
||||||
let alertController = UIAlertController.alertController(for: .controllerSkins, with: errors)
|
let alertController = UIAlertController.alertController(for: .controllerSkins, with: errors)
|
||||||
@ -300,6 +313,7 @@ extension GamesViewController: ImportControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private extension GamesViewController
|
private extension GamesViewController
|
||||||
{
|
{
|
||||||
|
|||||||
39
Delta/Importing/Import Options/ClipboardImportOption.swift
Normal file
39
Delta/Importing/Import Options/ClipboardImportOption.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// ClipboardImportOption.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/1/17.
|
||||||
|
// Copyright © 2017 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
|
import Roxas
|
||||||
|
|
||||||
|
struct ClipboardImportOption: ImportOption
|
||||||
|
{
|
||||||
|
let title = NSLocalizedString("Clipboard", comment: "")
|
||||||
|
let image: UIImage? = nil
|
||||||
|
|
||||||
|
func `import`(withCompletionHandler completionHandler: @escaping (Set<URL>?) -> Void)
|
||||||
|
{
|
||||||
|
guard UIPasteboard.general.hasImages else { return completionHandler([]) }
|
||||||
|
|
||||||
|
guard let data = UIPasteboard.general.data(forPasteboardType: kUTTypeImage as String) else { return completionHandler([]) }
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let temporaryURL = FileManager.uniqueTemporaryURL()
|
||||||
|
try data.write(to: temporaryURL, options: .atomic)
|
||||||
|
|
||||||
|
completionHandler([temporaryURL])
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
|
||||||
|
completionHandler([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// GamesDatabaseImportOption.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/1/17.
|
||||||
|
// Copyright © 2017 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
struct GamesDatabaseImportOption: ImportOption
|
||||||
|
{
|
||||||
|
let title = NSLocalizedString("Games Database", comment: "")
|
||||||
|
let image: UIImage? = nil
|
||||||
|
|
||||||
|
private let presentingViewController: UIViewController
|
||||||
|
|
||||||
|
init(presentingViewController: UIViewController)
|
||||||
|
{
|
||||||
|
self.presentingViewController = presentingViewController
|
||||||
|
}
|
||||||
|
|
||||||
|
func `import`(withCompletionHandler completionHandler: @escaping (Set<URL>?) -> Void)
|
||||||
|
{
|
||||||
|
let storyboard = UIStoryboard(name: "GamesDatabase", bundle: nil)
|
||||||
|
let navigationController = (storyboard.instantiateInitialViewController() as! UINavigationController)
|
||||||
|
|
||||||
|
let gamesDatabaseBrowserViewController = navigationController.topViewController as! GamesDatabaseBrowserViewController
|
||||||
|
gamesDatabaseBrowserViewController.selectionHandler = { (metadata) in
|
||||||
|
if let artworkURL = metadata.artworkURL
|
||||||
|
{
|
||||||
|
completionHandler([artworkURL])
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completionHandler(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.presentingViewController.present(navigationController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// PhotoLibraryImportOption.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/2/17.
|
||||||
|
// Copyright © 2017 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
|
class PhotoLibraryImportOption: NSObject, ImportOption
|
||||||
|
{
|
||||||
|
let title = NSLocalizedString("Photo Library", comment: "")
|
||||||
|
let image: UIImage? = nil
|
||||||
|
|
||||||
|
private let presentingViewController: UIViewController
|
||||||
|
fileprivate var completionHandler: ((Set<URL>?) -> Void)?
|
||||||
|
|
||||||
|
init(presentingViewController: UIViewController)
|
||||||
|
{
|
||||||
|
self.presentingViewController = presentingViewController
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func `import`(withCompletionHandler completionHandler: @escaping (Set<URL>?) -> Void)
|
||||||
|
{
|
||||||
|
self.completionHandler = completionHandler
|
||||||
|
|
||||||
|
let imagePickerController = UIImagePickerController()
|
||||||
|
imagePickerController.delegate = self
|
||||||
|
imagePickerController.sourceType = .photoLibrary
|
||||||
|
imagePickerController.mediaTypes = [kUTTypeImage as String]
|
||||||
|
self.presentingViewController.present(imagePickerController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PhotoLibraryImportOption: UIImagePickerControllerDelegate, UINavigationControllerDelegate
|
||||||
|
{
|
||||||
|
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
|
||||||
|
{
|
||||||
|
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage, let data = UIImageJPEGRepresentation(image, 0.85) else {
|
||||||
|
self.completionHandler?([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let temporaryURL = FileManager.uniqueTemporaryURL()
|
||||||
|
try data.write(to: temporaryURL, options: .atomic)
|
||||||
|
|
||||||
|
self.completionHandler?([temporaryURL])
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
self.completionHandler?([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
Delta/Importing/Import Options/iTunesImportOption.swift
Normal file
73
Delta/Importing/Import Options/iTunesImportOption.swift
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// iTunesImportOption.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/1/17.
|
||||||
|
// Copyright © 2017 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
|
|
||||||
|
struct iTunesImportOption: ImportOption
|
||||||
|
{
|
||||||
|
let title = NSLocalizedString("iTunes", comment: "")
|
||||||
|
let image: UIImage? = nil
|
||||||
|
|
||||||
|
private let presentingViewController: UIViewController
|
||||||
|
|
||||||
|
init(presentingViewController: UIViewController)
|
||||||
|
{
|
||||||
|
self.presentingViewController = presentingViewController
|
||||||
|
}
|
||||||
|
|
||||||
|
func `import`(withCompletionHandler completionHandler: @escaping (Set<URL>?) -> Void)
|
||||||
|
{
|
||||||
|
let alertController = UIAlertController(title: NSLocalizedString("Import from iTunes?", comment: ""), message: NSLocalizedString("Delta will import the games and controller skins copied over via iTunes.", comment: ""), preferredStyle: .alert)
|
||||||
|
|
||||||
|
let importAction = UIAlertAction(title: NSLocalizedString("Import", comment: ""), style: .default) { action in
|
||||||
|
|
||||||
|
var importedURLs = Set<URL>()
|
||||||
|
|
||||||
|
let documentsDirectoryURL = DatabaseManager.defaultDirectoryURL().deletingLastPathComponent()
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
let contents = try FileManager.default.contentsOfDirectory(at: documentsDirectoryURL, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
|
||||||
|
|
||||||
|
let itemURLs = contents.filter { GameType(fileExtension: $0.pathExtension) != nil || $0.pathExtension.lowercased() == "zip" || $0.pathExtension.lowercased() == "deltaskin" }
|
||||||
|
|
||||||
|
for url in itemURLs
|
||||||
|
{
|
||||||
|
let destinationURL = FileManager.uniqueTemporaryURL().appendingPathExtension(url.pathExtension)
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try FileManager.default.moveItem(at: url, to: destinationURL)
|
||||||
|
importedURLs.insert(destinationURL)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print("Error importing file at URL", url, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
completionHandler(importedURLs)
|
||||||
|
}
|
||||||
|
alertController.addAction(importAction)
|
||||||
|
|
||||||
|
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { action in
|
||||||
|
completionHandler(nil)
|
||||||
|
}
|
||||||
|
alertController.addAction(cancelAction)
|
||||||
|
|
||||||
|
self.presentingViewController.present(alertController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
135
Delta/Importing/ImportController.swift
Normal file
135
Delta/Importing/ImportController.swift
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
//
|
||||||
|
// ImportController.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 10/10/15.
|
||||||
|
// Copyright © 2015 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import ObjectiveC
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
|
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
|
protocol ImportControllerDelegate
|
||||||
|
{
|
||||||
|
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>)
|
||||||
|
|
||||||
|
/** Optional **/
|
||||||
|
func importControllerDidCancel(_ importController: ImportController)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ImportControllerDelegate
|
||||||
|
{
|
||||||
|
func importControllerDidCancel(_ importController: ImportController)
|
||||||
|
{
|
||||||
|
// Empty Implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImportController: NSObject
|
||||||
|
{
|
||||||
|
let documentTypes: Set<String>
|
||||||
|
|
||||||
|
var delegate: ImportControllerDelegate?
|
||||||
|
var importOptions: [ImportOption]?
|
||||||
|
|
||||||
|
init(documentTypes: Set<String>)
|
||||||
|
{
|
||||||
|
self.documentTypes = documentTypes
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate weak var presentingViewController: UIViewController?
|
||||||
|
|
||||||
|
fileprivate func presentImportController(from presentingViewController: UIViewController, animated: Bool, completionHandler: ((Void) -> Void)?)
|
||||||
|
{
|
||||||
|
self.presentingViewController = presentingViewController
|
||||||
|
|
||||||
|
let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(self.documentTypes), in: .import)
|
||||||
|
documentMenuController.delegate = self
|
||||||
|
|
||||||
|
if let reversedImportOptions = self.importOptions?.reversed()
|
||||||
|
{
|
||||||
|
for importOption in reversedImportOptions
|
||||||
|
{
|
||||||
|
documentMenuController.add(importOption, order: UIDocumentMenuOrder.first) { (urls) in
|
||||||
|
if let urls = urls
|
||||||
|
{
|
||||||
|
self.delegate?.importController(self, didImportItemsAt: urls)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.delegate?.importControllerDidCancel(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.presentingViewController?.importController = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension ImportController: UIDocumentMenuDelegate
|
||||||
|
{
|
||||||
|
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
|
||||||
|
{
|
||||||
|
documentPicker.delegate = self
|
||||||
|
self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
|
||||||
|
{
|
||||||
|
self.delegate?.importControllerDidCancel(self)
|
||||||
|
|
||||||
|
self.presentingViewController?.importController = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ImportController: UIDocumentPickerDelegate
|
||||||
|
{
|
||||||
|
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
|
||||||
|
{
|
||||||
|
self.delegate?.importController(self, didImportItemsAt: [url])
|
||||||
|
|
||||||
|
self.presentingViewController?.importController = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
|
||||||
|
{
|
||||||
|
self.delegate?.importControllerDidCancel(self)
|
||||||
|
|
||||||
|
self.presentingViewController?.importController = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var ImportControllerKey: UInt8 = 0
|
||||||
|
|
||||||
|
extension UIViewController
|
||||||
|
{
|
||||||
|
fileprivate(set) var importController: ImportController?
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
objc_setAssociatedObject(self, &ImportControllerKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(self, &ImportControllerKey) as? ImportController
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func present(_ importController: ImportController, animated: Bool, completion: ((Void) -> Void)?)
|
||||||
|
{
|
||||||
|
self.importController = importController
|
||||||
|
|
||||||
|
importController.presentImportController(from: self, animated: animated, completionHandler: completion)
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Delta/Importing/ImportOption.swift
Normal file
29
Delta/Importing/ImportOption.swift
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// ImportOption.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/1/17.
|
||||||
|
// Copyright © 2017 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
|
|
||||||
|
extension UIDocumentMenuViewController
|
||||||
|
{
|
||||||
|
func add(_ importOption: ImportOption, order: UIDocumentMenuOrder, completionHandler: @escaping (Set<URL>?) -> Void)
|
||||||
|
{
|
||||||
|
self.addOption(withTitle: importOption.title, image: importOption.image, order: order) {
|
||||||
|
importOption.import(withCompletionHandler: completionHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol ImportOption
|
||||||
|
{
|
||||||
|
var title: String { get }
|
||||||
|
var image: UIImage? { get }
|
||||||
|
|
||||||
|
func `import`(withCompletionHandler completionHandler: @escaping (Set<URL>?) -> Void)
|
||||||
|
}
|
||||||
@ -126,6 +126,8 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>Press "OK" to allow Delta to use images from your Photo Library as game artwork.</string>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ extension GameType
|
|||||||
{
|
{
|
||||||
init?(fileExtension: String)
|
init?(fileExtension: String)
|
||||||
{
|
{
|
||||||
switch fileExtension
|
switch fileExtension.lowercased()
|
||||||
{
|
{
|
||||||
case "smc", "sfc", "fig": self = .snes
|
case "smc", "sfc", "fig": self = .snes
|
||||||
case "gba": self = .gba
|
case "gba": self = .gba
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user