mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 23:34:53 +08:00
[flutter] Refactor, widget scafold.
This commit is contained in:
parent
3f11f44c54
commit
656e672ee0
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:spine_flutter/spine_flutter.dart' as spine_flutter;
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
import 'package:spine_flutter/spine_flutter_bindings_generated.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
@ -13,27 +14,54 @@ class MyApp extends StatefulWidget {
|
||||
_MyAppState createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
late int majorVersion;
|
||||
late int minorVersion;
|
||||
class SpinePainter extends CustomPainter {
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
var paint = Paint()
|
||||
..color = Colors.teal
|
||||
..strokeWidth = 5
|
||||
..strokeCap = StrokeCap.round;
|
||||
canvas.drawLine(Offset(0, 0), Offset(size.width, size.height), paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class SpineWidget extends StatelessWidget {
|
||||
String skeletonFile;
|
||||
String atlasFile;
|
||||
late spine_flutter.SpineSkeletonDrawable skeletonDrawable;
|
||||
|
||||
SpineWidget(this.skeletonFile, this.atlasFile) {
|
||||
loadSkeleton();
|
||||
}
|
||||
|
||||
void loadSkeleton() async {
|
||||
final atlas = await spine_flutter.SpineAtlas.fromAsset(rootBundle, atlasFile);
|
||||
final skeletonData = skeletonFile.endsWith(".json") ?
|
||||
spine_flutter.SpineSkeletonData.fromJson(atlas, await rootBundle.loadString(skeletonFile))
|
||||
: spine_flutter.SpineSkeletonData.fromBinary(atlas, await rootBundle.load(skeletonFile));
|
||||
skeletonDrawable = spine_flutter.SpineSkeletonDrawable(atlas, skeletonData);
|
||||
skeletonDrawable.update(0.016);
|
||||
print("Loaded skeleton");
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
painter: SpinePainter(),
|
||||
child: Container()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
majorVersion = spine_flutter.majorVersion();
|
||||
minorVersion = spine_flutter.minorVersion();
|
||||
|
||||
loadSkeleton();
|
||||
}
|
||||
|
||||
void loadSkeleton() async {
|
||||
final atlas = await spine_flutter.loadAtlas(rootBundle, "assets/skeleton.atlas");
|
||||
final skeletonData = spine_flutter.loadSkeletonDataJson(atlas, await rootBundle.loadString("assets/skeleton.json"));
|
||||
// final skeletonDataBinary = spine_flutter.loadSkeletonDataBinary(atlas, await rootBundle.load("assets/spineboy-pro.skel"));
|
||||
final skeletonDrawable = spine_flutter.createSkeletonDrawable(skeletonData);
|
||||
spine_flutter.updateSkeletonDrawable(skeletonDrawable, 0.016);
|
||||
final renderCommands = spine_flutter.renderSkeletonDrawable(skeletonDrawable);
|
||||
print(renderCommands[0].vertices);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -41,24 +69,7 @@ class _MyAppState extends State<MyApp> {
|
||||
const textStyle = TextStyle(fontSize: 25);
|
||||
const spacerSmall = SizedBox(height: 10);
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
const Image(image: AssetImage("assets/spineboy.png")),
|
||||
spacerSmall,
|
||||
Text(
|
||||
'Spine version: $majorVersion.$minorVersion',
|
||||
style: textStyle,
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
home: SpineWidget("assets/skeleton.json", "assets/skeleton.atlas")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,69 +13,97 @@ import 'package:path/path.dart' as Path;
|
||||
int majorVersion() => _bindings.spine_major_version();
|
||||
int minorVersion() => _bindings.spine_minor_version();
|
||||
|
||||
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());
|
||||
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);
|
||||
class SpineAtlas {
|
||||
Pointer<spine_atlas> _atlas;
|
||||
List<Image> _atlasPages;
|
||||
|
||||
SpineAtlas(this._atlas, this._atlasPages);
|
||||
|
||||
static Future<SpineAtlas> fromAsset(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(Image(image: AssetImage(imagePath)));
|
||||
}
|
||||
|
||||
return SpineAtlas(atlas, atlasPages);
|
||||
}
|
||||
}
|
||||
|
||||
class SpineSkeletonData {
|
||||
Pointer<spine_skeleton_data> _skeletonData;
|
||||
|
||||
SpineSkeletonData(this._skeletonData);
|
||||
|
||||
static SpineSkeletonData fromJson(SpineAtlas atlas, String json) {
|
||||
final jsonNative = json.toNativeUtf8();
|
||||
final skeletonData = _bindings.spine_skeleton_data_load_json(atlas._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 SpineSkeletonData(skeletonData);
|
||||
}
|
||||
|
||||
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)));
|
||||
static SpineSkeletonData fromBinary(SpineAtlas 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._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 SpineSkeletonData(skeletonData);
|
||||
}
|
||||
}
|
||||
|
||||
class SpineSkeletonDrawable {
|
||||
SpineAtlas atlas;
|
||||
SpineSkeletonData skeletonData;
|
||||
late Pointer<spine_skeleton_drawable> _drawable;
|
||||
|
||||
SpineSkeletonDrawable(this.atlas, this.skeletonData) {
|
||||
_drawable = _bindings.spine_skeleton_drawable_create(skeletonData._skeletonData);
|
||||
}
|
||||
|
||||
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);
|
||||
void update(double delta) {
|
||||
_bindings.spine_skeleton_drawable_update(_drawable, delta);
|
||||
}
|
||||
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);
|
||||
List<SpineRenderCommand> render() {
|
||||
Pointer<spine_render_command> nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
|
||||
List<SpineRenderCommand> commands = [];
|
||||
while(nativeCmd.address != nullptr.address) {
|
||||
commands.add(SpineRenderCommand(nativeCmd));
|
||||
nativeCmd = nativeCmd.ref.next;
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
return skeletonData;
|
||||
}
|
||||
|
||||
Pointer<spine_skeleton_drawable> createSkeletonDrawable(Pointer<spine_skeleton_data> skeletonData) {
|
||||
return _bindings.spine_skeleton_drawable_create(skeletonData);
|
||||
}
|
||||
|
||||
void updateSkeletonDrawable(Pointer<spine_skeleton_drawable> drawable, double deltaTime) {
|
||||
_bindings.spine_skeleton_drawable_update(drawable, deltaTime);
|
||||
}
|
||||
|
||||
class RenderCommand {
|
||||
class SpineRenderCommand {
|
||||
late Vertices vertices;
|
||||
late int atlasPageIndex;
|
||||
RenderCommand? next;
|
||||
|
||||
RenderCommand(Pointer<spine_render_command> nativeCmd) {
|
||||
SpineRenderCommand(Pointer<spine_render_command> nativeCmd) {
|
||||
atlasPageIndex = nativeCmd.ref.atlasPage;
|
||||
int numVertices = nativeCmd.ref.numVertices;
|
||||
int numIndices = nativeCmd.ref.numIndices;
|
||||
@ -91,17 +119,6 @@ class RenderCommand {
|
||||
}
|
||||
}
|
||||
|
||||
List<RenderCommand> renderSkeletonDrawable(Pointer<spine_skeleton_drawable> drawable) {
|
||||
Pointer<spine_render_command> nativeCmd = _bindings.spine_skeleton_drawable_render(drawable);
|
||||
List<RenderCommand> commands = [];
|
||||
while(nativeCmd.address != nullptr.address) {
|
||||
commands.add(RenderCommand(nativeCmd));
|
||||
nativeCmd = nativeCmd.ref.next;
|
||||
}
|
||||
return commands;
|
||||
|
||||
}
|
||||
|
||||
const String _libName = 'spine_flutter';
|
||||
|
||||
final DynamicLibrary _dylib = () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user