From 4c744be48ab8378513e6c5c649121a53a56252e2 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 15 Aug 2022 13:22:20 +0200 Subject: [PATCH] [flutter] Skeleton data loading from binary and json. --- spine-flutter/example/lib/main.dart | 9 ++- spine-flutter/lib/spine_flutter.dart | 30 ++++++++- .../lib/spine_flutter_bindings_generated.dart | 63 +++++++++++++++++++ spine-flutter/src/spine_flutter.cpp | 29 +++++++++ spine-flutter/src/spine_flutter.h | 9 +++ 5 files changed, 137 insertions(+), 3 deletions(-) diff --git a/spine-flutter/example/lib/main.dart b/spine-flutter/example/lib/main.dart index 261cc5e03..22c93c6c8 100644 --- a/spine-flutter/example/lib/main.dart +++ b/spine-flutter/example/lib/main.dart @@ -22,7 +22,14 @@ class _MyAppState extends State { super.initState(); majorVersion = spine_flutter.majorVersion(); minorVersion = spine_flutter.minorVersion(); - spine_flutter.loadAtlas(rootBundle, "assets/spineboy.atlas"); + + loadSkeleton(); + } + + void loadSkeleton() async { + final atlas = await spine_flutter.loadAtlas(rootBundle, "assets/spineboy.atlas"); + final skeletonData = spine_flutter.loadSkeletonDataJson(atlas, await rootBundle.loadString("assets/spineboy-pro.json")); + final skeletonDataBinary = spine_flutter.loadSkeletonDataBinary(atlas, await rootBundle.load("assets/spineboy-pro.skel")); } @override diff --git a/spine-flutter/lib/spine_flutter.dart b/spine-flutter/lib/spine_flutter.dart index 5755afa04..4205c3439 100644 --- a/spine-flutter/lib/spine_flutter.dart +++ b/spine-flutter/lib/spine_flutter.dart @@ -11,7 +11,7 @@ import 'package:path/path.dart' as Path; int majorVersion() => _bindings.spine_major_version(); int minorVersion() => _bindings.spine_minor_version(); -void loadAtlas(AssetBundle assetBundle, String atlasFileName) async { +Future> loadAtlas(AssetBundle assetBundle, String atlasFileName) async { final atlasData = await assetBundle.loadString(atlasFileName); final atlasDataNative = atlasData.toNativeUtf8(); final atlas = _bindings.spine_atlas_load(atlasDataNative.cast()); @@ -31,7 +31,33 @@ void loadAtlas(AssetBundle assetBundle, String atlasFileName) async { atlasPages.add(await Image(image: AssetImage(imagePath))); } - _bindings.spine_atlas_dispose(atlas); + return atlas; +} + +Pointer loadSkeletonDataJson(Pointer atlas, String json) { + final jsonNative = json.toNativeUtf8(); + final skeletonData = _bindings.spine_skeleton_data_load_json(atlas, jsonNative.cast()); + if (skeletonData.ref.error.address != nullptr.address) { + final Pointer error = skeletonData.ref.error.cast(); + final message = error.toDartString(); + _bindings.spine_skeleton_data_dispose(skeletonData); + throw Exception("Couldn't load skeleton data: " + message); + } + return skeletonData; +} + +Pointer loadSkeletonDataBinary(Pointer atlas, ByteData binary) { + final Pointer binaryNative = malloc.allocate(binary.lengthInBytes); + binaryNative.asTypedList(binary.lengthInBytes).setAll(0, binary.buffer.asUint8List()); + final skeletonData = _bindings.spine_skeleton_data_load_binary(atlas, binaryNative.cast(), binary.lengthInBytes); + malloc.free(binaryNative); + if (skeletonData.ref.error.address != nullptr.address) { + final Pointer error = skeletonData.ref.error.cast(); + final message = error.toDartString(); + _bindings.spine_skeleton_data_dispose(skeletonData); + throw Exception("Couldn't load skeleton data: " + message); + } + return skeletonData; } const String _libName = 'spine_flutter'; diff --git a/spine-flutter/lib/spine_flutter_bindings_generated.dart b/spine-flutter/lib/spine_flutter_bindings_generated.dart index 1440521e6..63946fb60 100644 --- a/spine-flutter/lib/spine_flutter_bindings_generated.dart +++ b/spine-flutter/lib/spine_flutter_bindings_generated.dart @@ -72,6 +72,63 @@ class SpineFlutterBindings { 'spine_atlas_dispose'); late final _spine_atlas_dispose = _spine_atlas_disposePtr .asFunction)>(); + + ffi.Pointer spine_skeleton_data_load_json( + ffi.Pointer atlas, + ffi.Pointer skeletonData, + ) { + return _spine_skeleton_data_load_json( + atlas, + skeletonData, + ); + } + + late final _spine_skeleton_data_load_jsonPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer)>>('spine_skeleton_data_load_json'); + late final _spine_skeleton_data_load_json = + _spine_skeleton_data_load_jsonPtr.asFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(); + + ffi.Pointer spine_skeleton_data_load_binary( + ffi.Pointer atlas, + ffi.Pointer skeletonData, + int length, + ) { + return _spine_skeleton_data_load_binary( + atlas, + skeletonData, + length, + ); + } + + late final _spine_skeleton_data_load_binaryPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Int32)>>('spine_skeleton_data_load_binary'); + late final _spine_skeleton_data_load_binary = + _spine_skeleton_data_load_binaryPtr.asFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer, int)>(); + + void spine_skeleton_data_dispose( + ffi.Pointer skeletonData, + ) { + return _spine_skeleton_data_dispose( + skeletonData, + ); + } + + late final _spine_skeleton_data_disposePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer)>>( + 'spine_skeleton_data_dispose'); + late final _spine_skeleton_data_dispose = _spine_skeleton_data_disposePtr + .asFunction)>(); } class spine_atlas extends ffi.Struct { @@ -84,3 +141,9 @@ class spine_atlas extends ffi.Struct { external ffi.Pointer error; } + +class spine_skeleton_data extends ffi.Struct { + external ffi.Pointer skeletonData; + + external ffi.Pointer error; +} diff --git a/spine-flutter/src/spine_flutter.cpp b/spine-flutter/src/spine_flutter.cpp index 82c462bff..f031a4191 100644 --- a/spine-flutter/src/spine_flutter.cpp +++ b/spine-flutter/src/spine_flutter.cpp @@ -35,6 +35,35 @@ FFI_PLUGIN_EXPORT void spine_atlas_dispose(spine_atlas *atlas) { SpineExtension::free(atlas, __FILE__, __LINE__); } +FFI_PLUGIN_EXPORT spine_skeleton_data *spine_skeleton_data_load_json(spine_atlas *atlas, const char *skeletonData) { + SkeletonJson json((Atlas*)atlas->atlas); + SkeletonData *data = json.readSkeletonData(skeletonData); + spine_skeleton_data *result = SpineExtension::calloc(1, __FILE__, __LINE__); + result->skeletonData = data; + if (!json.getError().isEmpty()) { + result->error = strdup(json.getError().buffer()); + } + return result; +} + +FFI_PLUGIN_EXPORT spine_skeleton_data* spine_skeleton_data_load_binary(spine_atlas *atlas, const unsigned char *skeletonData, int32_t length) { + SkeletonBinary binary((Atlas*)atlas->atlas); + SkeletonData *data = binary.readSkeletonData(skeletonData, length); + spine_skeleton_data *result = SpineExtension::calloc(1, __FILE__, __LINE__); + result->skeletonData = data; + if (!binary.getError().isEmpty()) { + result->error = strdup(binary.getError().buffer()); + } + return result; +} + +FFI_PLUGIN_EXPORT void spine_skeleton_data_dispose(spine_skeleton_data *skeletonData) { + if (!skeletonData) return; + if (skeletonData->skeletonData) delete (SkeletonData*)skeletonData->skeletonData; + if (skeletonData->error) free(skeletonData->error); + SpineExtension::free(skeletonData, __FILE__, __LINE__); +} + spine::SpineExtension *spine::getDefaultExtension() { return new spine::DefaultSpineExtension(); } diff --git a/spine-flutter/src/spine_flutter.h b/spine-flutter/src/spine_flutter.h index 5bf89e5b0..030a668a9 100644 --- a/spine-flutter/src/spine_flutter.h +++ b/spine-flutter/src/spine_flutter.h @@ -36,3 +36,12 @@ typedef struct spine_atlas { FFI_PLUGIN_EXPORT spine_atlas* spine_atlas_load(const char *atlasData); FFI_PLUGIN_EXPORT void spine_atlas_dispose(spine_atlas *atlas); +typedef struct spine_skeleton_data { + void *skeletonData; + char *error; +} spine_skeleton_data; + +FFI_PLUGIN_EXPORT spine_skeleton_data* spine_skeleton_data_load_json(spine_atlas *atlas, const char *skeletonData); +FFI_PLUGIN_EXPORT spine_skeleton_data* spine_skeleton_data_load_binary(spine_atlas *atlas, const unsigned char *skeletonData, int32_t length); +FFI_PLUGIN_EXPORT void spine_skeleton_data_dispose(spine_skeleton_data *skeletonData); +