mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 15:24:55 +08:00
[flutter] Atas loading POC including async image load.
This commit is contained in:
parent
54aa6a0dc6
commit
75a656ebfc
@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:spine_flutter/spine_flutter.dart' as spine_flutter;
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
@ -21,8 +20,9 @@ class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
majorVersion = spine_flutter.spine_major_version();
|
||||
minorVersion = spine_flutter.spine_minor_version();
|
||||
majorVersion = spine_flutter.majorVersion();
|
||||
minorVersion = spine_flutter.minorVersion();
|
||||
spine_flutter.loadAtlas(rootBundle, "assets/spineboy.atlas");
|
||||
}
|
||||
|
||||
@override
|
||||
@ -31,20 +31,12 @@ class _MyAppState extends State<MyApp> {
|
||||
const spacerSmall = SizedBox(height: 10);
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Native Packages'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'This calls a native function through FFI that is shipped as source in the package. '
|
||||
'The native code is built as part of the Flutter Runner build.',
|
||||
style: textStyle,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const Image(image: AssetImage("assets/spineboy.png")),
|
||||
spacerSmall,
|
||||
Text(
|
||||
'Spine version: $majorVersion.$minorVersion',
|
||||
|
||||
@ -57,6 +57,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
||||
@ -1,17 +1,41 @@
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'spine_flutter_bindings_generated.dart';
|
||||
import 'package:path/path.dart' as Path;
|
||||
|
||||
int spine_major_version() => _bindings.spine_major_version();
|
||||
int spine_minor_version() => _bindings.spine_minor_version();
|
||||
int majorVersion() => _bindings.spine_major_version();
|
||||
int minorVersion() => _bindings.spine_minor_version();
|
||||
|
||||
void loadAtlas(AssetBundle assetBundle, String atlasFileName) async {
|
||||
final atlasData = await assetBundle.loadString(atlasFileName);
|
||||
final atlasDataNative = atlasData.toNativeUtf8();
|
||||
final atlas = _bindings.spine_atlas_load(atlasDataNative.cast());
|
||||
calloc.free(atlasDataNative);
|
||||
if (atlas.ref.error.address != nullptr.address) {
|
||||
final Pointer<Utf8> error = atlas.ref.error.cast();
|
||||
final message = error.toDartString();
|
||||
_bindings.spine_atlas_dispose(atlas);
|
||||
throw Exception("Couldn't load atlas: " + message);
|
||||
}
|
||||
|
||||
final atlasDir = Path.dirname(atlasFileName);
|
||||
List<Image> atlasPages = [];
|
||||
for (int i = 0; i < atlas.ref.numImagePaths; i++) {
|
||||
final Pointer<Utf8> atlasPageFile = atlas.ref.imagePaths[i].cast();
|
||||
final imagePath = Path.join(atlasDir, atlasPageFile.toDartString());
|
||||
atlasPages.add(await Image(image: AssetImage(imagePath)));
|
||||
}
|
||||
|
||||
_bindings.spine_atlas_dispose(atlas);
|
||||
}
|
||||
|
||||
const String _libName = 'spine_flutter';
|
||||
|
||||
/// The dynamic library in which the symbols for [SpineFlutterBindings] can be found.
|
||||
final DynamicLibrary _dylib = () {
|
||||
if (Platform.isMacOS || Platform.isIOS) {
|
||||
return DynamicLibrary.open('$_libName.framework/$_libName');
|
||||
@ -25,5 +49,4 @@ final DynamicLibrary _dylib = () {
|
||||
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
|
||||
}();
|
||||
|
||||
/// The bindings to the native functions in [_dylib].
|
||||
final SpineFlutterBindings _bindings = SpineFlutterBindings(_dylib);
|
||||
@ -43,4 +43,44 @@ class SpineFlutterBindings {
|
||||
_lookup<ffi.NativeFunction<ffi.Int32 Function()>>('spine_minor_version');
|
||||
late final _spine_minor_version =
|
||||
_spine_minor_versionPtr.asFunction<int Function()>();
|
||||
|
||||
ffi.Pointer<spine_atlas> spine_atlas_load(
|
||||
ffi.Pointer<ffi.Int8> atlasData,
|
||||
) {
|
||||
return _spine_atlas_load(
|
||||
atlasData,
|
||||
);
|
||||
}
|
||||
|
||||
late final _spine_atlas_loadPtr = _lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Pointer<spine_atlas> Function(
|
||||
ffi.Pointer<ffi.Int8>)>>('spine_atlas_load');
|
||||
late final _spine_atlas_load = _spine_atlas_loadPtr
|
||||
.asFunction<ffi.Pointer<spine_atlas> Function(ffi.Pointer<ffi.Int8>)>();
|
||||
|
||||
void spine_atlas_dispose(
|
||||
ffi.Pointer<spine_atlas> atlas,
|
||||
) {
|
||||
return _spine_atlas_dispose(
|
||||
atlas,
|
||||
);
|
||||
}
|
||||
|
||||
late final _spine_atlas_disposePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<spine_atlas>)>>(
|
||||
'spine_atlas_dispose');
|
||||
late final _spine_atlas_dispose = _spine_atlas_disposePtr
|
||||
.asFunction<void Function(ffi.Pointer<spine_atlas>)>();
|
||||
}
|
||||
|
||||
class spine_atlas extends ffi.Struct {
|
||||
external ffi.Pointer<ffi.Void> atlas;
|
||||
|
||||
external ffi.Pointer<ffi.Pointer<ffi.Int8>> imagePaths;
|
||||
|
||||
@ffi.Int32()
|
||||
external int numImagePaths;
|
||||
|
||||
external ffi.Pointer<ffi.Int8> error;
|
||||
}
|
||||
|
||||
@ -11,13 +11,14 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^2.0.2
|
||||
ffi: ^1.1.2
|
||||
|
||||
dev_dependencies:
|
||||
ffi: ^1.1.2
|
||||
ffigen: ^4.1.2
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
ffi: ^1.1.2
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
@ -2,14 +2,39 @@
|
||||
#include <spine/spine.h>
|
||||
#include <spine/Version.h>
|
||||
|
||||
int32_t spine_major_version() {
|
||||
using namespace spine;
|
||||
|
||||
FFI_PLUGIN_EXPORT int32_t spine_major_version() {
|
||||
return SPINE_MAJOR_VERSION;
|
||||
}
|
||||
|
||||
int32_t spine_minor_version() {
|
||||
FFI_PLUGIN_EXPORT int32_t spine_minor_version() {
|
||||
return SPINE_MINOR_VERSION;
|
||||
}
|
||||
|
||||
FFI_PLUGIN_EXPORT spine_atlas* spine_atlas_load(const char *atlasData) {
|
||||
int length = strlen(atlasData);
|
||||
auto atlas = new Atlas(atlasData, length, "", (TextureLoader*)nullptr, false);
|
||||
spine_atlas *result = SpineExtension::calloc<spine_atlas>(1, __FILE__, __LINE__);
|
||||
result->atlas = atlas;
|
||||
result->numImagePaths = atlas->getPages().size();
|
||||
result->imagePaths = SpineExtension::calloc<char *>(result->numImagePaths, __FILE__, __LINE__);
|
||||
for (int i = 0; i < result->numImagePaths; i++) {
|
||||
result->imagePaths[i] = strdup(atlas->getPages()[i]->texturePath.buffer());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FFI_PLUGIN_EXPORT void spine_atlas_dispose(spine_atlas *atlas) {
|
||||
if (!atlas) return;
|
||||
if (atlas->atlas) delete (Atlas*)atlas->atlas;
|
||||
if (atlas->error) free(atlas->error);
|
||||
for (int i = 0; i < atlas->numImagePaths; i++) {
|
||||
free(atlas->imagePaths[i]);
|
||||
}
|
||||
SpineExtension::free(atlas, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
spine::SpineExtension *spine::getDefaultExtension() {
|
||||
return new spine::DefaultSpineExtension();
|
||||
}
|
||||
|
||||
@ -9,13 +9,30 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if _WIN32
|
||||
#define FFI_PLUGIN_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define FFI_PLUGIN_EXPORT extern "C"
|
||||
#endif
|
||||
#else
|
||||
#if _WIN32
|
||||
#define FFI_PLUGIN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define FFI_PLUGIN_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
FFI_PLUGIN_EXPORT int32_t spine_major_version();
|
||||
FFI_PLUGIN_EXPORT int32_t spine_minor_version();
|
||||
|
||||
typedef struct spine_atlas {
|
||||
void *atlas;
|
||||
char **imagePaths;
|
||||
int32_t numImagePaths;
|
||||
char *error;
|
||||
} spine_atlas;
|
||||
|
||||
FFI_PLUGIN_EXPORT spine_atlas* spine_atlas_load(const char *atlasData);
|
||||
FFI_PLUGIN_EXPORT void spine_atlas_dispose(spine_atlas *atlas);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user