no message
This commit is contained in:
		
							parent
							
								
									24fc4c113d
								
							
						
					
					
						commit
						a8f3ce3307
					
				| @ -109,18 +109,18 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: leak_tracker | ||||
|       sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" | ||||
|       sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "10.0.5" | ||||
|     version: "10.0.4" | ||||
|   leak_tracker_flutter_testing: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: leak_tracker_flutter_testing | ||||
|       sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" | ||||
|       sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.0.5" | ||||
|     version: "3.0.3" | ||||
|   leak_tracker_testing: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @ -149,18 +149,18 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: material_color_utilities | ||||
|       sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec | ||||
|       sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.11.1" | ||||
|     version: "0.8.0" | ||||
|   meta: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: meta | ||||
|       sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 | ||||
|       sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "1.15.0" | ||||
|     version: "1.12.0" | ||||
|   path: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @ -173,10 +173,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: platform | ||||
|       sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" | ||||
|       sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "3.1.5" | ||||
|     version: "3.1.4" | ||||
|   plugin_platform_interface: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @ -222,6 +222,14 @@ packages: | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.1.2" | ||||
|   stream_transform: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: stream_transform | ||||
|       sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "2.1.1" | ||||
|   string_scanner: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @ -250,10 +258,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: test_api | ||||
|       sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" | ||||
|       sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "0.7.2" | ||||
|     version: "0.7.0" | ||||
|   vector_math: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @ -266,10 +274,10 @@ packages: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|       name: vm_service | ||||
|       sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" | ||||
|       sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" | ||||
|       url: "https://pub.dev" | ||||
|     source: hosted | ||||
|     version: "14.2.5" | ||||
|     version: "14.2.1" | ||||
|   webdriver: | ||||
|     dependency: transitive | ||||
|     description: | ||||
| @ -279,5 +287,5 @@ packages: | ||||
|     source: hosted | ||||
|     version: "3.0.3" | ||||
| sdks: | ||||
|   dart: ">=3.5.4 <4.0.0" | ||||
|   dart: ">=3.4.4 <4.0.0" | ||||
|   flutter: ">=3.18.0-18.0.pre.54" | ||||
|  | ||||
| @ -5,7 +5,7 @@ description: "Demonstrates how to use the flutter_cocos_view plugin." | ||||
| publish_to: 'none' # Remove this line if you wish to publish to pub.dev | ||||
| 
 | ||||
| environment: | ||||
|   sdk: ^3.5.4 | ||||
|   sdk: ^3.4.4 | ||||
| 
 | ||||
| # Dependencies specify other packages that your package needs in order to work. | ||||
| # To automatically upgrade your package dependencies to the latest versions | ||||
|  | ||||
| @ -5,10 +5,11 @@ | ||||
| // platforms in the `pubspec.yaml` at | ||||
| // https://flutter.dev/to/pubspec-plugin-platforms. | ||||
| 
 | ||||
| import 'flutter_cocos_view_platform_interface.dart'; | ||||
| library flutter_Cocos_widget; | ||||
| 
 | ||||
| class FlutterCocosView { | ||||
|   Future<String?> getPlatformVersion() { | ||||
|     return FlutterCocosViewPlatform.instance.getPlatformVersion(); | ||||
|   } | ||||
| } | ||||
| export 'src/facade_controller.dart'; | ||||
| export 'src/facade_widget.dart' | ||||
| if (dart.library.io) 'src/io/cocos_widget.dart'; | ||||
| export 'src/helpers/events.dart'; | ||||
| export 'src/helpers/misc.dart'; | ||||
| export 'src/helpers/types.dart'; | ||||
|  | ||||
| @ -1,17 +0,0 @@ | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| 
 | ||||
| import 'flutter_cocos_view_platform_interface.dart'; | ||||
| 
 | ||||
| /// An implementation of [FlutterCocosViewPlatform] that uses method channels. | ||||
| class MethodChannelFlutterCocosView extends FlutterCocosViewPlatform { | ||||
|   /// The method channel used to interact with the native platform. | ||||
|   @visibleForTesting | ||||
|   final methodChannel = const MethodChannel('flutter_cocos_view'); | ||||
| 
 | ||||
|   @override | ||||
|   Future<String?> getPlatformVersion() async { | ||||
|     final version = await methodChannel.invokeMethod<String>('getPlatformVersion'); | ||||
|     return version; | ||||
|   } | ||||
| } | ||||
| @ -1,29 +0,0 @@ | ||||
| import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | ||||
| 
 | ||||
| import 'flutter_cocos_view_method_channel.dart'; | ||||
| 
 | ||||
