[flutter] Skeleton data loading from binary and json.

This commit is contained in:
Mario Zechner 2022-08-15 13:22:20 +02:00
parent 75a656ebfc
commit 4c744be48a
5 changed files with 137 additions and 3 deletions

View File

@ -22,7 +22,14 @@ class _MyAppState extends State<MyApp> {
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

View File

@ -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<Pointer<spine_atlas>> 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<spine_skeleton_data> loadSkeletonDataJson(Pointer<spine_atlas> 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<Utf8> 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<spine_skeleton_data> loadSkeletonDataBinary(Pointer<spine_atlas> atlas, ByteData binary) {
final Pointer<Uint8> 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<Utf8> 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';

View File

@ -72,6 +72,63 @@ class SpineFlutterBindings {
'spine_atlas_dispose');
late final _spine_atlas_dispose = _spine_atlas_disposePtr
.asFunction<void Function(ffi.Pointer<spine_atlas>)>();
ffi.Pointer<spine_skeleton_data> spine_skeleton_data_load_json(
ffi.Pointer<spine_atlas> atlas,
ffi.Pointer<ffi.Int8> skeletonData,
) {
return _spine_skeleton_data_load_json(
atlas,
skeletonData,
);
}
late final _spine_skeleton_data_load_jsonPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<spine_skeleton_data> Function(ffi.Pointer<spine_atlas>,
ffi.Pointer<ffi.Int8>)>>('spine_skeleton_data_load_json');
late final _spine_skeleton_data_load_json =
_spine_skeleton_data_load_jsonPtr.asFunction<
ffi.Pointer<spine_skeleton_data> Function(
ffi.Pointer<spine_atlas>, ffi.Pointer<ffi.Int8>)>();
ffi.Pointer<spine_skeleton_data> spine_skeleton_data_load_binary(
ffi.Pointer<spine_atlas> atlas,
ffi.Pointer<ffi.Uint8> skeletonData,
int length,
) {
return _spine_skeleton_data_load_binary(
atlas,
skeletonData,
length,
);
}
late final _spine_skeleton_data_load_binaryPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<spine_skeleton_data> Function(
ffi.Pointer<spine_atlas>,
ffi.Pointer<ffi.Uint8>,
ffi.Int32)>>('spine_skeleton_data_load_binary');
late final _spine_skeleton_data_load_binary =
_spine_skeleton_data_load_binaryPtr.asFunction<
ffi.Pointer<spine_skeleton_data> Function(
ffi.Pointer<spine_atlas>, ffi.Pointer<ffi.Uint8>, int)>();
void spine_skeleton_data_dispose(
ffi.Pointer<spine_skeleton_data> skeletonData,
) {
return _spine_skeleton_data_dispose(
skeletonData,
);
}
late final _spine_skeleton_data_disposePtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<spine_skeleton_data>)>>(
'spine_skeleton_data_dispose');
late final _spine_skeleton_data_dispose = _spine_skeleton_data_disposePtr
.asFunction<void Function(ffi.Pointer<spine_skeleton_data>)>();
}
class spine_atlas extends ffi.Struct {
@ -84,3 +141,9 @@ class spine_atlas extends ffi.Struct {
external ffi.Pointer<ffi.Int8> error;
}
class spine_skeleton_data extends ffi.Struct {
external ffi.Pointer<ffi.Void> skeletonData;
external ffi.Pointer<ffi.Int8> error;
}

View File

@ -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<spine_skeleton_data>(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<spine_skeleton_data>(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();
}

View File

@ -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);