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.
330 lines
11 KiB
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()
|
|
|
|
// 获取当前Pod库的Bundle
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|