mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-05 22:55:41 +13:00
iOS: Add file picker
This commit is contained in:
parent
90725252d3
commit
69ef842e36
8 changed files with 130 additions and 11 deletions
|
@ -3,4 +3,5 @@
|
|||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
void iosCreateEmulator();
|
||||
void iosLoadROM(NSString* pathNS);
|
||||
void iosRunFrame(CAMetalLayer* layer);
|
|
@ -23,10 +23,6 @@ IOS_EXPORT void iosCreateEmulator() {
|
|||
emulator = std::make_unique<Emulator>();
|
||||
hidService = &emulator->getServiceManager().getHID();
|
||||
emulator->initGraphicsContext(nullptr);
|
||||
|
||||
// TODO: Add game selection on iOS frontend
|
||||
auto path = emulator->getAppDataRoot() / "toon_shading.elf";
|
||||
emulator->loadROM(path);
|
||||
}
|
||||
|
||||
IOS_EXPORT void iosRunFrame(CAMetalLayer* layer) {
|
||||
|
@ -34,4 +30,9 @@ IOS_EXPORT void iosRunFrame(CAMetalLayer* layer) {
|
|||
|
||||
emulator->getRenderer()->setMTKLayer(layerBridged);
|
||||
emulator->runFrame();
|
||||
}
|
||||
|
||||
IOS_EXPORT void iosLoadROM(NSString* pathNS) {
|
||||
auto path = std::filesystem::path([pathNS UTF8String]);
|
||||
emulator->loadROM(path);
|
||||
}
|
|
@ -3,4 +3,5 @@
|
|||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
void iosCreateEmulator();
|
||||
void iosLoadROM(NSString* pathNS);
|
||||
void iosRunFrame(CAMetalLayer* layer);
|
|
@ -51,11 +51,7 @@
|
|||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
4F6E8FC42D77C0120025DD0D /* Pandios */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = Pandios;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4F6E8FC42D77C0120025DD0D /* Pandios */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Pandios; sourceTree = "<group>"; };
|
||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -202,6 +198,7 @@
|
|||
};
|
||||
};
|
||||
buildConfigurationList = 4F6E8FBD2D77C0120025DD0D /* Build configuration list for PBXProject "Pandios" */;
|
||||
compatibilityVersion = "Xcode 16.0.Superseded.1";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
|
@ -210,7 +207,6 @@
|
|||
);
|
||||
mainGroup = 4F6E8FB92D77C0120025DD0D;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
preferredProjectObjectVersion = 70;
|
||||
productRefGroup = 4F6E8FC32D77C0120025DD0D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
|
|
Binary file not shown.
|
@ -3,6 +3,47 @@ import SwiftUI
|
|||
import MetalKit
|
||||
import Darwin
|
||||
|
||||
var emulatorLock = NSLock()
|
||||
|
||||
class DocumentViewController: UIViewController, DocumentDelegate {
|
||||
var documentPicker: DocumentPicker!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
/// set up the document picker
|
||||
documentPicker = DocumentPicker(presentationController: self, delegate: self)
|
||||
/// When the view loads (ie user opens the app) show the file picker
|
||||
show()
|
||||
}
|
||||
|
||||
/// callback from the document picker
|
||||
func didPickDocument(document: Document?) {
|
||||
if let pickedDoc = document {
|
||||
let fileURL = pickedDoc.fileURL
|
||||
|
||||
emulatorLock.lock()
|
||||
print("Loading ROM", fileURL)
|
||||
iosLoadROM(fileURL.path(percentEncoded: false))
|
||||
emulatorLock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func show() {
|
||||
documentPicker.displayPicker()
|
||||
}
|
||||
}
|
||||
|
||||
struct DocumentView: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context: Context) -> DocumentViewController {
|
||||
return DocumentViewController()
|
||||
}
|
||||
|
||||
func updateUIViewController(_ uiViewController: DocumentViewController, context: Context) {
|
||||
// No update needed
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView: UIViewRepresentable {
|
||||
@State var showFileImporter = true
|
||||
|
||||
|
@ -32,7 +73,9 @@ struct ContentView: UIViewRepresentable {
|
|||
iosCreateEmulator()
|
||||
|
||||
while (true) {
|
||||
emulatorLock.lock()
|
||||
iosRunFrame(metalLayer);
|
||||
emulatorLock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,6 +89,7 @@ struct ContentView: UIViewRepresentable {
|
|||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ContentView()
|
||||
DocumentView();
|
||||
ContentView();
|
||||
}
|
||||
}
|
||||
|
|
75
src/pandios/Pandios/DocumentPicker.swift
Normal file
75
src/pandios/Pandios/DocumentPicker.swift
Normal file
|
@ -0,0 +1,75 @@
|
|||
// From https://gist.github.com/aheze/dbc7f9b452e4f86f2d8fe278b3c5001f
|
||||
// DocumentPicker.swift
|
||||
|
||||
import UIKit
|
||||
import MobileCoreServices
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
protocol DocumentDelegate: AnyObject {
|
||||
func didPickDocument(document: Document?)
|
||||
}
|
||||
|
||||
class Document: UIDocument {
|
||||
var data: Data?
|
||||
override func contents(forType typeName: String) throws -> Any {
|
||||
guard let data = data else { return Data() }
|
||||
return try NSKeyedArchiver.archivedData(withRootObject:data,
|
||||
requiringSecureCoding: true)
|
||||
}
|
||||
override func load(fromContents contents: Any, ofType typeName:
|
||||
String?) throws {
|
||||
guard let data = contents as? Data else { return }
|
||||
self.data = data
|
||||
}
|
||||
}
|
||||
|
||||
open class DocumentPicker: NSObject {
|
||||
private var pickerController: UIDocumentPickerViewController?
|
||||
private weak var presentationController: UIViewController?
|
||||
private weak var delegate: DocumentDelegate?
|
||||
|
||||
private var pickedDocument: Document?
|
||||
|
||||
init(presentationController: UIViewController, delegate: DocumentDelegate) {
|
||||
super.init()
|
||||
self.presentationController = presentationController
|
||||
self.delegate = delegate
|
||||
}
|
||||
|
||||
public func displayPicker() {
|
||||
self.pickerController = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.data])
|
||||
self.pickerController!.delegate = self
|
||||
self.presentationController?.present(self.pickerController!, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
extension DocumentPicker: UIDocumentPickerDelegate {
|
||||
/// delegate method, when the user selects a file
|
||||
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
guard let url = urls.first else {
|
||||
return
|
||||
}
|
||||
documentFromURL(pickedURL: url)
|
||||
delegate?.didPickDocument(document: pickedDocument)
|
||||
}
|
||||
|
||||
/// delegate method, when the user cancels
|
||||
public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
|
||||
delegate?.didPickDocument(document: nil)
|
||||
}
|
||||
|
||||
private func documentFromURL(pickedURL: URL) {
|
||||
/// start accessing the resource
|
||||
let shouldStopAccessing = pickedURL.startAccessingSecurityScopedResource()
|
||||
|
||||
defer {
|
||||
if shouldStopAccessing {
|
||||
pickedURL.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
}
|
||||
NSFileCoordinator().coordinate(readingItemAt: pickedURL, error: NSErrorPointer.none) { (readURL) in
|
||||
let document = Document(fileURL: readURL)
|
||||
pickedDocument = document
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ struct PandiosApp: App {
|
|||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
DocumentView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue