[flutter] Refactor, widget scafold.

This commit is contained in:
Mario Zechner 2022-08-22 16:49:25 +02:00
parent 3f11f44c54
commit 656e672ee0
2 changed files with 125 additions and 97 deletions

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:spine_flutter/spine_flutter.dart' as spine_flutter; import 'package:spine_flutter/spine_flutter.dart' as spine_flutter;
import 'package:flutter/services.dart' show rootBundle; import 'package:flutter/services.dart' show rootBundle;
import 'package:spine_flutter/spine_flutter_bindings_generated.dart';
void main() { void main() {
runApp(const MyApp()); runApp(const MyApp());
@ -13,27 +14,54 @@ class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState(); _MyAppState createState() => _MyAppState();
} }
class _MyAppState extends State<MyApp> { class SpinePainter extends CustomPainter {
late int majorVersion; @override
late int minorVersion; 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 @override
void initState() { void initState() {
super.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 @override
@ -41,24 +69,7 @@ class _MyAppState extends State<MyApp> {
const textStyle = TextStyle(fontSize: 25); const textStyle = TextStyle(fontSize: 25);
const spacerSmall = SizedBox(height: 10); const spacerSmall = SizedBox(height: 10);
return MaterialApp( return MaterialApp(
home: Scaffold( home: SpineWidget("assets/skeleton.json", "assets/skeleton.atlas")
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,
)
],
),
),
),
),
); );
} }
} }

View File

@ -13,69 +13,97 @@ import 'package:path/path.dart' as Path;
int majorVersion() => _bindings.spine_major_version(); int majorVersion() => _bindings.spine_major_version();
int minorVersion() => _bindings.spine_minor_version(); int minorVersion() => _bindings.spine_minor_version();
Future<Pointer<spine_atlas>> loadAtlas(AssetBundle assetBundle, String atlasFileName) async { class SpineAtlas {
final atlasData = await assetBundle.loadString(atlasFileName); Pointer<spine_atlas> _atlas;
final atlasDataNative = atlasData.toNativeUtf8(); List<Image> _atlasPages;
final atlas = _bindings.spine_atlas_load(atlasDataNative.cast());
calloc.free(atlasDataNative); SpineAtlas(this._atlas, this._atlasPages);
if (atlas.ref.error.address != nullptr.address) {
final Pointer<Utf8> error = atlas.ref.error.cast(); static Future<SpineAtlas> fromAsset(AssetBundle assetBundle, String atlasFileName) async {
final message = error.toDartString(); final atlasData = await assetBundle.loadString(atlasFileName);
_bindings.spine_atlas_dispose(atlas); final atlasDataNative = atlasData.toNativeUtf8();
throw Exception("Couldn't load atlas: " + message); 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); static SpineSkeletonData fromBinary(SpineAtlas atlas, ByteData binary) {
List<Image> atlasPages = []; final Pointer<Uint8> binaryNative = malloc.allocate(binary.lengthInBytes);
for (int i = 0; i < atlas.ref.numImagePaths; i++) { binaryNative.asTypedList(binary.lengthInBytes).setAll(0, binary.buffer.asUint8List());
final Pointer<Utf8> atlasPageFile = atlas.ref.imagePaths[i].cast(); final skeletonData = _bindings.spine_skeleton_data_load_binary(atlas._atlas, binaryNative.cast(), binary.lengthInBytes);
final imagePath = Path.join(atlasDir, atlasPageFile.toDartString()); malloc.free(binaryNative);
atlasPages.add(await Image(image: AssetImage(imagePath))); 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; void update(double delta) {
} _bindings.spine_skeleton_drawable_update(_drawable, delta);
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) { List<SpineRenderCommand> render() {
final Pointer<Uint8> binaryNative = malloc.allocate(binary.lengthInBytes); Pointer<spine_render_command> nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
binaryNative.asTypedList(binary.lengthInBytes).setAll(0, binary.buffer.asUint8List()); List<SpineRenderCommand> commands = [];
final skeletonData = _bindings.spine_skeleton_data_load_binary(atlas, binaryNative.cast(), binary.lengthInBytes); while(nativeCmd.address != nullptr.address) {
malloc.free(binaryNative); commands.add(SpineRenderCommand(nativeCmd));
if (skeletonData.ref.error.address != nullptr.address) { nativeCmd = nativeCmd.ref.next;
final Pointer<Utf8> error = skeletonData.ref.error.cast(); }
final message = error.toDartString(); return commands;
_bindings.spine_skeleton_data_dispose(skeletonData);
throw Exception("Couldn't load skeleton data: " + message);
} }
return skeletonData;
} }
Pointer<spine_skeleton_drawable> createSkeletonDrawable(Pointer<spine_skeleton_data> skeletonData) { class SpineRenderCommand {
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 {
late Vertices vertices; late Vertices vertices;
late int atlasPageIndex; late int atlasPageIndex;
RenderCommand? next;
RenderCommand(Pointer<spine_render_command> nativeCmd) { SpineRenderCommand(Pointer<spine_render_command> nativeCmd) {
atlasPageIndex = nativeCmd.ref.atlasPage; atlasPageIndex = nativeCmd.ref.atlasPage;
int numVertices = nativeCmd.ref.numVertices; int numVertices = nativeCmd.ref.numVertices;
int numIndices = nativeCmd.ref.numIndices; 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'; const String _libName = 'spine_flutter';
final DynamicLibrary _dylib = () { final DynamicLibrary _dylib = () {