[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: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")
);
}
}

View File

@ -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 = () {