You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
flutter_cocos_view/ios/Classes/CocosPlayerUtils.swift

330 lines
11 KiB

//
// CocosPlayerUtils.swift
// flutter_cocos_widget
//
// Created by Rex Raphael on 30/01/2021.
//
import Foundation
private var cocos_warmed_up = false
// Hack to work around iOS SDK 4.3 linker problem
// we need at least one __TEXT, __const section entry in main application .o files
// to get this section emitted at right time and so avoid LC_ENCRYPTION_INFO size miscalculation
private let constsection = 0
// keep arg for cocos init from non main
var gArgc: Int32 = 0
var gArgv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>? = nil
var appLaunchOpts: [UIApplication.LaunchOptionsKey: Any]? = [:]
/***********************************PLUGIN_ENTRY STARTS**************************************/
public func InitCocosIntegration(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?) {
gArgc = argc
gArgv = argv
}
public func InitCocosIntegrationWithOptions(
argc: Int32,
argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?,
_ launchingOptions: [UIApplication.LaunchOptionsKey: Any]?) {
gArgc = argc
gArgv = argv
appLaunchOpts = launchingOptions
}
/***********************************PLUGIN_ENTRY END**************************************/
// Load cocos framework for fisrt run
func CocosFrameworkLoad() -> dcocos_bridge? {
return dcocos_bridge.instance()
}
/*********************************** GLOBAL FUNCS & VARS START**************************************/
public var globalControllers: Array<FLTCocosWidgetController> = [FLTCocosWidgetController]()
private var cocosPlayerUtils: CocosPlayerUtils? = nil
func GetCocosPlayerUtils() -> CocosPlayerUtils {
if cocosPlayerUtils == nil {
cocosPlayerUtils = CocosPlayerUtils()
}
return cocosPlayerUtils ?? CocosPlayerUtils()
}
/*********************************** GLOBAL FUNCS & VARS END****************************************/
//var controller: CocosAppController?
var sharedApplication: UIApplication?
@objc protocol CocosEventListener: AnyObject {
func onReceiveMessage(_ message: UnsafePointer<Int8>?)
}
@objc public class CocosPlayerUtils: UIResponder, UIApplicationDelegate {
var ufw: dcocos_bridge!
private var _isCocosPaused = false
private var _isCocosReady = false
private var _isCocosLoaded = false
override init() {
super.init()
//
NotificationCenter.default.addObserver(self, selector: #selector(handleViewWillTransition), name: NSNotification.Name("ViewWillTransition"), object: nil)
}
deinit {
//
NotificationCenter.default.removeObserver(self)
}
@objc func handleViewWillTransition(notification: Notification) {
guard let size = notification.userInfo?["size"] as? CGSize,
let coordinator = notification.userInfo?["coordinator"] as? UIViewControllerTransitionCoordinator else {
return
}
//
print("CocosPlayerUtils will transition to size: \(size)")
//
let selector = NSSelectorFromString("viewWillTransitionToSize:withTransitionCoordinator:")
if self.ufw.responds(to: selector) {
self.ufw.perform(selector, with: size, with: coordinator)
}
}
func initCocos() {
if (self.cocosIsInitiallized()) {
//todo
//self.ufw?.showCocosWindow()
return
}
//
//UIDevice.current.beginGeneratingDeviceOrientationNotifications()
self.ufw = CocosFrameworkLoad()
// PodBundle
let bundle = Bundle(for: dcocos_bridge.self)
// `YourPodResources.bundle`
if let bundleURL = bundle.url(forResource: "cocos_main_bundle", withExtension: "bundle") {
let bundlePath = bundleURL.path
print("Bundle absolute path: \(bundlePath)")
self.ufw.configureCocos2dSearchPaths(bundlePath)
} else {
print("Could not find the bundle.")
}
//self.ufw?.setDataBundleId("com.cocos3d.framework")
self.ufw.initPlatform()
let application = UIApplication.shared
self.ufw.application(application, didFinishLaunchingWithOptions: appLaunchOpts )
registerCocosListener()
// self.ufw?.runEmbedded(withArgc: gArgc, argv: gArgv, appLaunchOpts: appLaunchOpts)
// if self.ufw?.appController() != nil {
// controller = self.ufw?.appController()
// controller?.cocosMessageHandler = self.cocosMessageHandlers
// controller?.cocosSceneLoadedHandler = self.cocosSceneLoadedHandlers
// self.ufw?.appController()?.window?.windowLevel = UIWindow.Level(UIWindow.Level.normal.rawValue - 1)
// }
_isCocosLoaded = true
}
// check if cocos is initiallized
func cocosIsInitiallized() -> Bool {
if self.ufw != nil {
return true
}
return false
}
// Create new cocos player
func createPlayer(completed: @escaping (_ view: UIView?) -> Void) {
if self.cocosIsInitiallized() && self._isCocosReady {
//todo
//completed(controller?.rootView)
completed(nil)
return
}
NotificationCenter.default.addObserver(forName: NSNotification.Name("CocosReady"), object: nil, queue: OperationQueue.main, using: { note in
self._isCocosReady = true
//todo
//completed(controller?.rootView)
completed(nil)
})
DispatchQueue.main.async {
// if (sharedApplication == nil) {
// sharedApplication = UIApplication.shared
// }
// Always keep Flutter window on top
// let flutterUIWindow = sharedApplication?.keyWindow
// flutterUIWindow?.windowLevel = UIWindow.Level(UIWindow.Level.normal.rawValue + 1) // Always keep Flutter window in top
// sharedApplication?.keyWindow?.windowLevel = UIWindow.Level(UIWindow.Level.normal.rawValue + 1)
self.initCocos()
cocos_warmed_up = true
self._isCocosReady = true
self._isCocosLoaded = true
self.listenAppState()
//todo
//completed(controller?.rootView)
completed(nil)
}
}
func registerCocosListener() {
if self.cocosIsInitiallized() {
// self.ufw?.register(self)
}
}
func unregisterCocosListener() {
if self.cocosIsInitiallized() {
// self.ufw?.unregisterFrameworkListener(self)
}
}
@objc
public func cocosDidUnload(_ notification: Notification!) {
unregisterCocosListener()
self.ufw = nil
self._isCocosReady = false
self._isCocosLoaded = false
}
@objc func handleAppStateDidChange(notification: Notification?) {
if !self._isCocosReady {
return
}
//todo
//let cocosAppController = self.ufw?.appController() as? CocosAppController
// let cocosAppController = nil
let application = UIApplication.shared
if notification?.name == UIApplication.willResignActiveNotification {
self.ufw?.applicationWillResignActive(application)
} else if notification?.name == UIApplication.didEnterBackgroundNotification {
// self.ufw?.applicationDidEnterBackground(application)
} else if notification?.name == UIApplication.willEnterForegroundNotification {
// self.ufw?.applicationWillEnterForeground(application)
} else if notification?.name == UIApplication.didBecomeActiveNotification {
self.ufw?.applicationDidBecomeActive(application)
} else if notification?.name == UIApplication.willTerminateNotification {
self.ufw?.applicationWillTerminate(application)
} else if notification?.name == UIApplication.didReceiveMemoryWarningNotification {
// self.ufw?.applicationDidReceiveMemoryWarning(application)
}
}
// Listener for app lifecycle eventa
func listenAppState() {
for name in [
UIApplication.didBecomeActiveNotification,
UIApplication.didEnterBackgroundNotification,
UIApplication.willTerminateNotification,
UIApplication.willResignActiveNotification,
UIApplication.willEnterForegroundNotification,
UIApplication.didReceiveMemoryWarningNotification
] {
NotificationCenter.default.addObserver(
self,
selector: #selector(self.handleAppStateDidChange),
name: name,
object: nil)
}
}
// Pause cocos player
func pause() {
//todo
// self.ufw?.pause(true)
self._isCocosPaused = true
}
// Resume cocos player
func resume() {
//todo
//self.ufw?.pause(false)
self._isCocosPaused = false
}
// Unoad cocos player
func unload() {
//todo
//self.ufw?.unloadApplication()
}
func isCocosLoaded() -> Bool {
return _isCocosLoaded
}
func isCocosPaused() -> Bool {
return _isCocosPaused
}
// Quit cocos player application
func quit() {
//todo
//self.ufw?.quitApplication(0)
self._isCocosLoaded = false
}
// Post message to cocos
func postMessageToCocos(gameObject: String?, cocosMethodName: String?, cocosMessage: String?) {
if self.cocosIsInitiallized() {
//todo
//self.ufw?.sendMessageToGO(withName: gameObject, functionName: cocosMethodName, message: cocosMessage)
}
}
/// Handle incoming cocos messages looping through all controllers and passing payload to
/// the controller handler methods
@objc
func cocosMessageHandlers(_ message: UnsafePointer<Int8>?) {
for c in globalControllers {
if let strMsg = message {
c.handleMessage(message: String(utf8String: strMsg) ?? "")
} else {
c.handleMessage(message: "")
}
}
}
func cocosSceneLoadedHandlers(name: UnsafePointer<Int8>?, buildIndex: UnsafePointer<Int32>?, isLoaded: UnsafePointer<Bool>?, isValid: UnsafePointer<Bool>?) {
if let sceneName = name,
let bIndex = buildIndex,
let loaded = isLoaded,
let valid = isValid {
let loadedVal = Bool((Int(bitPattern: loaded) != 0))
let validVal = Bool((Int(bitPattern: valid) != 0))
let addObject: Dictionary<String, Any> = [
"name": String(utf8String: sceneName) ?? "",
"buildIndex": Int(bitPattern: bIndex),
"isLoaded": loadedVal,
"isValid": validVal,
]
for c in globalControllers {
c.handleSceneChangeEvent(info: addObject)
}
}
}
}