Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/Folium-iOS/Controllers/EmulationControllers/SkinController.swift
2 views
//
//  SkinController.swift
//  Folium-iOS
//
//  Created by Jarrod Norwell on 13/12/2024.
//  Copyright © 2024 Jarrod Norwell. All rights reserved.
//

import Foundation
import GameController
import UIKit

class SkinController : UIViewController {
    var controllerView: ControllerView? = nil
    
    var skinManager: SkinManager = .init()
    
    var game: BaseGame
    var skin: Skin
    init(game: BaseGame, skin: Skin) {
        self.game = game
        self.skin = skin
        super.init(nibName: nil, bundle: nil)
    }
    
    @MainActor required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        
        guard let orientation = skin.orientation(for: interfaceOrientation()) else {
            return
        }
        
        controllerView = .init(orientation: orientation, skin: skin, delegates: (button: self, thumbstick: self))
        guard let controllerView else { return }
        controllerView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(controllerView)
        
        controllerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        controllerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        controllerView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        controllerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        
        Task { await GCController.startWirelessControllerDiscovery() }
        
        NotificationCenter.default.addObserver(forName: NSNotification.Name.GCControllerDidConnect, object: nil, queue: .main, using: { notification in
            self.controllerDidConnect(notification)
        })
        NotificationCenter.default.addObserver(forName: NSNotification.Name.GCControllerDidDisconnect, object: nil, queue: .main, using: { notification in
            self.controllerDidDisconnect(notification)
        })
        NotificationCenter.default.addObserver(forName: .init("applicationStateDidChange"), object: nil, queue: .main, using: { notification in
            Task { await self.applicationStateDidChange(notification) }
        })
    }
    
    override var prefersHomeIndicatorAutoHidden: Bool { true }
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { .portrait }
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask { skin.orientations.supportedInterfaceOrientations }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self)
    }
    
    override func viewWillTransition(to size: CGSize, with coordinator: any UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        coordinator.animate { context in
            let skin: Skin? = if let url = self.skin.url {
                try? self.skinManager.skin(from: url)
            } else {
                switch self.skin.core {
                default:
                    nil
                }
            }
            
            guard let skin else { return }
            self.skin = skin
            
            guard let controllerView = self.controllerView,
                  let orientation = skin.orientation(for: self.interfaceOrientation()) else { return }
            
#if targetEnvironment(simulator)
            controllerView.updateFrames(for: orientation, controllerDisconnected: true)
#else
            controllerView.updateFrames(for: orientation, controllerDisconnected: GCController.controllers().isEmpty)
#endif
        }
    }
    
    func controllerDidConnect(_ notification: Notification) {}
    func controllerDidDisconnect(_ notification: Notification) {}
    
    func applicationStateDidChange(_ notification: Notification) {}
}

extension SkinController : @MainActor ControllerButtonDelegate {
    func touchBegan(with type: Button.`Type`, playerIndex: GCControllerPlayerIndex) {
        
    }
    
    func touchEnded(with type: Button.`Type`, playerIndex: GCControllerPlayerIndex) {
        
    }
    
    func touchMoved(with type: Button.`Type`, playerIndex: GCControllerPlayerIndex) {
        
    }
    
    func touchBegan(with type: Button.`Type`, playerIndex: GCControllerPlayerIndex) async {
        
    }
    
    func touchEnded(with type: Button.`Type`, playerIndex: GCControllerPlayerIndex) async {
        
    }
    
    func touchMoved(with type: Button.`Type`, playerIndex: GCControllerPlayerIndex) async {
        
    }
}

extension SkinController : @MainActor ControllerThumbstickDelegate {
    func touchBegan(with type: Thumbstick.`Type`, position: (x: Float, y: Float), playerIndex: GCControllerPlayerIndex) async {
        
    }
    
    func touchEnded(with type: Thumbstick.`Type`, position: (x: Float, y: Float), playerIndex: GCControllerPlayerIndex) async {
        
    }
    
    func touchMoved(with type: Thumbstick.`Type`, position: (x: Float, y: Float), playerIndex: GCControllerPlayerIndex) async {
        
    }
}