mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-25 11:11:24 +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: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
|
@override
|
||||||
void initState() {
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||||
super.initState();
|
return false;
|
||||||
majorVersion = spine_flutter.majorVersion();
|
}
|
||||||
minorVersion = spine_flutter.minorVersion();
|
}
|
||||||
|
|
||||||
|
class SpineWidget extends StatelessWidget {
|
||||||
|
String skeletonFile;
|
||||||
|
String atlasFile;
|
||||||
|
late spine_flutter.SpineSkeletonDrawable skeletonDrawable;
|
||||||
|
|
||||||
|
SpineWidget(this.skeletonFile, this.atlasFile) {
|
||||||
loadSkeleton();
|
loadSkeleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadSkeleton() async {
|
void loadSkeleton() async {
|
||||||
final atlas = await spine_flutter.loadAtlas(rootBundle, "assets/skeleton.atlas");
|
final atlas = await spine_flutter.SpineAtlas.fromAsset(rootBundle, atlasFile);
|
||||||
final skeletonData = spine_flutter.loadSkeletonDataJson(atlas, await rootBundle.loadString("assets/skeleton.json"));
|
final skeletonData = skeletonFile.endsWith(".json") ?
|
||||||
// final skeletonDataBinary = spine_flutter.loadSkeletonDataBinary(atlas, await rootBundle.load("assets/spineboy-pro.skel"));
|
spine_flutter.SpineSkeletonData.fromJson(atlas, await rootBundle.loadString(skeletonFile))
|
||||||
final skeletonDrawable = spine_flutter.createSkeletonDrawable(skeletonData);
|
: spine_flutter.SpineSkeletonData.fromBinary(atlas, await rootBundle.load(skeletonFile));
|
||||||
spine_flutter.updateSkeletonDrawable(skeletonDrawable, 0.016);
|
skeletonDrawable = spine_flutter.SpineSkeletonDrawable(atlas, skeletonData);
|
||||||
final renderCommands = spine_flutter.renderSkeletonDrawable(skeletonDrawable);
|
skeletonDrawable.update(0.016);
|
||||||
print(renderCommands[0].vertices);
|
print("Loaded skeleton");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CustomPaint(
|
||||||
|
painter: SpinePainter(),
|
||||||
|
child: Container()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyAppState extends State<MyApp> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@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,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 = () {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user