| abstract class FlutterCocosViewPlatform extends PlatformInterface { | ||||
|   /// Constructs a FlutterCocosViewPlatform. | ||||
|   FlutterCocosViewPlatform() : super(token: _token); | ||||
| 
 | ||||
|   static final Object _token = Object(); | ||||
| 
 | ||||
|   static FlutterCocosViewPlatform _instance = MethodChannelFlutterCocosView(); | ||||
| 
 | ||||
|   /// The default instance of [FlutterCocosViewPlatform] to use. | ||||
|   /// | ||||
|   /// Defaults to [MethodChannelFlutterCocosView]. | ||||
|   static FlutterCocosViewPlatform get instance => _instance; | ||||
| 
 | ||||
|   /// Platform-specific implementations should set this with their own | ||||
|   /// platform-specific class that extends [FlutterCocosViewPlatform] when | ||||
|   /// they register themselves. | ||||
|   static set instance(FlutterCocosViewPlatform instance) { | ||||
|     PlatformInterface.verifyToken(instance, _token); | ||||
|     _instance = instance; | ||||
|   } | ||||
| 
 | ||||
|   Future<String?> getPlatformVersion() { | ||||
|     throw UnimplementedError('platformVersion() has not been implemented.'); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										103
									
								
								lib/src/facade_controller.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								lib/src/facade_controller.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| typedef void CocosCreatedCallback(CocosWidgetController controller); | ||||
| 
 | ||||
| abstract class CocosWidgetController { | ||||
|   static dynamic webRegistrar; | ||||
| 
 | ||||
|   /// Method required for web initialization | ||||
|   static void registerWith(dynamic registrar) { | ||||
|     webRegistrar = registrar; | ||||
|   } | ||||
| 
 | ||||
|   /// Initialize [CocosWidgetController] with [id] | ||||
|   /// Mainly for internal use when instantiating a [CocosWidgetController] passed | ||||
|   /// in [CocosWidget.onCocosCreated] callback. | ||||
|   static Future<CocosWidgetController> init( | ||||
|       int id, dynamic CocosWidgetState) async { | ||||
|     throw UnimplementedError('init() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Checks to see if Cocos player is ready to be used | ||||
|   /// Returns `true` if Cocos player is ready. | ||||
|   Future<bool?>? isReady() { | ||||
|     throw UnimplementedError('isReady() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Get the current pause state of the Cocos player | ||||
|   /// Returns `true` if Cocos player is paused. | ||||
|   Future<bool?>? isPaused() { | ||||
|     throw UnimplementedError('isPaused() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Get the current load state of the Cocos player | ||||
|   /// Returns `true` if Cocos player is loaded. | ||||
|   Future<bool?>? isLoaded() { | ||||
|     throw UnimplementedError('isLoaded() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Helper method to know if Cocos has been put in background mode (WIP) unstable | ||||
|   /// Returns `true` if Cocos player is in background. | ||||
|   Future<bool?>? inBackground() { | ||||
|     throw UnimplementedError('inBackground() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Creates a Cocos player if it's not already created. Please only call this if Cocos is not ready, | ||||
|   /// or is in unloaded state. Use [isLoaded] to check. | ||||
|   /// Returns `true` if Cocos player was created succesfully. | ||||
|   Future<bool?>? create() { | ||||
|     throw UnimplementedError('create() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Post message to Cocos from flutter. This method takes in a string [message]. | ||||
|   /// The [gameObject] must match the name of an actual Cocos game object in a scene at runtime, and the [methodName], | ||||
|   /// must exist in a `MonoDevelop` `class` and also exposed as a method. [message] is an parameter taken by the method | ||||
|   /// | ||||
|   /// ```dart | ||||
|   /// postMessage("GameManager", "openScene", "ThirdScene") | ||||
|   /// ``` | ||||
|   Future<void>? postMessage(String gameObject, methodName, message) { | ||||
|     throw UnimplementedError('postMessage() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Post message to Cocos from flutter. This method takes in a Json or map structure as the [message]. | ||||
|   /// The [gameObject] must match the name of an actual Cocos game object in a scene at runtime, and the [methodName], | ||||
|   /// must exist in a `MonoDevelop` `class` and also exposed as a method. [message] is an parameter taken by the method | ||||
|   /// | ||||
|   /// ```dart | ||||
|   /// postJsonMessage("GameManager", "openScene", {"buildIndex": 3, "name": "ThirdScene"}) | ||||
|   /// ``` | ||||
|   Future<void>? postJsonMessage( | ||||
|       String gameObject, String methodName, Map<String, dynamic> message) { | ||||
|     throw UnimplementedError('postJsonMessage() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Pause the Cocos in-game player with this method | ||||
|   Future<void>? pause() { | ||||
|     throw UnimplementedError('pause() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Resume the Cocos in-game player with this method idf it is in a paused state | ||||
|   Future<void>? resume() { | ||||
|     throw UnimplementedError('resume() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Sometimes you want to open Cocos in it's own process and openInNativeProcess does just that. | ||||
|   /// It works for Android and iOS is WIP | ||||
|   Future<void>? openInNativeProcess() { | ||||
|     throw UnimplementedError('openInNativeProcess() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Unloads Cocos player from th current process (Works on Android only for now) | ||||
|   /// iOS is WIP. For more information please read [Cocos Docs](https://docs.Cocos3d.com/2020.2/Documentation/Manual/CocosasaLibrary.html) | ||||
|   Future<void>? unload() { | ||||
|     throw UnimplementedError('unload() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Quits Cocos player. Note that this kills the current flutter process, thus quiting the app | ||||
|   Future<void>? quit() { | ||||
|     throw UnimplementedError('quit() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   void dispose() { | ||||
|     throw UnimplementedError('dispose() has not been implemented.'); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										89
									
								
								lib/src/facade_widget.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								lib/src/facade_widget.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter_cocos_view/src/facade_controller.dart'; | ||||
| 
 | ||||
| import 'helpers/misc.dart'; | ||||
| 
 | ||||
| class CocosWidget extends StatefulWidget { | ||||
|   CocosWidget({ | ||||
|     Key? key, | ||||
|     required this.onCocosCreated, | ||||
|     this.onCocosMessage, | ||||
|     this.fullscreen = false, | ||||
|     this.enablePlaceholder = false, | ||||
|     this.runImmediately = false, | ||||
|     this.unloadOnDispose = false, | ||||
|     this.printSetupLog = true, | ||||
|     this.onCocosUnloaded, | ||||
|     this.gestureRecognizers, | ||||
|     this.placeholder, | ||||
|     this.useAndroidViewSurface = false, | ||||
|     this.onCocosSceneLoaded, | ||||
|     this.uiLevel = 1, | ||||
|     this.borderRadius = BorderRadius.zero, | ||||
|     this.layoutDirection, | ||||
|     this.hideStatus = false, | ||||
|   }); | ||||
| 
 | ||||
|   ///Event fires when the Cocos player is created. | ||||
|   final CocosCreatedCallback onCocosCreated; | ||||
| 
 | ||||
|   ///Event fires when the [CocosWidget] gets a message from Cocos. | ||||
|   final CocosMessageCallback? onCocosMessage; | ||||
| 
 | ||||
|   ///Event fires when the [CocosWidget] gets a scene loaded from Cocos. | ||||
|   final CocosSceneChangeCallback? onCocosSceneLoaded; | ||||
| 
 | ||||
|   ///Event fires when the [CocosWidget] Cocos player gets unloaded. | ||||
|   final CocosUnloadCallback? onCocosUnloaded; | ||||
| 
 | ||||
|   final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers; | ||||
| 
 | ||||
|   /// Set to true to force Cocos to fullscreen | ||||
|   final bool fullscreen; | ||||
| 
 | ||||
|   /// Set to true to force Cocos to fullscreen | ||||
|   final bool hideStatus; | ||||
| 
 | ||||
|   /// Controls the layer in which Cocos widget is rendered in flutter (defaults to 1) | ||||
|   final int uiLevel; | ||||
| 
 | ||||
|   /// This flag tells android to load Cocos as the flutter app starts (Android only) | ||||
|   final bool runImmediately; | ||||
| 
 | ||||
|   /// This flag tells android to unload Cocos whenever widget is disposed | ||||
|   final bool unloadOnDispose; | ||||
| 
 | ||||
|   /// This flag enables placeholder widget | ||||
|   final bool enablePlaceholder; | ||||
| 
 | ||||
|   /// This flag enables placeholder widget | ||||
|   final bool printSetupLog; | ||||
| 
 | ||||
|   /// This flag allows you use AndroidView instead of PlatformViewLink for android | ||||
|   final bool? useAndroidViewSurface; | ||||
| 
 | ||||
|   /// This is just a helper to render a placeholder widget | ||||
|   final Widget? placeholder; | ||||
| 
 | ||||
|   /// Border radius | ||||
|   final BorderRadius borderRadius; | ||||
| 
 | ||||
|   /// The layout direction to use for the embedded view. | ||||
|   /// | ||||
|   /// If this is null, the ambient [Directionality] is used instead. If there is | ||||
|   /// no ambient [Directionality], [TextDirection.ltr] is used. | ||||
|   final TextDirection? layoutDirection; | ||||
| 
 | ||||
|   @override | ||||
|   _CocosWidgetState createState() => _CocosWidgetState(); | ||||
| } | ||||
| 
 | ||||
| class _CocosWidgetState extends State<CocosWidget> { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Text( | ||||
|         '$defaultTargetPlatform is not yet supported by the Cocos player plugin'); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										36
									
								
								lib/src/helpers/events.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								lib/src/helpers/events.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| import 'package:flutter_cocos_view/src/helpers/types.dart'; | ||||
| 
 | ||||
| class CocosEvent<T> { | ||||
|   /// The ID of the Cocos this event is associated to. | ||||
|   final int cocosId; | ||||
| 
 | ||||
|   /// The value wrapped by this event | ||||
|   final T value; | ||||
| 
 | ||||
|   /// Build a Cocos Event, that relates a mapId with a given value. | ||||
|   /// | ||||
|   /// The `cocosId` is the id of the map that triggered the event. | ||||
|   /// `value` may be `null` in events that don't transport any meaningful data. | ||||
|   CocosEvent(this.cocosId, this.value); | ||||
| } | ||||
| 
 | ||||
| class CocosSceneLoadedEvent extends CocosEvent<SceneLoaded?> { | ||||
|   CocosSceneLoadedEvent(int cocosId, SceneLoaded? value) | ||||
|       : super(cocosId, value); | ||||
| } | ||||
| 
 | ||||
| class CocosLoadedEvent extends CocosEvent<void> { | ||||
|   CocosLoadedEvent(int cocosId, void value) : super(cocosId, value); | ||||
| } | ||||
| 
 | ||||
| class CocosUnLoadedEvent extends CocosEvent<void> { | ||||
|   CocosUnLoadedEvent(int cocosId, void value) : super(cocosId, value); | ||||
| } | ||||
| 
 | ||||
| class CocosCreatedEvent extends CocosEvent<void> { | ||||
|   CocosCreatedEvent(int cocosId, void value) : super(cocosId, value); | ||||
| } | ||||
| 
 | ||||
| class CocosMessageEvent extends CocosEvent<dynamic> { | ||||
|   CocosMessageEvent(int cocosId, dynamic value) : super(cocosId, value); | ||||
| } | ||||
							
								
								
									
										27
									
								
								lib/src/helpers/misc.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lib/src/helpers/misc.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| import 'package:flutter_cocos_view/src/helpers/types.dart'; | ||||
| 
 | ||||
| /// Error thrown when an unknown cocos ID is provided to a method channel API. | ||||
| class UnknownCocosIDError extends Error { | ||||
|   /// Creates an assertion error with the provided [cocosId] and optional | ||||
|   /// [message]. | ||||
|   UnknownCocosIDError(this.cocosId, [this.message]); | ||||
| 
 | ||||
|   /// The unknown ID. | ||||
|   final int cocosId; | ||||
| 
 | ||||
|   /// Message describing the assertion error. | ||||
|   final Object? message; | ||||
| 
 | ||||
|   String toString() { | ||||
|     if (message != null) { | ||||
|       return "Unknown cocos ID $cocosId: ${Error.safeToString(message)}"; | ||||
|     } | ||||
|     return "Unknown cocos ID $cocosId"; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| typedef void CocosMessageCallback(dynamic handler); | ||||
| 
 | ||||
| typedef void CocosSceneChangeCallback(SceneLoaded? message); | ||||
| 
 | ||||
| typedef void CocosUnloadCallback(); | ||||
							
								
								
									
										31
									
								
								lib/src/helpers/types.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								lib/src/helpers/types.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| class SceneLoaded { | ||||
|   final String? name; | ||||
|   final int? buildIndex; | ||||
|   final bool? isLoaded; | ||||
|   final bool? isValid; | ||||
| 
 | ||||
|   SceneLoaded({this.name, this.buildIndex, this.isLoaded, this.isValid}); | ||||
| 
 | ||||
|   /// Mainly for internal use when calling [CameraUpdate.newCameraPosition]. | ||||
|   dynamic toMap() => <String, dynamic>{ | ||||
|         'name': name, | ||||
|         'buildIndex': buildIndex, | ||||
|         'isLoaded': isLoaded, | ||||
|         'isValid': isValid, | ||||
|       }; | ||||
| 
 | ||||
|   /// Deserializes [SceneLoaded] from a map. | ||||
|   /// | ||||
|   /// Mainly for internal use. | ||||
|   static SceneLoaded? fromMap(dynamic json) { | ||||
|     if (json == null) { | ||||
|       return null; | ||||
|     } | ||||
|     return SceneLoaded( | ||||
|       name: json['name'], | ||||
|       buildIndex: json['buildIndex'], | ||||
|       isLoaded: json['isLoaded'], | ||||
|       isValid: json['isValid'], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										201
									
								
								lib/src/io/cocos_widget.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								lib/src/io/cocos_widget.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,201 @@ | ||||
| import 'dart:developer'; | ||||
| 
 | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| 
 | ||||
| import '../facade_controller.dart'; | ||||
| import '../helpers/misc.dart'; | ||||
| import 'device_method.dart'; | ||||
| import 'mobile_cocos_widget_controller.dart'; | ||||
| import 'cocos_widget_platform.dart'; | ||||
| 
 | ||||
| int _nextCocosCreationId = 0; | ||||
| 
 | ||||
| /// Android specific settings for [CocosWidget]. | ||||
| class AndroidCocosWidgetFlutter { | ||||
|   /// Whether to render [CocosWidget] with a [AndroidViewSurface] to build the Flutter Cocos widget. | ||||
|   /// | ||||
|   /// This implementation uses hybrid composition to render the Flutter Cocos | ||||
|   /// Widget on Android. This comes at the cost of some performance on Android | ||||
|   /// versions below 10. See | ||||
|   /// https://flutter.dev/docs/development/platform-integration/platform-views#performance for more | ||||
|   /// information. | ||||
|   /// | ||||
|   /// Defaults to true. | ||||
|   static bool get useAndroidViewSurface { | ||||
|     final CocosWidgetPlatform platform = CocosWidgetPlatform.instance; | ||||
|     if (platform is MethodChannelCocosWidget) { | ||||
|       return platform.useAndroidViewSurface; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   /// Set whether to render [CocosWidget] with a [AndroidViewSurface] to build the Flutter Cocos widget. | ||||
|   /// | ||||
|   /// This implementation uses hybrid composition to render the Cocos Widget | ||||
|   /// Widget on Android. This comes at the cost of some performance on Android | ||||
|   /// versions below 10. See | ||||
|   /// https://flutter.dev/docs/development/platform-integration/platform-views#performance for more | ||||
|   /// information. | ||||
|   /// | ||||
|   /// Defaults to true. | ||||
|   static set useAndroidViewSurface(bool useAndroidViewSurface) { | ||||
|     final CocosWidgetPlatform platform = CocosWidgetPlatform.instance; | ||||
|     if (platform is MethodChannelCocosWidget) { | ||||
|       platform.useAndroidViewSurface = useAndroidViewSurface; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| typedef MobileCocosWidgetState = _CocosWidgetState; | ||||
| 
 | ||||
| class CocosWidget extends StatefulWidget { | ||||
|   CocosWidget({ | ||||
|     Key? key, | ||||
|     required this.onCocosCreated, | ||||
|     this.onCocosMessage, | ||||
|     this.fullscreen = false, | ||||
|     this.enablePlaceholder = false, | ||||
|     this.runImmediately = false, | ||||
|     this.unloadOnDispose = false, | ||||
|     this.printSetupLog = true, | ||||
|     this.onCocosUnloaded, | ||||
|     this.gestureRecognizers, | ||||
|     this.placeholder, | ||||
|     this.useAndroidViewSurface = false, | ||||
|     this.onCocosSceneLoaded, | ||||
|     this.uiLevel = 1, | ||||
|     this.borderRadius = BorderRadius.zero, | ||||
|     this.layoutDirection, | ||||
|     this.hideStatus = false, | ||||
|     this.webUrl, | ||||
|   }); | ||||
| 
 | ||||
|   ///Event fires when the Cocos player is created. | ||||
|   final CocosCreatedCallback onCocosCreated; | ||||
| 
 | ||||
|   /// WebGL url source. | ||||
|   final String? webUrl; | ||||
| 
 | ||||
|   ///Event fires when the [CocosWidget] gets a message from Cocos. | ||||
|   final CocosMessageCallback? onCocosMessage; | ||||
| 
 | ||||
|   ///Event fires when the [CocosWidget] gets a scene loaded from Cocos. | ||||
|   final CocosSceneChangeCallback? onCocosSceneLoaded; | ||||
| 
 | ||||
|   ///Event fires when the [CocosWidget] Cocos player gets unloaded. | ||||
|   final CocosUnloadCallback? onCocosUnloaded; | ||||
| 
 | ||||
|   final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers; | ||||
| 
 | ||||
|   /// Set to true to force Cocos to fullscreen | ||||
|   final bool fullscreen; | ||||
| 
 | ||||
|   /// Set to true to force Cocos to fullscreen | ||||
|   final bool hideStatus; | ||||
| 
 | ||||
|   /// Controls the layer in which Cocos widget is rendered in flutter (defaults to 1) | ||||
|   final int uiLevel; | ||||
| 
 | ||||
|   /// This flag tells android to load Cocos as the flutter app starts (Android only) | ||||
|   final bool runImmediately; | ||||
| 
 | ||||
|   /// This flag tells android to unload Cocos whenever widget is disposed | ||||
|   final bool unloadOnDispose; | ||||
| 
 | ||||
|   /// This flag enables placeholder widget | ||||
|   final bool enablePlaceholder; | ||||
| 
 | ||||
|   /// This flag enables placeholder widget | ||||
|   final bool printSetupLog; | ||||
| 
 | ||||
|   /// This flag allows you use AndroidView instead of PlatformViewLink for android | ||||
|   final bool? useAndroidViewSurface; | ||||
| 
 | ||||
|   /// This is just a helper to render a placeholder widget | ||||
|   final Widget? placeholder; | ||||
| 
 | ||||
|   /// Border radius | ||||
|   final BorderRadius borderRadius; | ||||
| 
 | ||||
|   /// The layout direction to use for the embedded view. | ||||
|   /// | ||||
|   /// If this is null, the ambient [Directionality] is used instead. If there is | ||||
|   /// no ambient [Directionality], [TextDirection.ltr] is used. | ||||
|   final TextDirection? layoutDirection; | ||||
| 
 | ||||
|   @override | ||||
|   _CocosWidgetState createState() => _CocosWidgetState(); | ||||
| } | ||||
| 
 | ||||
| class _CocosWidgetState extends State<CocosWidget> { | ||||
|   late int _CocosId; | ||||
| 
 | ||||
|   CocosWidgetController? _controller; | ||||
| 
 | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
| 
 | ||||
|     if (!kIsWeb) { | ||||
|       _CocosId = _nextCocosCreationId++; | ||||
|     } else { | ||||
|       _CocosId = 0; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> dispose() async { | ||||
|     if (!kIsWeb) { | ||||
|       if (_nextCocosCreationId > 0) --_nextCocosCreationId; | ||||
|     } | ||||
|     try { | ||||
|       _controller?.dispose(); | ||||
|       _controller = null; | ||||
|     } catch (e) { | ||||
|       // todo: implement | ||||
|     } | ||||
|     super.dispose(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     final Map<String, dynamic> CocosOptions = <String, dynamic>{ | ||||
|       'fullscreen': widget.fullscreen, | ||||
|       'uiLevel': widget.uiLevel, | ||||
|       'hideStatus': widget.hideStatus, | ||||
|       'unloadOnDispose': widget.unloadOnDispose, | ||||
|       'runImmediately': widget.runImmediately, | ||||
|     }; | ||||
| 
 | ||||
|     if (widget.enablePlaceholder) { | ||||
|       return widget.placeholder ?? | ||||
|           Text('Placeholder mode enabled, no native code will be called'); | ||||
|     } | ||||
| 
 | ||||
|     return CocosWidgetPlatform.instance.buildViewWithTextDirection( | ||||
|       _CocosId, | ||||
|       _onPlatformViewCreated, | ||||
|       cocosOptions: CocosOptions, | ||||
|       textDirection: widget.layoutDirection ?? | ||||
|           Directionality.maybeOf(context) ?? | ||||
|           TextDirection.ltr, | ||||
|       gestureRecognizers: widget.gestureRecognizers, | ||||
|       useAndroidViewSurf: widget.useAndroidViewSurface, | ||||
|       cocosSrcUrl: widget.webUrl, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> _onPlatformViewCreated(int id) async { | ||||
|     final controller = await MobileCocosWidgetController.init(id, this); | ||||
|     _controller = controller; | ||||
|     widget.onCocosCreated(controller); | ||||
| 
 | ||||
|     if (widget.printSetupLog) { | ||||
|       log('*********************************************'); | ||||
|       log('** flutter Cocos controller setup complete **'); | ||||
|       log('*********************************************'); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										154
									
								
								lib/src/io/cocos_widget_platform.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								lib/src/io/cocos_widget_platform.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,154 @@ | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | ||||
| 
 | ||||
| import '../helpers/events.dart'; | ||||
| import 'device_method.dart'; | ||||
| 
 | ||||
| abstract class CocosWidgetPlatform extends PlatformInterface { | ||||
|   /// Constructs a CocosViewFlutterPlatform. | ||||
|   CocosWidgetPlatform() : super(token: _token); | ||||
| 
 | ||||
|   static final Object _token = Object(); | ||||
| 
 | ||||
|   static CocosWidgetPlatform _instance = MethodChannelCocosWidget(); | ||||
| 
 | ||||
|   /// The default instance of [CocosWidgetPlatform] to use. | ||||
|   /// | ||||
|   /// Defaults to [MethodChannelCocosWidgetFlutter]. | ||||
|   static CocosWidgetPlatform get instance => _instance; | ||||
| 
 | ||||
|   /// Platform-specific plugins should set this with their own platform-specific | ||||
|   /// class that extends [CocosWidgetPlatform] when they register themselves. | ||||
|   static set instance(CocosWidgetPlatform instance) { | ||||
|     PlatformInterface.verifyToken(instance, _token); | ||||
|     _instance = instance; | ||||
|   } | ||||
| 
 | ||||
|   /// /// Initializes the platform interface with [id]. | ||||
|   /// | ||||
|   /// This method is called when the plugin is first initialized. | ||||
|   Future<void> init(int cocosId) { | ||||
|     throw UnimplementedError('init() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<bool?> isReady({required int cocosId}) async { | ||||
|     throw UnimplementedError('init() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<bool?> isPaused({required int cocosId}) async { | ||||
|     throw UnimplementedError('isPaused() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<bool?> isLoaded({required int cocosId}) async { | ||||
|     throw UnimplementedError('isLoaded() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<bool?> inBackground({required int cocosId}) async { | ||||
|     throw UnimplementedError('inBackground() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<bool?> createCocosPlayer({required int cocosId}) async { | ||||
|     throw UnimplementedError('createCocosPlayer() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> postMessage( | ||||
|       {required int cocosId, | ||||
|       required String gameObject, | ||||
|       required String methodName, | ||||
|       required String message}) { | ||||
|     throw UnimplementedError('postMessage() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> postJsonMessage( | ||||
|       {required int cocosId, | ||||
|       required String gameObject, | ||||
|       required String methodName, | ||||
|       required Map message}) { | ||||
|     throw UnimplementedError('postJsonMessage() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> pausePlayer({required int cocosId}) async { | ||||
|     throw UnimplementedError('pausePlayer() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> resumePlayer({required int cocosId}) async { | ||||
|     throw UnimplementedError('resumePlayer() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Opens cocos in it's own activity. Android only. | ||||
|   Future<void> openInNativeProcess({required int cocosId}) async { | ||||
|     throw UnimplementedError('openInNativeProcess() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> unloadPlayer({required int cocosId}) async { | ||||
|     throw UnimplementedError('unloadPlayer() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> quitPlayer({required int cocosId}) async { | ||||
|     throw UnimplementedError('quitPlayer() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Stream<CocosMessageEvent> onCocosMessage({required int cocosId}) { | ||||
|     throw UnimplementedError('onCocosMessage() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Stream<CocosLoadedEvent> onCocosUnloaded({required int cocosId}) { | ||||
|     throw UnimplementedError('onCocosUnloaded() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Stream<CocosCreatedEvent> onCocosCreated({required int cocosId}) { | ||||
|     throw UnimplementedError('onCocosUnloaded() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   Stream<CocosSceneLoadedEvent> onCocosSceneLoaded({required int cocosId}) { | ||||
|     throw UnimplementedError('onCocosSceneLoaded() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Dispose of whatever resources the `cocosId` is holding on to. | ||||
|   void dispose({required int cocosId}) { | ||||
|     throw UnimplementedError('dispose() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Returns a widget displaying the cocos view | ||||
|   Widget buildView( | ||||
|     int creationId, | ||||
|     PlatformViewCreatedCallback onPlatformViewCreated, { | ||||
|     Map<String, dynamic> cocosOptions = const {}, | ||||
|     Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers, | ||||
|     bool? useAndroidViewSurf, | ||||
|     String? cocosSrcUrl, | ||||
|   }) { | ||||
|     throw UnimplementedError('buildView() has not been implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   /// Returns a widget displaying the cocos view. | ||||
|   /// | ||||
|   /// This method is similar to [buildView], but contains a parameter for | ||||
|   /// platforms that require a text direction. | ||||
|   /// | ||||
|   /// Default behavior passes all parameters except `textDirection` to | ||||
|   /// [buildView]. This is for backward compatibility with existing | ||||
|   /// implementations. Platforms that use the text direction should override | ||||
|   /// this as the primary implementation, and delegate to it from buildView. | ||||
|   Widget buildViewWithTextDirection( | ||||
|     int creationId, | ||||
|     PlatformViewCreatedCallback onPlatformViewCreated, { | ||||
|     required TextDirection textDirection, | ||||
|     Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers, | ||||
|     Map<String, dynamic> cocosOptions = const <String, dynamic>{}, | ||||
|     bool? useAndroidViewSurf, | ||||
|     String? cocosSrcUrl, | ||||
|   }) { | ||||
|     return buildView( | ||||
|       creationId, | ||||
|       onPlatformViewCreated, | ||||
|       gestureRecognizers: gestureRecognizers, | ||||
|       cocosOptions: cocosOptions, | ||||
|       useAndroidViewSurf: useAndroidViewSurf, | ||||
|       cocosSrcUrl: cocosSrcUrl, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										299
									
								
								lib/src/io/device_method.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								lib/src/io/device_method.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,299 @@ | ||||
| import 'dart:async'; | ||||
| import 'dart:convert'; | ||||
| 
 | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/gestures.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/rendering.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:stream_transform/stream_transform.dart'; | ||||
| 
 | ||||
| import '../helpers/events.dart'; | ||||
| import '../helpers/misc.dart'; | ||||
| import '../helpers/types.dart'; | ||||
| import 'cocos_widget_platform.dart'; | ||||
| import 'windows_cocos_widget_view.dart'; | ||||
| 
 | ||||
| class MethodChannelCocosWidget extends CocosWidgetPlatform { | ||||
|   // Every method call passes the int cocosId | ||||
|   late final Map<int, MethodChannel> _channels = {}; | ||||
| 
 | ||||
|   /// Set [CocosWidgetFlutterPlatform] to use [AndroidViewSurface] to build the Google Maps widget. | ||||
|   /// | ||||
|   /// This implementation uses hybrid composition to render the Cocos Widget | ||||
|   /// Widget on Android. This comes at the cost of some performance on Android | ||||
|   /// versions below 10. See | ||||
|   /// https://flutter.dev/docs/development/platform-integration/platform-views#performance for more | ||||
|   /// information. | ||||
|   /// Defaults to false. | ||||
|   bool useAndroidViewSurface = true; | ||||
| 
 | ||||
|   /// Accesses the MethodChannel associated to the passed cocosId. | ||||
|   MethodChannel channel(int cocosId) { | ||||
|     MethodChannel? channel = _channels[cocosId]; | ||||
|     if (channel == null) { | ||||
|       throw UnknownCocosIDError(cocosId); | ||||
|     } | ||||
|     return channel; | ||||
|   } | ||||
| 
 | ||||
|   MethodChannel ensureChannelInitialized(int cocosId) { | ||||
|     MethodChannel? channel = _channels[cocosId]; | ||||
|     if (channel == null) { | ||||
|       channel = MethodChannel('plugin.xraph.com/cocos_view_$cocosId'); | ||||
| 
 | ||||
|       channel.setMethodCallHandler( | ||||
|           (MethodCall call) => _handleMethodCall(call, cocosId)); | ||||
|       _channels[cocosId] = channel; | ||||
|     } | ||||
|     return channel; | ||||
|   } | ||||
| 
 | ||||
|   /// Initializes the platform interface with [id]. | ||||
|   /// | ||||
|   /// This method is called when the plugin is first initialized. | ||||
|   @override | ||||
|   Future<void> init(int cocosId) { | ||||
|     MethodChannel channel = ensureChannelInitialized(cocosId); | ||||
|     return channel.invokeMethod<void>('cocos#waitForCocos'); | ||||
|   } | ||||
| 
 | ||||
|   /// Dispose of the native resources. | ||||
|   @override | ||||
|   Future<void> dispose({int? cocosId}) async { | ||||
|     try { | ||||
|       if (cocosId != null) await channel(cocosId).invokeMethod('cocos#dispose'); | ||||
|     } catch (e) { | ||||
|       // ignore | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // The controller we need to broadcast the different events coming | ||||
|   // from handleMethodCall. | ||||
|   // | ||||
|   // It is a `broadcast` because multiple controllers will connect to | ||||
|   // different stream views of this Controller. | ||||
|   final StreamController<CocosEvent> _cocosStreamController = | ||||
|       StreamController<CocosEvent>.broadcast(); | ||||
| 
 | ||||
|   // Returns a filtered view of the events in the _controller, by cocosId. | ||||
|   Stream<CocosEvent> _events(int cocosId) => | ||||
|       _cocosStreamController.stream.where((event) => event.cocosId == cocosId); | ||||
| 
 | ||||
|   Future<dynamic> _handleMethodCall(MethodCall call, int cocosId) async { | ||||
|     switch (call.method) { | ||||
|       case "events#onCocosMessage": | ||||
|         _cocosStreamController.add(CocosMessageEvent(cocosId, call.arguments)); | ||||
|         break; | ||||
|       case "events#onCocosUnloaded": | ||||
|         _cocosStreamController.add(CocosLoadedEvent(cocosId, call.arguments)); | ||||
|         break; | ||||
|       case "events#onCocosSceneLoaded": | ||||
|         _cocosStreamController.add(CocosSceneLoadedEvent( | ||||
|             cocosId, SceneLoaded.fromMap(call.arguments))); | ||||
|         break; | ||||
|       case "events#onCocosCreated": | ||||
|         _cocosStreamController.add(CocosCreatedEvent(cocosId, call.arguments)); | ||||
|         break; | ||||
|       default: | ||||
|         throw UnimplementedError("Unimplemented ${call.method} method"); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<bool?> isPaused({required int cocosId}) async { | ||||
|     return await channel(cocosId).invokeMethod('cocos#isPaused'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<bool?> isReady({required int cocosId}) async { | ||||
|     return await channel(cocosId).invokeMethod('cocos#isReady'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<bool?> isLoaded({required int cocosId}) async { | ||||
|     return await channel(cocosId).invokeMethod('cocos#isLoaded'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<bool?> inBackground({required int cocosId}) async { | ||||
|     return await channel(cocosId).invokeMethod('cocos#inBackground'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<bool?> createCocosPlayer({required int cocosId}) async { | ||||
|     return await channel(cocosId).invokeMethod('cocos#createPlayer'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Stream<CocosMessageEvent> onCocosMessage({required int cocosId}) { | ||||
|     return _events(cocosId).whereType<CocosMessageEvent>(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Stream<CocosLoadedEvent> onCocosUnloaded({required int cocosId}) { | ||||
|     return _events(cocosId).whereType<CocosLoadedEvent>(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Stream<CocosCreatedEvent> onCocosCreated({required int cocosId}) { | ||||
|     return _events(cocosId).whereType<CocosCreatedEvent>(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Stream<CocosSceneLoadedEvent> onCocosSceneLoaded({required int cocosId}) { | ||||
|     return _events(cocosId).whereType<CocosSceneLoadedEvent>(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget buildViewWithTextDirection( | ||||
|     int creationId, | ||||
|     PlatformViewCreatedCallback onPlatformViewCreated, { | ||||
|     required TextDirection textDirection, | ||||
|     Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers, | ||||
|     Map<String, dynamic> cocosOptions = const <String, dynamic>{}, | ||||
|     bool? useAndroidViewSurf, | ||||
|     bool? height, | ||||
|     bool? width, | ||||
|     bool? cocosWebSource, | ||||
|     String? cocosSrcUrl, | ||||
|   }) { | ||||
|     final String _viewType = 'plugin.xraph.com/cocos_view'; | ||||
| 
 | ||||
|     if (useAndroidViewSurf != null) useAndroidViewSurface = useAndroidViewSurf; | ||||
| 
 | ||||
|     final Map<String, dynamic> creationParams = cocosOptions; | ||||
| 
 | ||||
|     if (defaultTargetPlatform == TargetPlatform.windows) { | ||||
|       return WindowsCocosWidgetView(); | ||||
|     } | ||||
| 
 | ||||
|     if (defaultTargetPlatform == TargetPlatform.android) { | ||||
|       if (!useAndroidViewSurface) { | ||||
|         return AndroidView( | ||||
|           viewType: _viewType, | ||||
|           onPlatformViewCreated: onPlatformViewCreated, | ||||
|           gestureRecognizers: gestureRecognizers, | ||||
|           creationParams: creationParams, | ||||
|           creationParamsCodec: const StandardMessageCodec(), | ||||
|           hitTestBehavior: PlatformViewHitTestBehavior.opaque, | ||||
|           layoutDirection: TextDirection.ltr, | ||||
|         ); | ||||
|       } | ||||
| 
 | ||||
|       return PlatformViewLink( | ||||
|         viewType: _viewType, | ||||
|         surfaceFactory: ( | ||||
|           BuildContext context, | ||||
|           PlatformViewController controller, | ||||
|         ) { | ||||
|           return AndroidViewSurface( | ||||
|             controller: controller as AndroidViewController, | ||||
|             gestureRecognizers: gestureRecognizers ?? | ||||
|                 const <Factory<OneSequenceGestureRecognizer>>{}, | ||||
|             hitTestBehavior: PlatformViewHitTestBehavior.opaque, | ||||
|           ); | ||||
|         }, | ||||
|         onCreatePlatformView: (PlatformViewCreationParams params) { | ||||
|           final controller = PlatformViewsService.initExpensiveAndroidView( | ||||
|             id: params.id, | ||||
|             viewType: _viewType, | ||||
|             layoutDirection: TextDirection.ltr, | ||||
|             creationParams: creationParams, | ||||
|             creationParamsCodec: const StandardMessageCodec(), | ||||
|             onFocus: () => params.onFocusChanged(true), | ||||
|           ); | ||||
| 
 | ||||
|           controller | ||||
|             ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) | ||||
|             ..addOnPlatformViewCreatedListener(onPlatformViewCreated) | ||||
|             ..create(); | ||||
|           return controller; | ||||
|         }, | ||||
|       ); | ||||
|     } else if (defaultTargetPlatform == TargetPlatform.iOS) { | ||||
|       return UiKitView( | ||||
|         viewType: _viewType, | ||||
|         onPlatformViewCreated: onPlatformViewCreated, | ||||
|         gestureRecognizers: gestureRecognizers, | ||||
|         creationParams: creationParams, | ||||
|         creationParamsCodec: const StandardMessageCodec(), | ||||
|       ); | ||||
|     } | ||||
|     return Text( | ||||
|         '$defaultTargetPlatform is not yet supported by the cocos player plugin'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget buildView( | ||||
|     int creationId, | ||||
|     PlatformViewCreatedCallback onPlatformViewCreated, { | ||||
|     Map<String, dynamic> cocosOptions = const {}, | ||||
|     Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers, | ||||
|     bool? useAndroidViewSurf, | ||||
|     String? cocosSrcUrl, | ||||
|   }) { | ||||
|     return buildViewWithTextDirection( | ||||
|       creationId, | ||||
|       onPlatformViewCreated, | ||||
|       textDirection: TextDirection.ltr, | ||||
|       gestureRecognizers: gestureRecognizers, | ||||
|       cocosOptions: cocosOptions, | ||||
|       useAndroidViewSurf: useAndroidViewSurf, | ||||
|       cocosSrcUrl: cocosSrcUrl, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> postMessage({ | ||||
|     required int cocosId, | ||||
|     required String gameObject, | ||||
|     required String methodName, | ||||
|     required String message, | ||||
|   }) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#postMessage', <String, dynamic>{ | ||||
|       'gameObject': gameObject, | ||||
|       'methodName': methodName, | ||||
|       'message': message, | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> postJsonMessage({ | ||||
|     required int cocosId, | ||||
|     required String gameObject, | ||||
|     required String methodName, | ||||
|     required Map message, | ||||
|   }) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#postMessage', <String, dynamic>{ | ||||
|       'gameObject': gameObject, | ||||
|       'methodName': methodName, | ||||
|       'message': json.encode(message), | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> pausePlayer({required int cocosId}) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#pausePlayer'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> resumePlayer({required int cocosId}) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#resumePlayer'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> openInNativeProcess({required int cocosId}) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#openInNativeProcess'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> unloadPlayer({required int cocosId}) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#unloadPlayer'); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> quitPlayer({required int cocosId}) async { | ||||
|     await channel(cocosId).invokeMethod('cocos#quitPlayer'); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										4
									
								
								lib/src/io/io.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/src/io/io.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| export '../facade_controller.dart'; | ||||
| export '../helpers/events.dart'; | ||||
| export '../helpers/misc.dart'; | ||||
| export '../helpers/types.dart'; | ||||
							
								
								
									
										213
									
								
								lib/src/io/mobile_cocos_widget_controller.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								lib/src/io/mobile_cocos_widget_controller.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,213 @@ | ||||
| import 'dart:async'; | ||||
| 
 | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| 
 | ||||
| import '../facade_controller.dart'; | ||||
| import '../helpers/events.dart'; | ||||
| import 'device_method.dart'; | ||||
| import 'cocos_widget.dart'; | ||||
| import 'cocos_widget_platform.dart'; | ||||
| 
 | ||||
| class MobileCocosWidgetController extends CocosWidgetController { | ||||
|   final MobileCocosWidgetState _cocosWidgetState; | ||||
| 
 | ||||
|   /// The cocosId for this controller | ||||
|   final int cocosId; | ||||
| 
 | ||||
|   /// used for cancel the subscription | ||||
|   StreamSubscription? _onCocosMessageSub, | ||||
|       _onCocosSceneLoadedSub, | ||||
|       _onCocosUnloadedSub; | ||||
| 
 | ||||
|   MobileCocosWidgetController._(this._cocosWidgetState, | ||||
|       {required this.cocosId}) { | ||||
|     _connectStreams(cocosId); | ||||
|   } | ||||
| 
 | ||||
|   /// Initialize [CocosWidgetController] with [id] | ||||
|   /// Mainly for internal use when instantiating a [CocosWidgetController] passed | ||||
|   /// in [CocosWidget.onCocosCreated] callback. | ||||
|   static Future<MobileCocosWidgetController> init( | ||||
|       int id, MobileCocosWidgetState cocosWidgetState) async { | ||||
|     await CocosWidgetPlatform.instance.init(id); | ||||
|     return MobileCocosWidgetController._( | ||||
|       cocosWidgetState, | ||||
|       cocosId: id, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @visibleForTesting | ||||
|   MethodChannel? get channel { | ||||
|     if (CocosWidgetPlatform.instance is MethodChannelCocosWidget) { | ||||
|       return (CocosWidgetPlatform.instance as MethodChannelCocosWidget) | ||||
|           .channel(cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   void _connectStreams(int cocosId) { | ||||
|     if (_cocosWidgetState.widget.onCocosMessage != null) { | ||||
|       _onCocosMessageSub = CocosWidgetPlatform.instance | ||||
|           .onCocosMessage(cocosId: cocosId) | ||||
|           .listen((CocosMessageEvent e) => | ||||
|               _cocosWidgetState.widget.onCocosMessage!(e.value)); | ||||
|     } | ||||
| 
 | ||||
|     if (_cocosWidgetState.widget.onCocosSceneLoaded != null) { | ||||
|       _onCocosSceneLoadedSub = CocosWidgetPlatform.instance | ||||
|           .onCocosSceneLoaded(cocosId: cocosId) | ||||
|           .listen((CocosSceneLoadedEvent e) => | ||||
|               _cocosWidgetState.widget.onCocosSceneLoaded!(e.value)); | ||||
|     } | ||||
| 
 | ||||
|     if (_cocosWidgetState.widget.onCocosUnloaded != null) { | ||||
|       _onCocosUnloadedSub = CocosWidgetPlatform.instance | ||||
|           .onCocosUnloaded(cocosId: cocosId) | ||||
|           .listen((_) => _cocosWidgetState.widget.onCocosUnloaded!()); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Checks to see if cocos player is ready to be used | ||||
|   /// Returns `true` if cocos player is ready. | ||||
|   Future<bool?>? isReady() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.isReady(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Get the current pause state of the cocos player | ||||
|   /// Returns `true` if cocos player is paused. | ||||
|   Future<bool?>? isPaused() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.isPaused(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Get the current load state of the cocos player | ||||
|   /// Returns `true` if cocos player is loaded. | ||||
|   Future<bool?>? isLoaded() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.isLoaded(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Helper method to know if Cocos has been put in background mode (WIP) unstable | ||||
|   /// Returns `true` if cocos player is in background. | ||||
|   Future<bool?>? inBackground() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.inBackground(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Creates a cocos player if it's not already created. Please only call this if cocos is not ready, | ||||
|   /// or is in unloaded state. Use [isLoaded] to check. | ||||
|   /// Returns `true` if cocos player was created succesfully. | ||||
|   Future<bool?>? create() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.createCocosPlayer(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Post message to cocos from flutter. This method takes in a string [message]. | ||||
|   /// The [gameObject] must match the name of an actual cocos game object in a scene at runtime, and the [methodName], | ||||
|   /// must exist in a `MonoDevelop` `class` and also exposed as a method. [message] is an parameter taken by the method | ||||
|   /// | ||||
|   /// ```dart | ||||
|   /// postMessage("GameManager", "openScene", "ThirdScene") | ||||
|   /// ``` | ||||
|   Future<void>? postMessage(String gameObject, methodName, message) { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.postMessage( | ||||
|         cocosId: cocosId, | ||||
|         gameObject: gameObject, | ||||
|         methodName: methodName, | ||||
|         message: message, | ||||
|       ); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Post message to cocos from flutter. This method takes in a Json or map structure as the [message]. | ||||
|   /// The [gameObject] must match the name of an actual cocos game object in a scene at runtime, and the [methodName], | ||||
|   /// must exist in a `MonoDevelop` `class` and also exposed as a method. [message] is an parameter taken by the method | ||||
|   /// | ||||
|   /// ```dart | ||||
|   /// postJsonMessage("GameManager", "openScene", {"buildIndex": 3, "name": "ThirdScene"}) | ||||
|   /// ``` | ||||
|   Future<void>? postJsonMessage( | ||||
|       String gameObject, String methodName, Map<String, dynamic> message) { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.postJsonMessage( | ||||
|         cocosId: cocosId, | ||||
|         gameObject: gameObject, | ||||
|         methodName: methodName, | ||||
|         message: message, | ||||
|       ); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Pause the cocos in-game player with this method | ||||
|   Future<void>? pause() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.pausePlayer(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Resume the cocos in-game player with this method idf it is in a paused state | ||||
|   Future<void>? resume() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.resumePlayer(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Sometimes you want to open cocos in it's own process and openInNativeProcess does just that. | ||||
|   /// It works for Android and iOS is WIP | ||||
|   Future<void>? openInNativeProcess() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.openInNativeProcess(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Unloads cocos player from th current process (Works on Android only for now) | ||||
|   /// iOS is WIP. For more information please read [Cocos Docs](https://docs.cocos3d.com/2020.2/Documentation/Manual/CocosasaLibrary.html) | ||||
|   Future<void>? unload() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.unloadPlayer(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// Quits cocos player. Note that this kills the current flutter process, thus quiting the app | ||||
|   Future<void>? quit() { | ||||
|     if (!_cocosWidgetState.widget.enablePlaceholder) { | ||||
|       return CocosWidgetPlatform.instance.quitPlayer(cocosId: cocosId); | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /// cancel the subscriptions when dispose called | ||||
|   void _cancelSubscriptions() { | ||||
|     _onCocosMessageSub?.cancel(); | ||||
|     _onCocosSceneLoadedSub?.cancel(); | ||||
|     _onCocosUnloadedSub?.cancel(); | ||||
| 
 | ||||
|     _onCocosMessageSub = null; | ||||
|     _onCocosSceneLoadedSub = null; | ||||
|     _onCocosUnloadedSub = null; | ||||
|   } | ||||
| 
 | ||||
|   void dispose() { | ||||
|     _cancelSubscriptions(); | ||||
|     CocosWidgetPlatform.instance.dispose(cocosId: cocosId); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										20
									
								
								lib/src/io/windows_cocos_widget_view.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								lib/src/io/windows_cocos_widget_view.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| 
 | ||||
| class WindowsCocosWidgetView extends StatefulWidget { | ||||
|   const WindowsCocosWidgetView({super.key}); | ||||
| 
 | ||||
|   @override | ||||
|   State<WindowsCocosWidgetView> createState() => _WindowsCocosWidgetViewState(); | ||||
| } | ||||
| 
 | ||||
| class _WindowsCocosWidgetViewState extends State<WindowsCocosWidgetView> { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     // TODO: Rex Update windows view | ||||
|     return const MouseRegion( | ||||
|       child: Texture( | ||||
|         textureId: 0, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -4,13 +4,14 @@ version: 0.0.1 | ||||
| homepage: | ||||
| 
 | ||||
| environment: | ||||
|   sdk: ^3.5.4 | ||||
|   sdk: ^3.4.4 | ||||
|   flutter: '>=3.3.0' | ||||
| 
 | ||||
| dependencies: | ||||
|   flutter: | ||||
|     sdk: flutter | ||||
|   plugin_platform_interface: ^2.0.2 | ||||
|   stream_transform: ^2.0.0 | ||||
| 
 | ||||
| dev_dependencies: | ||||
|   flutter_test: | ||||
|  | ||||
| @ -1,27 +0,0 @@ | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
| import 'package:flutter_cocos_view/flutter_cocos_view_method_channel.dart'; | ||||
| 
 | ||||
| void main() { | ||||
|   TestWidgetsFlutterBinding.ensureInitialized(); | ||||
| 
 | ||||
|   MethodChannelFlutterCocosView platform = MethodChannelFlutterCocosView(); | ||||
|   const MethodChannel channel = MethodChannel('flutter_cocos_view'); | ||||
| 
 | ||||
|   setUp(() { | ||||
|     TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( | ||||
|       channel, | ||||
|       (MethodCall methodCall) async { | ||||
|         return '42'; | ||||
|       }, | ||||
|     ); | ||||
|   }); | ||||
| 
 | ||||
|   tearDown(() { | ||||
|     TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null); | ||||
|   }); | ||||
| 
 | ||||
|   test('getPlatformVersion', () async { | ||||
|     expect(await platform.getPlatformVersion(), '42'); | ||||
|   }); | ||||
| } | ||||
| @ -1,29 +0,0 @@ | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
| import 'package:flutter_cocos_view/flutter_cocos_view.dart'; | ||||
| import 'package:flutter_cocos_view/flutter_cocos_view_platform_interface.dart'; | ||||
| import 'package:flutter_cocos_view/flutter_cocos_view_method_channel.dart'; | ||||
| import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | ||||
| 
 | ||||
| class MockFlutterCocosViewPlatform | ||||
|     with MockPlatformInterfaceMixin | ||||
|     implements FlutterCocosViewPlatform { | ||||
| 
 | ||||
|   @override | ||||
|   Future<String?> getPlatformVersion() => Future.value('42'); | ||||
| } | ||||
| 
 | ||||
| void main() { | ||||
|   final FlutterCocosViewPlatform initialPlatform = FlutterCocosViewPlatform.instance; | ||||
| 
 | ||||
|   test('$MethodChannelFlutterCocosView is the default instance', () { | ||||
|     expect(initialPlatform, isInstanceOf<MethodChannelFlutterCocosView>()); | ||||
|   }); | ||||
| 
 | ||||
|   test('getPlatformVersion', () async { | ||||
|     FlutterCocosView flutterCocosViewPlugin = FlutterCocosView(); | ||||
|     MockFlutterCocosViewPlatform fakePlatform = MockFlutterCocosViewPlatform(); | ||||
|     FlutterCocosViewPlatform.instance = fakePlatform; | ||||
| 
 | ||||
|     expect(await flutterCocosViewPlugin.getPlatformVersion(), '42'); | ||||
|   }); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user