// // FLTCocosViewController.swift // flutter_cocos_widget // // Created by Rex Raphael on 30/01/2021. // import Foundation import CocosFramework // Defines cocos controllable from Flutter. public class FLTCocosWidgetController: NSObject, FLTCocosOptionsSink, FlutterPlatformView { private var _rootView: FLTCocosView private var viewId: Int64 = 0 private var channel: FlutterMethodChannel? private weak var registrar: (NSObjectProtocol & FlutterPluginRegistrar)? private var _disposed = false init( frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, registrar: NSObjectProtocol & FlutterPluginRegistrar ) { self._rootView = FLTCocosView(frame: frame) super.init() globalControllers.append(self) self.viewId = viewId let channelName = String(format: "plugin.xraph.com/cocos_view_%lld", viewId) self.channel = FlutterMethodChannel(name: channelName, binaryMessenger: registrar.messenger()) self.channel?.setMethodCallHandler(self.methodHandler) self.attachView() } func methodHandler(_ call: FlutterMethodCall, result: FlutterResult) { if call.method == "cocos#dispose" { self.dispose() result(nil) } else { self.reattachView() if call.method == "cocos#isReady" { result(GetCocosPlayerUtils().cocosIsInitiallized()) } else if call.method == "cocos#isLoaded" { let _isUnloaded = GetCocosPlayerUtils().isCocosLoaded() result(_isUnloaded) } else if call.method == "cocos#createCocosPlayer" { startCocosIfNeeded() result(nil) } else if call.method == "cocos#isPaused" { let _isPaused = GetCocosPlayerUtils().isCocosPaused() result(_isPaused) } else if call.method == "cocos#pausePlayer" { GetCocosPlayerUtils().pause() result(nil) } else if call.method == "cocos#postMessage" { self.postMessage(call: call, result: result) result(nil) } else if call.method == "cocos#resumePlayer" { GetCocosPlayerUtils().resume() result(nil) } else if call.method == "cocos#unloadPlayer" { GetCocosPlayerUtils().unload() result(nil) } else if call.method == "cocos#quitPlayer" { GetCocosPlayerUtils().quit() result(nil) } else if call.method == "cocos#waitForCocos" { result(nil) } else { result(FlutterMethodNotImplemented) } } } func setDisabledUnload(enabled: Bool) { } public func view() -> UIView { return _rootView; } private func startCocosIfNeeded() { GetCocosPlayerUtils().createPlayer(completed: { [self] (view: UIView?) in }) } func attachView() { startCocosIfNeeded() let cocosView = GetCocosPlayerUtils().ufw?.appController()?.rootView if let superview = cocosView?.superview { cocosView?.removeFromSuperview() superview.layoutIfNeeded() } if let cocosView = cocosView { _rootView.addSubview(cocosView) _rootView.layoutIfNeeded() self.channel?.invokeMethod("events#onViewReattached", arguments: "") } GetCocosPlayerUtils().resume() } func reattachView() { let cocosView = GetCocosPlayerUtils().ufw?.appController()?.rootView let superview = cocosView?.superview if superview != _rootView { attachView() } GetCocosPlayerUtils().resume() } func removeViewIfNeeded() { if GetCocosPlayerUtils().ufw == nil { return } let cocosView = GetCocosPlayerUtils().ufw?.appController()?.rootView if _rootView == cocosView?.superview { if globalControllers.isEmpty { cocosView?.removeFromSuperview() cocosView?.superview?.layoutIfNeeded() } else { globalControllers.last?.reattachView() } } GetCocosPlayerUtils().resume() } func dispose() { if _disposed { return } globalControllers.removeAll{ value in return value == self } channel?.setMethodCallHandler(nil) removeViewIfNeeded() _disposed = true } /// Handles messages from cocos in the current view func handleMessage(message: String) { self.channel?.invokeMethod("events#onCocosMessage", arguments: message) } /// Handles scene changed event from cocos in the current view func handleSceneChangeEvent(info: Dictionary) { self.channel?.invokeMethod("events#onCocosSceneLoaded", arguments: info) } /// Post messages to cocos from flutter func postMessage(call: FlutterMethodCall, result: FlutterResult) { guard let args = call.arguments else { result("iOS could not recognize flutter arguments in method: (postMessage)") return } if let myArgs = args as? [String: Any], let gObj = myArgs["gameObject"] as? String, let method = myArgs["methodName"] as? String, let message = myArgs["message"] as? String { GetCocosPlayerUtils().postMessageToCocos(gameObject: gObj, cocosMethodName: method, cocosMessage: message) result(nil) } else { result(FlutterError(code: "-1", message: "iOS could not extract " + "flutter arguments in method: (postMessage)", details: nil)) } } }