diff --git a/spine-flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/spine-flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
new file mode 100644
index 000000000..e793a000d
--- /dev/null
+++ b/spine-flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/spine-flutter/example/lib/main.dart b/spine-flutter/example/lib/main.dart
index 2cfc3c23d..b7488fe2f 100644
--- a/spine-flutter/example/lib/main.dart
+++ b/spine-flutter/example/lib/main.dart
@@ -6,6 +6,7 @@ import 'pause_play_animation.dart';
import 'skins.dart';
import 'dress_up.dart';
import 'ik_following.dart';
+import 'package:spine_flutter/spine_flutter.dart';
class ExampleSelector extends StatelessWidget {
const ExampleSelector({super.key});
@@ -98,7 +99,9 @@ class ExampleSelector extends StatelessWidget {
}
}
-void main() {
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+ await initSpineFlutter();
runApp(const MaterialApp(
title: "Spine Examples",
home: ExampleSelector()
diff --git a/spine-flutter/example/pubspec.lock b/spine-flutter/example/pubspec.lock
index 79022a62c..0a6e03b6c 100644
--- a/spine-flutter/example/pubspec.lock
+++ b/spine-flutter/example/pubspec.lock
@@ -95,6 +95,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
+ inject_js:
+ dependency: transitive
+ description:
+ name: inject_js
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.6.5"
lints:
dependency: transitive
description:
@@ -212,6 +226,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
+ web_ffi:
+ dependency: transitive
+ description:
+ name: web_ffi
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.7.2"
sdks:
dart: ">=2.17.6 <3.0.0"
flutter: ">=2.11.0"
diff --git a/spine-flutter/example/pubspec.yaml b/spine-flutter/example/pubspec.yaml
index d170c5610..d3ef97567 100644
--- a/spine-flutter/example/pubspec.yaml
+++ b/spine-flutter/example/pubspec.yaml
@@ -45,8 +45,6 @@ dependencies:
raw_image_provider: ^0.2.0
dev_dependencies:
- flutter_test:
- sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
diff --git a/spine-flutter/example/web/favicon.png b/spine-flutter/example/web/favicon.png
new file mode 100644
index 000000000..8aaa46ac1
Binary files /dev/null and b/spine-flutter/example/web/favicon.png differ
diff --git a/spine-flutter/example/web/icons/Icon-192.png b/spine-flutter/example/web/icons/Icon-192.png
new file mode 100644
index 000000000..b749bfef0
Binary files /dev/null and b/spine-flutter/example/web/icons/Icon-192.png differ
diff --git a/spine-flutter/example/web/icons/Icon-512.png b/spine-flutter/example/web/icons/Icon-512.png
new file mode 100644
index 000000000..88cfd48df
Binary files /dev/null and b/spine-flutter/example/web/icons/Icon-512.png differ
diff --git a/spine-flutter/example/web/icons/Icon-maskable-192.png b/spine-flutter/example/web/icons/Icon-maskable-192.png
new file mode 100644
index 000000000..eb9b4d76e
Binary files /dev/null and b/spine-flutter/example/web/icons/Icon-maskable-192.png differ
diff --git a/spine-flutter/example/web/icons/Icon-maskable-512.png b/spine-flutter/example/web/icons/Icon-maskable-512.png
new file mode 100644
index 000000000..d69c56691
Binary files /dev/null and b/spine-flutter/example/web/icons/Icon-maskable-512.png differ
diff --git a/spine-flutter/example/web/index.html b/spine-flutter/example/web/index.html
new file mode 100644
index 000000000..41b3bc336
--- /dev/null
+++ b/spine-flutter/example/web/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ example
+
+
+
+
+
+
+
+
+
+
diff --git a/spine-flutter/example/web/manifest.json b/spine-flutter/example/web/manifest.json
new file mode 100644
index 000000000..096edf8fe
--- /dev/null
+++ b/spine-flutter/example/web/manifest.json
@@ -0,0 +1,35 @@
+{
+ "name": "example",
+ "short_name": "example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-maskable-192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "icons/Icon-maskable-512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ]
+}
diff --git a/spine-flutter/lib/ffi_proxy.dart b/spine-flutter/lib/ffi_proxy.dart
new file mode 100644
index 000000000..5ff8e34e5
--- /dev/null
+++ b/spine-flutter/lib/ffi_proxy.dart
@@ -0,0 +1 @@
+export 'dart:ffi' if (dart.library.html) 'package:web_ffi/web_ffi.dart';
\ No newline at end of file
diff --git a/spine-flutter/lib/ffi_utf8.dart b/spine-flutter/lib/ffi_utf8.dart
new file mode 100644
index 000000000..2af6b78dd
--- /dev/null
+++ b/spine-flutter/lib/ffi_utf8.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'ffi_proxy.dart';
+import 'dart:typed_data';
+
+/// The contents of a native zero-terminated array of UTF-8 code units.
+///
+/// The Utf8 type itself has no functionality, it's only intended to be used
+/// through a `Pointer` representing the entire array. This pointer is
+/// the equivalent of a char pointer (`const char*`) in C code.
+class Utf8 extends Opaque {}
+
+/// Extension method for converting a`Pointer` to a [String].
+extension Utf8Pointer on Pointer {
+ /// The number of UTF-8 code units in this zero-terminated UTF-8 string.
+ ///
+ /// The UTF-8 code units of the strings are the non-zero code units up to the
+ /// first zero code unit.
+ int get length {
+ _ensureNotNullptr('length');
+ final codeUnits = cast();
+ return _length(codeUnits);
+ }
+
+ /// Converts this UTF-8 encoded string to a Dart string.
+ ///
+ /// Decodes the UTF-8 code units of this zero-terminated byte array as
+ /// Unicode code points and creates a Dart string containing those code
+ /// points.
+ ///
+ /// If [length] is provided, zero-termination is ignored and the result can
+ /// contain NUL characters.
+ ///
+ /// If [length] is not provided, the returned string is the string up til
+ /// but not including the first NUL character.
+ String toDartString({int? length}) {
+ _ensureNotNullptr('toDartString');
+ final codeUnits = cast();
+ if (length != null) {
+ RangeError.checkNotNegative(length, 'length');
+ } else {
+ length = _length(codeUnits);
+ }
+ return utf8.decode(codeUnits.asTypedList(length));
+ }
+
+ static int _length(Pointer codeUnits) {
+ var length = 0;
+ while (codeUnits[length] != 0) {
+ length++;
+ }
+ return length;
+ }
+
+ void _ensureNotNullptr(String operation) {
+ if (this == nullptr) {
+ throw UnsupportedError(
+ "Operation '$operation' not allowed on a 'nullptr'.");
+ }
+ }
+}
+
+/// Extension method for converting a [String] to a `Pointer`.
+extension StringUtf8Pointer on String {
+ /// Creates a zero-terminated [Utf8] code-unit array from this String.
+ ///
+ /// If this [String] contains NUL characters, converting it back to a string
+ /// using [Utf8Pointer.toDartString] will truncate the result if a length is
+ /// not passed.
+ ///
+ /// Unpaired surrogate code points in this [String] will be encoded as
+ /// replacement characters (U+FFFD, encoded as the bytes 0xEF 0xBF 0xBD) in
+ /// the UTF-8 encoded result. See [Utf8Encoder] for details on encoding.
+ ///
+ /// Returns an [allocator]-allocated pointer to the result.
+ Pointer toNativeUtf8(Allocator allocator) {
+ final units = utf8.encode(this);
+ final Pointer result = allocator(units.length + 1);
+ final Uint8List nativeString = result.asTypedList(units.length + 1);
+ nativeString.setAll(0, units);
+ nativeString[units.length] = 0;
+ return result.cast();
+ }
+}
\ No newline at end of file
diff --git a/spine-flutter/lib/init.dart b/spine-flutter/lib/init.dart
new file mode 100644
index 000000000..93fc9fa7a
--- /dev/null
+++ b/spine-flutter/lib/init.dart
@@ -0,0 +1,28 @@
+import 'dart:io';
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+const String _libName = 'spine_flutter';
+final DynamicLibrary _dylib = () {
+ if (Platform.isMacOS || Platform.isIOS) {
+ return DynamicLibrary.open('$_libName.framework/$_libName');
+ }
+ if (Platform.isAndroid || Platform.isLinux) {
+ return DynamicLibrary.open('lib$_libName.so');
+ }
+ if (Platform.isWindows) {
+ return DynamicLibrary.open('$_libName.dll');
+ }
+ throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
+}();
+
+class SpineFlutterFFI {
+ DynamicLibrary dylib;
+ Allocator allocator;
+
+ SpineFlutterFFI(this.dylib, this.allocator);
+}
+
+Future initSpineFlutterFFI() async {
+ return SpineFlutterFFI(_dylib, malloc);
+}
diff --git a/spine-flutter/lib/init_web.dart b/spine-flutter/lib/init_web.dart
new file mode 100644
index 000000000..3a38bf494
--- /dev/null
+++ b/spine-flutter/lib/init_web.dart
@@ -0,0 +1,77 @@
+import 'package:flutter/services.dart';
+import 'package:inject_js/inject_js.dart' as js;
+import 'package:spine_flutter/ffi_utf8.dart';
+import 'package:web_ffi/web_ffi.dart';
+import 'package:web_ffi/web_ffi_modules.dart';
+import 'spine_flutter_bindings_generated.dart';
+
+const String _basePath = 'packages/spine_flutter/assets';
+Module? _module;
+
+class SpineFlutterFFI {
+ final DynamicLibrary dylib;
+ final Allocator allocator;
+
+ SpineFlutterFFI(this.dylib, this.allocator);
+}
+
+Future initSpineFlutterFFI() async {
+ if (_module == null) {
+ Memory.init();
+
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+ registerOpaqueType();
+
+ await js.importLibrary('$_basePath/libspine_flutter.js');
+ String path = 'libspine_flutter.wasm';
+ Uint8List wasmBinaries = (await rootBundle.load(path)).buffer.asUint8List();
+ _module = await EmscriptenModule.compile(wasmBinaries, 'libspine_flutter');
+ }
+ Module? m = _module;
+ if (m != null) {
+ final dylib = DynamicLibrary.fromModule(m);
+ return SpineFlutterFFI(dylib, dylib.boundMemory);
+ } else {
+ throw Exception("Couldn't load libspine-flutter.js/.wasm");
+ }
+}
\ No newline at end of file
diff --git a/spine-flutter/lib/spine_flutter.dart b/spine-flutter/lib/spine_flutter.dart
index a3f317943..3293b5d46 100644
--- a/spine-flutter/lib/spine_flutter.dart
+++ b/spine-flutter/lib/spine_flutter.dart
@@ -1,18 +1,30 @@
import 'dart:convert' as convert;
-import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';
-import 'package:ffi/ffi.dart';
import 'package:flutter/rendering.dart' as rendering;
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
import 'spine_flutter_bindings_generated.dart';
+import 'ffi_proxy.dart';
+import 'ffi_utf8.dart';
export 'spine_widget.dart';
+import 'init.dart' if (dart.library.html) 'init_web.dart';
+import 'package:flutter/foundation.dart' show kIsWeb;
+
+late SpineFlutterBindings _bindings;
+late Allocator _allocator;
+
+Future initSpineFlutter() async {
+ final ffi = await initSpineFlutterFFI();
+ _bindings = SpineFlutterBindings(ffi.dylib);
+ _allocator = ffi.allocator;
+ return;
+}
int majorVersion() => _bindings.spine_major_version();
@@ -46,7 +58,7 @@ class Vector2 {
}
class Atlas {
- final Pointer _atlas;
+ final spine_atlas _atlas;
final List atlasPages;
final List atlasPagePaints;
bool _disposed;
@@ -56,11 +68,11 @@ class Atlas {
static Future _load(String atlasFileName, Future Function(String name) loadFile) async {
final atlasBytes = await loadFile(atlasFileName);
final atlasData = convert.utf8.decode(atlasBytes);
- final atlasDataNative = atlasData.toNativeUtf8();
+ final atlasDataNative = atlasData.toNativeUtf8(_allocator);
final atlas = _bindings.spine_atlas_load(atlasDataNative.cast());
- malloc.free(atlasDataNative);
- if (atlas.ref.error.address != nullptr.address) {
- final Pointer error = atlas.ref.error.cast();
+ _allocator.free(atlasDataNative);
+ if (_bindings.spine_atlas_get_error(atlas).address != nullptr.address) {
+ final Pointer error = _bindings.spine_atlas_get_error(atlas).cast();
final message = error.toDartString();
_bindings.spine_atlas_dispose(atlas);
throw Exception("Couldn't load atlas: $message");
@@ -69,8 +81,9 @@ class Atlas {
final atlasDir = path.dirname(atlasFileName);
List atlasPages = [];
List atlasPagePaints = [];
- for (int i = 0; i < atlas.ref.numImagePaths; i++) {
- final Pointer atlasPageFile = atlas.ref.imagePaths[i].cast();
+ final numImagePaths = _bindings.spine_atlas_get_num_image_paths(atlas);
+ for (int i = 0; i < numImagePaths; i++) {
+ final Pointer atlasPageFile = _bindings.spine_atlas_get_image_path(atlas, i).cast();
final imagePath = path.join(atlasDir, atlasPageFile.toDartString());
var imageData = await loadFile(imagePath);
final Codec codec = await instantiateImageCodec(imageData);
@@ -117,30 +130,34 @@ class SkeletonData {
SkeletonData._(this._data) : _disposed = false;
static SkeletonData fromJson(Atlas atlas, String json) {
- final jsonNative = json.toNativeUtf8();
+ final jsonNative = json.toNativeUtf8(_allocator);
final result = _bindings.spine_skeleton_data_load_json(atlas._atlas, jsonNative.cast());
- malloc.free(jsonNative);
- if (result.error.address != nullptr.address) {
- final Pointer error = result.error.cast();
+ _allocator.free(jsonNative);
+ if (_bindings.spine_skeleton_data_result_get_error(result).address != nullptr.address) {
+ final Pointer error = _bindings.spine_skeleton_data_result_get_error(result).cast();
final message = error.toDartString();
- malloc.free(error);
+ _bindings.spine_skeleton_data_result_dispose(result);
throw Exception("Couldn't load skeleton data: $message");
}
- return SkeletonData._(result.skeletonData);
+ var data = SkeletonData._(_bindings.spine_skeleton_data_result_get_data(result));
+ _bindings.spine_skeleton_data_result_dispose(result);
+ return data;
}
static SkeletonData fromBinary(Atlas atlas, Uint8List binary) {
- final Pointer binaryNative = malloc.allocate(binary.lengthInBytes);
+ final Pointer binaryNative = _allocator.allocate(binary.lengthInBytes);
binaryNative.asTypedList(binary.lengthInBytes).setAll(0, binary);
final result = _bindings.spine_skeleton_data_load_binary(atlas._atlas, binaryNative.cast(), binary.lengthInBytes);
- malloc.free(binaryNative);
- if (result.error.address != nullptr.address) {
- final Pointer error = result.error.cast();
+ _allocator.free(binaryNative);
+ if (_bindings.spine_skeleton_data_result_get_error(result).address != nullptr.address) {
+ final Pointer error = _bindings.spine_skeleton_data_result_get_error(result).cast();
final message = error.toDartString();
- malloc.free(error);
+ _bindings.spine_skeleton_data_result_dispose(result);
throw Exception("Couldn't load skeleton data: $message");
}
- return SkeletonData._(result.skeletonData);
+ var data = SkeletonData._(_bindings.spine_skeleton_data_result_get_data(result));
+ _bindings.spine_skeleton_data_result_dispose(result);
+ return data;
}
static Future fromAsset(AssetBundle assetBundle, Atlas atlas, String skeletonFile) async {
@@ -169,18 +186,18 @@ class SkeletonData {
/// Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it multiple times.
BoneData? findBone(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final bone = _bindings.spine_skeleton_data_find_bone(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (bone.address == nullptr.address) return null;
return BoneData._(bone);
}
/// Finds a slot by comparing each slot's name. It is more efficient to cache the results of this method than to call it multiple times.
SlotData? findSlot(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final slot = _bindings.spine_skeleton_data_find_slot(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (slot.address == nullptr.address) return null;
return SlotData._(slot);
}
@@ -188,9 +205,9 @@ class SkeletonData {
/// Finds a skin by comparing each skin's name. It is more efficient to cache the results of this method than to call it
/// multiple times.
Skin? findSkin(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final skin = _bindings.spine_skeleton_data_find_skin(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (skin.address == nullptr.address) return null;
return Skin._(skin);
}
@@ -198,9 +215,9 @@ class SkeletonData {
/// Finds an event by comparing each events's name. It is more efficient to cache the results of this method than to call it
/// multiple times.
EventData? findEvent(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final event = _bindings.spine_skeleton_data_find_event(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (event.address == nullptr.address) return null;
return EventData._(event);
}
@@ -208,9 +225,9 @@ class SkeletonData {
/// Finds an animation by comparing each animation's name. It is more efficient to cache the results of this method than to
/// call it multiple times.
Animation? findAnimation(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final animation = _bindings.spine_skeleton_data_find_animation(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (animation.address == nullptr.address) return null;
return Animation._(animation);
}
@@ -218,9 +235,9 @@ class SkeletonData {
/// Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results of this method
/// than to call it multiple times.
IkConstraintData? findIkConstraint(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final constraint = _bindings.spine_skeleton_data_find_ik_constraint(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (constraint.address == nullptr.address) return null;
return IkConstraintData._(constraint);
}
@@ -228,9 +245,9 @@ class SkeletonData {
/// Finds a transform constraint by comparing each transform constraint's name. It is more efficient to cache the results of
/// this method than to call it multiple times.
TransformConstraintData? findTransformConstraint(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final constraint = _bindings.spine_skeleton_data_find_transform_constraint(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (constraint.address == nullptr.address) return null;
return TransformConstraintData._(constraint);
}
@@ -238,9 +255,9 @@ class SkeletonData {
/// Finds a path constraint by comparing each path constraint's name. It is more efficient to cache the results of this method
/// than to call it multiple times.
PathConstraintData? findPathConstraint(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final constraint = _bindings.spine_skeleton_data_find_path_constraint(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (constraint.address == nullptr.address) return null;
return PathConstraintData._(constraint);
}
@@ -588,7 +605,11 @@ class BoneData {
Color getColor() {
final color = _bindings.spine_bone_data_get_color(_data);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -633,12 +654,16 @@ class Bone {
Vector2 worldToLocal(double worldX, double worldY) {
final local = _bindings.spine_bone_world_to_local(_bone, worldX, worldY);
- return Vector2(local.x, local.y);
+ final result = Vector2(_bindings.spine_vector_get_x(local), _bindings.spine_vector_get_y(local));
+ _allocator.free(local);
+ return result;
}
Vector2 localToWorld(double localX, double localY) {
final world = _bindings.spine_bone_local_to_world(_bone, localX, localY);
- return Vector2(world.x, world.y);
+ final result = Vector2(_bindings.spine_vector_get_x(world), _bindings.spine_vector_get_y(world));
+ _allocator.free(world);
+ return result;
}
double worldToLocalRotation(double worldRotation) {
@@ -890,7 +915,11 @@ class SlotData {
Color getColor() {
final color = _bindings.spine_slot_data_get_color(_data);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -899,7 +928,11 @@ class SlotData {
Color getDarkColor() {
final color = _bindings.spine_slot_data_get_dark_color(_data);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setDarkColor(double r, double g, double b, double a) {
@@ -920,9 +953,9 @@ class SlotData {
}
void setAttachmentName(String attachmentName) {
- final nativeName = attachmentName.toNativeUtf8();
+ final nativeName = attachmentName.toNativeUtf8(_allocator);
_bindings.spine_slot_data_set_attachment_name(_data, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
}
BlendMode getBlendMode() {
@@ -962,7 +995,11 @@ class Slot {
Color getColor() {
final color = _bindings.spine_slot_get_color(_slot);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(Color color) {
@@ -971,7 +1008,11 @@ class Slot {
Color getDarkColor() {
final color = _bindings.spine_slot_get_dark_color(_slot);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setDarkColor(Color color) {
@@ -1118,11 +1159,11 @@ class Sequence {
}
String getPath(String basePath, int index) {
- final nativeBasePath = basePath.toNativeUtf8();
+ final nativeBasePath = basePath.toNativeUtf8(_allocator);
final Pointer path = _bindings.spine_sequence_get_path(_sequence, nativeBasePath.cast(), index).cast();
final result = path.toDartString();
- malloc.free(nativeBasePath);
- malloc.free(path);
+ _allocator.free(nativeBasePath);
+ _allocator.free(path);
return result;
}
@@ -1228,10 +1269,10 @@ class RegionAttachment extends Attachment {
RegionAttachment._(spine_region_attachment attachment) : super._(attachment);
List computeWorldVertices(Slot slot) {
- Pointer vertices = malloc.allocate(4 * 8).cast();
+ Pointer vertices = _allocator.allocate(4 * 8).cast();
_bindings.spine_region_attachment_compute_world_vertices(_attachment, slot._slot, vertices);
final result = vertices.asTypedList(8).toList();
- malloc.free(vertices);
+ _allocator.free(vertices);
return result;
}
@@ -1293,7 +1334,11 @@ class RegionAttachment extends Attachment {
Color getColor() {
final color = _bindings.spine_region_attachment_get_color(_attachment);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -1335,10 +1380,10 @@ class VertexAttachment extends Attachment {
List computeWorldVertices(Slot slot) {
final worldVerticesLength = _bindings.spine_vertex_attachment_get_world_vertices_length(_attachment.cast());
- Pointer vertices = malloc.allocate(4 * worldVerticesLength).cast();
+ Pointer vertices = _allocator.allocate(4 * worldVerticesLength).cast();
_bindings.spine_vertex_attachment_compute_world_vertices(_attachment.cast(), slot._slot, vertices);
final result = vertices.asTypedList(worldVerticesLength).toList();
- malloc.free(vertices);
+ _allocator.free(vertices);
return result;
}
@@ -1401,7 +1446,11 @@ class MeshAttachment extends VertexAttachment {
Color getColor() {
final color = _bindings.spine_mesh_attachment_get_color(_attachment);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -1473,7 +1522,11 @@ class ClippingAttachment extends VertexAttachment {
Color getColor() {
final color = _bindings.spine_clipping_attachment_get_color(_attachment);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -1486,7 +1539,11 @@ class BoundingBoxAttachment extends VertexAttachment {
Color getColor() {
final color = _bindings.spine_path_attachment_get_color(_attachment);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -1534,7 +1595,9 @@ class PointAttachment extends Attachment {
Vector2 computeWorldPosition(Bone bone) {
final position = _bindings.spine_point_attachment_compute_world_position(_attachment, bone._bone);
- return Vector2(position.x, position.y);
+ final result = Vector2(_bindings.spine_vector_get_x(position), _bindings.spine_vector_get_y(position));
+ _allocator.free(position);
+ return result;
}
double computeWorldRotation(Bone bone) {
@@ -1567,7 +1630,11 @@ class PointAttachment extends Attachment {
Color getColor() {
final color = _bindings.spine_point_attachment_get_color(_attachment);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(double r, double g, double b, double a) {
@@ -1590,9 +1657,9 @@ class Skin {
Skin._(this._skin) : _isCustomSkin = false;
Skin.new(String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
_skin = _bindings.spine_skin_create(nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
_isCustomSkin = true;
}
@@ -1602,24 +1669,24 @@ class Skin {
}
void setAttachment(int slotIndex, String name, Attachment? attachment) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
_bindings.spine_skin_set_attachment(
_skin, slotIndex, nativeName.cast(), attachment == null ? nullptr : attachment._attachment.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
}
Attachment? getAttachment(int slotIndex, String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
final attachment = _bindings.spine_skin_get_attachment(_skin, slotIndex, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
if (attachment.address == nullptr.address) return null;
return Attachment._toSubclass(attachment);
}
void removeAttachment(int slotIndex, String name) {
- final nativeName = name.toNativeUtf8();
+ final nativeName = name.toNativeUtf8(_allocator);
_bindings.spine_skin_remove_attachment(_skin, slotIndex, nativeName.cast());
- malloc.free(nativeName);
+ _allocator.free(nativeName);
}
String getName() {
@@ -1634,12 +1701,12 @@ class Skin {
List getEntries() {
List result = [];
final entries = _bindings.spine_skin_get_entries(_skin);
- int numEntries = entries.ref.numEntries;
+ int numEntries = _bindings.spine_skin_entries_get_num_entries(entries);
for (int i = 0; i < numEntries; i++) {
- final entry = entries.ref.entries[i];
- Pointer name = entry.name.cast();
- result.add(SkinEntry(entry.slotIndex, name.toDartString(),
- entry.attachment.address == nullptr.address ? null : Attachment._toSubclass(entry.attachment)));
+ final entry = _bindings.spine_skin_entries_get_entry(entries, i);
+ Pointer name = _bindings.spine_skin_entry_get_name(entry).cast();
+ result.add(SkinEntry(_bindings.spine_skin_entry_get_slot_index(entry), name.toDartString(),
+ _bindings.spine_skin_entry_get_attachment(entry).address == nullptr.address ? null : Attachment._toSubclass(_bindings.spine_skin_entry_get_attachment(entry))));
}
return result;
}
@@ -2297,17 +2364,17 @@ class Skeleton {
}
Bone? findBone(String boneName) {
- final nameNative = boneName.toNativeUtf8();
+ final nameNative = boneName.toNativeUtf8(_allocator);
final bone = _bindings.spine_skeleton_find_bone(_skeleton, nameNative.cast());
- malloc.free(nameNative);
+ _allocator.free(nameNative);
if (bone.address == nullptr.address) return null;
return Bone._(bone);
}
Slot? findSlot(String slotName) {
- final nameNative = slotName.toNativeUtf8();
+ final nameNative = slotName.toNativeUtf8(_allocator);
final slot = _bindings.spine_skeleton_find_slot(_skeleton, nameNative.cast());
- malloc.free(nameNative);
+ _allocator.free(nameNative);
if (slot.address == nullptr.address) return null;
return Slot._(slot);
}
@@ -2320,9 +2387,9 @@ class Skeleton {
/// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin.
/// @param skinName May be NULL.
void setSkinByName(String skinName) {
- final nameNative = skinName.toNativeUtf8();
+ final nameNative = skinName.toNativeUtf8(_allocator);
_bindings.spine_skeleton_set_skin_by_name(_skeleton, nameNative.cast());
- malloc.free(nameNative);
+ _allocator.free(nameNative);
}
void setSkin(Skin skin) {
@@ -2330,52 +2397,52 @@ class Skeleton {
}
Attachment? getAttachmentByName(String slotName, String attachmentName) {
- final slotNameNative = slotName.toNativeUtf8();
- final attachmentNameNative = attachmentName.toNativeUtf8();
+ final slotNameNative = slotName.toNativeUtf8(_allocator);
+ final attachmentNameNative = attachmentName.toNativeUtf8(_allocator);
final attachment =
_bindings.spine_skeleton_get_attachment_by_name(_skeleton, slotNameNative.cast(), attachmentNameNative.cast());
- malloc.free(slotNameNative);
- malloc.free(attachmentNameNative);
+ _allocator.free(slotNameNative);
+ _allocator.free(attachmentNameNative);
if (attachment.address == nullptr.address) return null;
return Attachment._toSubclass(attachment);
}
Attachment? getAttachment(int slotIndex, String attachmentName) {
- final attachmentNameNative = attachmentName.toNativeUtf8();
+ final attachmentNameNative = attachmentName.toNativeUtf8(_allocator);
final attachment = _bindings.spine_skeleton_get_attachment(_skeleton, slotIndex, attachmentNameNative.cast());
- malloc.free(attachmentNameNative);
+ _allocator.free(attachmentNameNative);
if (attachment.address == nullptr.address) return null;
return Attachment._toSubclass(attachment);
}
void setAttachment(String slotName, String attachmentName) {
- final slotNameNative = slotName.toNativeUtf8();
- final attachmentNameNative = attachmentName.toNativeUtf8();
+ final slotNameNative = slotName.toNativeUtf8(_allocator);
+ final attachmentNameNative = attachmentName.toNativeUtf8(_allocator);
_bindings.spine_skeleton_set_attachment(_skeleton, slotNameNative.cast(), attachmentNameNative.cast());
- malloc.free(slotNameNative);
- malloc.free(attachmentNameNative);
+ _allocator.free(slotNameNative);
+ _allocator.free(attachmentNameNative);
}
IkConstraint? findIkConstraint(String constraintName) {
- final nameNative = constraintName.toNativeUtf8();
+ final nameNative = constraintName.toNativeUtf8(_allocator);
final constraint = _bindings.spine_skeleton_find_ik_constraint(_skeleton, nameNative.cast());
- malloc.free(nameNative);
+ _allocator.free(nameNative);
if (constraint.address == nullptr.address) return null;
return IkConstraint._(constraint);
}
TransformConstraint? findTransformConstraint(String constraintName) {
- final nameNative = constraintName.toNativeUtf8();
+ final nameNative = constraintName.toNativeUtf8(_allocator);
final constraint = _bindings.spine_skeleton_find_transform_constraint(_skeleton, nameNative.cast());
- malloc.free(nameNative);
+ _allocator.free(nameNative);
if (constraint.address == nullptr.address) return null;
return TransformConstraint._(constraint);
}
PathConstraint? findPathConstraint(String constraintName) {
- final nameNative = constraintName.toNativeUtf8();
+ final nameNative = constraintName.toNativeUtf8(_allocator);
final constraint = _bindings.spine_skeleton_find_path_constraint(_skeleton, nameNative.cast());
- malloc.free(nameNative);
+ _allocator.free(nameNative);
if (constraint.address == nullptr.address) return null;
return PathConstraint._(constraint);
}
@@ -2388,7 +2455,13 @@ class Skeleton {
/// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed.
Bounds getBounds() {
final nativeBounds = _bindings.spine_skeleton_get_bounds(_skeleton);
- return Bounds(nativeBounds.x, nativeBounds.y, nativeBounds.width, nativeBounds.height);
+ final bounds = Bounds(
+ _bindings.spine_bounds_get_x(nativeBounds),
+ _bindings.spine_bounds_get_y(nativeBounds),
+ _bindings.spine_bounds_get_width(nativeBounds),
+ _bindings.spine_bounds_get_height(nativeBounds));
+ _allocator.free(nativeBounds);
+ return bounds;
}
Bone? getRootBone() {
@@ -2471,7 +2544,11 @@ class Skeleton {
Color getColor() {
final color = _bindings.spine_skeleton_get_color(_skeleton);
- return Color(color.r, color.g, color.b, color.a);
+ return Color(
+ _bindings.spine_color_get_r(color),
+ _bindings.spine_color_get_g(color),
+ _bindings.spine_color_get_b(color),
+ _bindings.spine_color_get_a(color));
}
void setColor(Color color) {
@@ -2848,9 +2925,9 @@ class EventData {
}
void setStringValue(String value) {
- final nativeString = value.toNativeUtf8();
+ final nativeString = value.toNativeUtf8(_allocator);
_bindings.spine_event_data_set_string_value(_data, nativeString.cast());
- malloc.free(nativeString);
+ _allocator.free(nativeString);
}
String getAudioPath() {
@@ -2910,9 +2987,9 @@ class Event {
}
void setStringValue(String value) {
- final nativeString = value.toNativeUtf8();
+ final nativeString = value.toNativeUtf8(_allocator);
_bindings.spine_event_set_string_value(_event, nativeString.cast());
- malloc.free(nativeString);
+ _allocator.free(nativeString);
}
double getVolume() {
@@ -2952,19 +3029,19 @@ class AnimationStateData {
}
void setMixByName(String fromName, String toName, double duration) {
- final fromNative = fromName.toNativeUtf8();
- final toNative = toName.toNativeUtf8();
+ final fromNative = fromName.toNativeUtf8(_allocator);
+ final toNative = toName.toNativeUtf8(_allocator);
_bindings.spine_animation_state_data_set_mix_by_name(_data, fromNative.cast(), toNative.cast(), duration);
- malloc.free(fromNative);
- malloc.free(toNative);
+ _allocator.free(fromNative);
+ _allocator.free(toNative);
}
double getMixByName(String fromName, String toName) {
- final fromNative = fromName.toNativeUtf8();
- final toNative = toName.toNativeUtf8();
+ final fromNative = fromName.toNativeUtf8(_allocator);
+ final toNative = toName.toNativeUtf8(_allocator);
final duration = _bindings.spine_animation_state_data_get_mix_by_name(_data, fromNative.cast(), toNative.cast());
- malloc.free(fromNative);
- malloc.free(toNative);
+ _allocator.free(fromNative);
+ _allocator.free(toNative);
return duration;
}
@@ -3072,10 +3149,10 @@ class AnimationState {
/// A track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after AnimationState.Dispose.
TrackEntry setAnimationByName(int trackIndex, String animationName, bool loop) {
- final animation = animationName.toNativeUtf8();
+ final animation = animationName.toNativeUtf8(_allocator);
final entry =
_bindings.spine_animation_state_set_animation_by_name(_state, trackIndex, animation.cast(), loop ? -1 : 0);
- malloc.free(animation);
+ _allocator.free(animation);
if (entry.address == nullptr.address) throw Exception("Couldn't set animation $animationName");
return TrackEntry._(entry, this);
}
@@ -3096,10 +3173,10 @@ class AnimationState {
/// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after AnimationState.Dispose
TrackEntry addAnimationByName(int trackIndex, String animationName, bool loop, double delay) {
- final animation = animationName.toNativeUtf8();
+ final animation = animationName.toNativeUtf8(_allocator);
final entry = _bindings.spine_animation_state_add_animation_by_name(
_state, trackIndex, animation.cast(), loop ? -1 : 0, delay);
- malloc.free(animation);
+ _allocator.free(animation);
if (entry.address == nullptr.address) throw Exception("Couldn't add animation $animationName");
return TrackEntry._(entry, this);
}
@@ -3167,7 +3244,7 @@ class AnimationState {
class SkeletonDrawable {
final Atlas atlas;
final SkeletonData skeletonData;
- late final Pointer _drawable;
+ late final spine_skeleton_drawable _drawable;
late final Skeleton skeleton;
late final AnimationStateData animationStateData;
late final AnimationState animationState;
@@ -3176,12 +3253,11 @@ class SkeletonDrawable {
SkeletonDrawable(this.atlas, this.skeletonData, this._ownsAtlasAndSkeletonData) : _disposed = false {
_drawable = _bindings.spine_skeleton_drawable_create(skeletonData._data);
- skeleton = Skeleton._(_drawable.ref.skeleton);
- animationStateData = AnimationStateData._(_drawable.ref.animationStateData);
- animationState = AnimationState._(_drawable.ref.animationState, _drawable.ref.animationStateEvents);
+ skeleton = Skeleton._(_bindings.spine_skeleton_drawable_get_skeleton(_drawable));
+ animationStateData = AnimationStateData._(_bindings.spine_skeleton_drawable_get_animation_state_data(_drawable));
+ animationState = AnimationState._(_bindings.spine_skeleton_drawable_get_animation_state(_drawable), _bindings.spine_skeleton_drawable_get_animation_state_events(_drawable));
}
-
static Future fromAsset(String skeletonFile, String atlasFile) async {
var atlas = await Atlas.fromAsset(rootBundle, atlasFile);
var skeletonData = await SkeletonData.fromAsset(rootBundle, atlas, skeletonFile);
@@ -3209,12 +3285,12 @@ class SkeletonDrawable {
List render() {
if (_disposed) return [];
- Pointer nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
+ spine_render_command nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
List commands = [];
while (nativeCmd.address != nullptr.address) {
- final atlasPage = atlas.atlasPages[nativeCmd.ref.atlasPage];
+ final atlasPage = atlas.atlasPages[_bindings.spine_render_command_get_atlas_page(nativeCmd)];
commands.add(RenderCommand._(nativeCmd, atlasPage.width.toDouble(), atlasPage.height.toDouble()));
- nativeCmd = nativeCmd.ref.next;
+ nativeCmd = _bindings.spine_render_command_get_next(nativeCmd);
}
return commands;
}
@@ -3242,40 +3318,38 @@ class RenderCommand {
late final Vertices vertices;
late final int atlasPageIndex;
- RenderCommand._(Pointer nativeCmd, double pageWidth, double pageHeight) {
- atlasPageIndex = nativeCmd.ref.atlasPage;
- int numVertices = nativeCmd.ref.numVertices;
- int numIndices = nativeCmd.ref.numIndices;
- final positions = nativeCmd.ref.positions.asTypedList(numVertices * 2);
- final uvs = nativeCmd.ref.uvs.asTypedList(numVertices * 2);
+ RenderCommand._(spine_render_command nativeCmd, double pageWidth, double pageHeight) {
+ atlasPageIndex = _bindings.spine_render_command_get_atlas_page(nativeCmd);
+ int numVertices = _bindings.spine_render_command_get_num_vertices(nativeCmd);
+ int numIndices = _bindings.spine_render_command_get_num_indices(nativeCmd);
+ final positions = _bindings.spine_render_command_get_positions(nativeCmd).asTypedList(numVertices * 2);
+ final uvs = _bindings.spine_render_command_get_uvs(nativeCmd).asTypedList(numVertices * 2);
for (int i = 0; i < numVertices * 2; i += 2) {
uvs[i] *= pageWidth;
uvs[i + 1] *= pageHeight;
}
- // We pass the native data as views directly to Vertices.raw. According to the sources, the data
- // is copied, so it doesn't matter that we free up the underlying memory on the next
- // render call. See the implementation of Vertices.raw() here:
- // https://github.com/flutter/engine/blob/5c60785b802ad2c8b8899608d949342d5c624952/lib/ui/painting/vertices.cc#L21
- vertices = Vertices.raw(VertexMode.triangles, positions,
- textureCoordinates: uvs,
- colors: nativeCmd.ref.colors.asTypedList(numVertices),
- indices: nativeCmd.ref.indices.asTypedList(numIndices));
- }
-}
+ final colors = _bindings.spine_render_command_get_colors(nativeCmd).asTypedList(numVertices);
+ final indices = _bindings.spine_render_command_get_indices(nativeCmd).asTypedList(numIndices);
-const String _libName = 'spine_flutter';
-
-final DynamicLibrary _dylib = () {
- if (Platform.isMacOS || Platform.isIOS) {
- return DynamicLibrary.open('$_libName.framework/$_libName');
+ if (!kIsWeb) {
+ // We pass the native data as views directly to Vertices.raw. According to the sources, the data
+ // is copied, so it doesn't matter that we free up the underlying memory on the next
+ // render call. See the implementation of Vertices.raw() here:
+ // https://github.com/flutter/engine/blob/5c60785b802ad2c8b8899608d949342d5c624952/lib/ui/painting/vertices.cc#L21
+ vertices = Vertices.raw(VertexMode.triangles, positions,
+ textureCoordinates: uvs,
+ colors: _bindings.spine_render_command_get_colors(nativeCmd).asTypedList(numVertices),
+ indices: _bindings.spine_render_command_get_indices(nativeCmd).asTypedList(numIndices));
+ } else {
+ // On the web, rendering is done through CanvasKit, which requires copies of the native data.
+ final positionsCopy = Float32List.fromList(positions);
+ final uvsCopy = Float32List.fromList(uvs);
+ final colorsCopy = Int32List.fromList(colors);
+ final indicesCopy = Uint16List.fromList(indices);
+ vertices = Vertices.raw(VertexMode.triangles, positionsCopy,
+ textureCoordinates: uvsCopy,
+ colors: colorsCopy,
+ indices: indicesCopy);
+ }
}
- if (Platform.isAndroid || Platform.isLinux) {
- return DynamicLibrary.open('lib$_libName.so');
- }
- if (Platform.isWindows) {
- return DynamicLibrary.open('$_libName.dll');
- }
- throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
-}();
-
-final SpineFlutterBindings _bindings = SpineFlutterBindings(_dylib);
+}
\ No newline at end of file
diff --git a/spine-flutter/lib/spine_flutter_bindings_generated.dart b/spine-flutter/lib/spine_flutter_bindings_generated.dart
index 23a7a0a24..bbabff38c 100644
--- a/spine-flutter/lib/spine_flutter_bindings_generated.dart
+++ b/spine-flutter/lib/spine_flutter_bindings_generated.dart
@@ -5,7 +5,7 @@
// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
-import 'dart:ffi' as ffi;
+import 'ffi_proxy.dart' as ffi;
/// Bindings for `src/spine_flutter.h`.
///
@@ -31,7 +31,7 @@ class SpineFlutterBindings {
}
late final _spine_major_versionPtr =
- _lookup>('spine_major_version');
+ _lookup>('spine_major_version');
late final _spine_major_version =
_spine_major_versionPtr.asFunction();
@@ -40,7 +40,7 @@ class SpineFlutterBindings {
}
late final _spine_minor_versionPtr =
- _lookup>('spine_minor_version');
+ _lookup>('spine_minor_version');
late final _spine_minor_version =
_spine_minor_versionPtr.asFunction();
@@ -53,23 +53,208 @@ class SpineFlutterBindings {
late final _spine_report_leaks =
_spine_report_leaksPtr.asFunction();
- ffi.Pointer spine_atlas_load(
- ffi.Pointer atlasData,
+ double spine_color_get_r(
+ spine_color color,
+ ) {
+ return _spine_color_get_r(
+ color,
+ );
+ }
+
+ late final _spine_color_get_rPtr =
+ _lookup>(
+ 'spine_color_get_r');
+ late final _spine_color_get_r =
+ _spine_color_get_rPtr.asFunction();
+
+ double spine_color_get_g(
+ spine_color color,
+ ) {
+ return _spine_color_get_g(
+ color,
+ );
+ }
+
+ late final _spine_color_get_gPtr =
+ _lookup>(
+ 'spine_color_get_g');
+ late final _spine_color_get_g =
+ _spine_color_get_gPtr.asFunction();
+
+ double spine_color_get_b(
+ spine_color color,
+ ) {
+ return _spine_color_get_b(
+ color,
+ );
+ }
+
+ late final _spine_color_get_bPtr =
+ _lookup>(
+ 'spine_color_get_b');
+ late final _spine_color_get_b =
+ _spine_color_get_bPtr.asFunction();
+
+ double spine_color_get_a(
+ spine_color color,
+ ) {
+ return _spine_color_get_a(
+ color,
+ );
+ }
+
+ late final _spine_color_get_aPtr =
+ _lookup>(
+ 'spine_color_get_a');
+ late final _spine_color_get_a =
+ _spine_color_get_aPtr.asFunction();
+
+ double spine_bounds_get_x(
+ spine_bounds bounds,
+ ) {
+ return _spine_bounds_get_x(
+ bounds,
+ );
+ }
+
+ late final _spine_bounds_get_xPtr =
+ _lookup>(
+ 'spine_bounds_get_x');
+ late final _spine_bounds_get_x =
+ _spine_bounds_get_xPtr.asFunction();
+
+ double spine_bounds_get_y(
+ spine_bounds bounds,
+ ) {
+ return _spine_bounds_get_y(
+ bounds,
+ );
+ }
+
+ late final _spine_bounds_get_yPtr =
+ _lookup>(
+ 'spine_bounds_get_y');
+ late final _spine_bounds_get_y =
+ _spine_bounds_get_yPtr.asFunction();
+
+ double spine_bounds_get_width(
+ spine_bounds bounds,
+ ) {
+ return _spine_bounds_get_width(
+ bounds,
+ );
+ }
+
+ late final _spine_bounds_get_widthPtr =
+ _lookup>(
+ 'spine_bounds_get_width');
+ late final _spine_bounds_get_width =
+ _spine_bounds_get_widthPtr.asFunction();
+
+ double spine_bounds_get_height(
+ spine_bounds bounds,
+ ) {
+ return _spine_bounds_get_height(
+ bounds,
+ );
+ }
+
+ late final _spine_bounds_get_heightPtr =
+ _lookup>(
+ 'spine_bounds_get_height');
+ late final _spine_bounds_get_height =
+ _spine_bounds_get_heightPtr.asFunction();
+
+ double spine_vector_get_x(
+ spine_vector vector,
+ ) {
+ return _spine_vector_get_x(
+ vector,
+ );
+ }
+
+ late final _spine_vector_get_xPtr =
+ _lookup>(
+ 'spine_vector_get_x');
+ late final _spine_vector_get_x =
+ _spine_vector_get_xPtr.asFunction();
+
+ double spine_vector_get_y(
+ spine_vector vector,
+ ) {
+ return _spine_vector_get_y(
+ vector,
+ );
+ }
+
+ late final _spine_vector_get_yPtr =
+ _lookup>(
+ 'spine_vector_get_y');
+ late final _spine_vector_get_y =
+ _spine_vector_get_yPtr.asFunction();
+
+ spine_atlas spine_atlas_load(
+ ffi.Pointer atlasData,
) {
return _spine_atlas_load(
atlasData,
);
}
- late final _spine_atlas_loadPtr = _lookup<
- ffi.NativeFunction<
- ffi.Pointer Function(
- ffi.Pointer)>>('spine_atlas_load');
+ late final _spine_atlas_loadPtr =
+ _lookup)>>(
+ 'spine_atlas_load');
late final _spine_atlas_load = _spine_atlas_loadPtr
- .asFunction Function(ffi.Pointer)>();
+ .asFunction)>();
+
+ int spine_atlas_get_num_image_paths(
+ spine_atlas atlas,
+ ) {
+ return _spine_atlas_get_num_image_paths(
+ atlas,
+ );
+ }
+
+ late final _spine_atlas_get_num_image_pathsPtr =
+ _lookup>(
+ 'spine_atlas_get_num_image_paths');
+ late final _spine_atlas_get_num_image_paths =
+ _spine_atlas_get_num_image_pathsPtr
+ .asFunction();
+
+ ffi.Pointer spine_atlas_get_image_path(
+ spine_atlas atlas,
+ int index,
+ ) {
+ return _spine_atlas_get_image_path(
+ atlas,
+ index,
+ );
+ }
+
+ late final _spine_atlas_get_image_pathPtr = _lookup<
+ ffi.NativeFunction<
+ ffi.Pointer Function(
+ spine_atlas, ffi.Int32)>>('spine_atlas_get_image_path');
+ late final _spine_atlas_get_image_path = _spine_atlas_get_image_pathPtr
+ .asFunction Function(spine_atlas, int)>();
+
+ ffi.Pointer spine_atlas_get_error(
+ spine_atlas atlas,
+ ) {
+ return _spine_atlas_get_error(
+ atlas,
+ );
+ }
+
+ late final _spine_atlas_get_errorPtr =
+ _lookup Function(spine_atlas)>>(
+ 'spine_atlas_get_error');
+ late final _spine_atlas_get_error = _spine_atlas_get_errorPtr
+ .asFunction Function(spine_atlas)>();
void spine_atlas_dispose(
- ffi.Pointer atlas,
+ spine_atlas atlas,
) {
return _spine_atlas_dispose(
atlas,
@@ -77,14 +262,14 @@ class SpineFlutterBindings {
}
late final _spine_atlas_disposePtr =
- _lookup)>>(
+ _lookup>(
'spine_atlas_dispose');
- late final _spine_atlas_dispose = _spine_atlas_disposePtr
- .asFunction)>();
+ late final _spine_atlas_dispose =
+ _spine_atlas_disposePtr.asFunction();
spine_skeleton_data_result spine_skeleton_data_load_json(
- ffi.Pointer atlas,
- ffi.Pointer skeletonData,
+ spine_atlas atlas,
+ ffi.Pointer skeletonData,
) {
return _spine_skeleton_data_load_json(
atlas,
@@ -94,16 +279,16 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_load_jsonPtr = _lookup<
ffi.NativeFunction<
- spine_skeleton_data_result Function(ffi.Pointer,
- ffi.Pointer)>>('spine_skeleton_data_load_json');
+ spine_skeleton_data_result Function(spine_atlas,
+ ffi.Pointer)>>('spine_skeleton_data_load_json');
late final _spine_skeleton_data_load_json =
_spine_skeleton_data_load_jsonPtr.asFunction<
spine_skeleton_data_result Function(
- ffi.Pointer, ffi.Pointer)>();
+ spine_atlas, ffi.Pointer)>();
spine_skeleton_data_result spine_skeleton_data_load_binary(
- ffi.Pointer atlas,
- ffi.Pointer skeletonData,
+ spine_atlas atlas,
+ ffi.Pointer skeletonData,
int length,
) {
return _spine_skeleton_data_load_binary(
@@ -116,17 +301,64 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_load_binaryPtr = _lookup<
ffi.NativeFunction<
spine_skeleton_data_result Function(
- ffi.Pointer,
- ffi.Pointer,
- ffi.Int)>>('spine_skeleton_data_load_binary');
+ spine_atlas,
+ ffi.Pointer,
+ ffi.Int32)>>('spine_skeleton_data_load_binary');
late final _spine_skeleton_data_load_binary =
_spine_skeleton_data_load_binaryPtr.asFunction<
spine_skeleton_data_result Function(
- ffi.Pointer, ffi.Pointer, int)>();
+ spine_atlas, ffi.Pointer, int)>();
+
+ ffi.Pointer spine_skeleton_data_result_get_error(
+ spine_skeleton_data_result result,
+ ) {
+ return _spine_skeleton_data_result_get_error(
+ result,
+ );
+ }
+
+ late final _spine_skeleton_data_result_get_errorPtr = _lookup<
+ ffi.NativeFunction<
+ ffi.Pointer Function(spine_skeleton_data_result)>>(
+ 'spine_skeleton_data_result_get_error');
+ late final _spine_skeleton_data_result_get_error =
+ _spine_skeleton_data_result_get_errorPtr
+ .asFunction Function(spine_skeleton_data_result)>();
+
+ spine_skeleton_data spine_skeleton_data_result_get_data(
+ spine_skeleton_data_result result,
+ ) {
+ return _spine_skeleton_data_result_get_data(
+ result,
+ );
+ }
+
+ late final _spine_skeleton_data_result_get_dataPtr = _lookup<
+ ffi.NativeFunction<
+ spine_skeleton_data Function(spine_skeleton_data_result)>>(
+ 'spine_skeleton_data_result_get_data');
+ late final _spine_skeleton_data_result_get_data =
+ _spine_skeleton_data_result_get_dataPtr.asFunction<
+ spine_skeleton_data Function(spine_skeleton_data_result)>();
+
+ void spine_skeleton_data_result_dispose(
+ spine_skeleton_data_result result,
+ ) {
+ return _spine_skeleton_data_result_dispose(
+ result,
+ );
+ }
+
+ late final _spine_skeleton_data_result_disposePtr = _lookup<
+ ffi.NativeFunction>(
+ 'spine_skeleton_data_result_dispose');
+ late final _spine_skeleton_data_result_dispose =
+ _spine_skeleton_data_result_disposePtr
+ .asFunction();
spine_bone_data spine_skeleton_data_find_bone(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_bone(
data,
@@ -137,15 +369,14 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_find_bonePtr = _lookup<
ffi.NativeFunction<
spine_bone_data Function(spine_skeleton_data,
- ffi.Pointer)>>('spine_skeleton_data_find_bone');
+ ffi.Pointer)>>('spine_skeleton_data_find_bone');
late final _spine_skeleton_data_find_bone =
_spine_skeleton_data_find_bonePtr.asFunction<
- spine_bone_data Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_bone_data Function(spine_skeleton_data, ffi.Pointer)>();
spine_slot_data spine_skeleton_data_find_slot(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_slot(
data,
@@ -156,15 +387,14 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_find_slotPtr = _lookup<
ffi.NativeFunction<
spine_slot_data Function(spine_skeleton_data,
- ffi.Pointer)>>('spine_skeleton_data_find_slot');
+ ffi.Pointer)>>('spine_skeleton_data_find_slot');
late final _spine_skeleton_data_find_slot =
_spine_skeleton_data_find_slotPtr.asFunction<
- spine_slot_data Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_slot_data Function(spine_skeleton_data, ffi.Pointer)>();
spine_skin spine_skeleton_data_find_skin(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_skin(
data,
@@ -175,14 +405,14 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_find_skinPtr = _lookup<
ffi.NativeFunction<
spine_skin Function(spine_skeleton_data,
- ffi.Pointer)>>('spine_skeleton_data_find_skin');
+ ffi.Pointer)>>('spine_skeleton_data_find_skin');
late final _spine_skeleton_data_find_skin =
_spine_skeleton_data_find_skinPtr.asFunction<
- spine_skin Function(spine_skeleton_data, ffi.Pointer)>();
+ spine_skin Function(spine_skeleton_data, ffi.Pointer)>();
spine_event_data spine_skeleton_data_find_event(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_event(
data,
@@ -193,15 +423,14 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_find_eventPtr = _lookup<
ffi.NativeFunction<
spine_event_data Function(spine_skeleton_data,
- ffi.Pointer)>>('spine_skeleton_data_find_event');
+ ffi.Pointer)>>('spine_skeleton_data_find_event');
late final _spine_skeleton_data_find_event =
_spine_skeleton_data_find_eventPtr.asFunction<
- spine_event_data Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_event_data Function(spine_skeleton_data, ffi.Pointer)>();
spine_animation spine_skeleton_data_find_animation(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_animation(
data,
@@ -212,15 +441,14 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_find_animationPtr = _lookup<
ffi.NativeFunction<
spine_animation Function(spine_skeleton_data,
- ffi.Pointer)>>('spine_skeleton_data_find_animation');
+ ffi.Pointer)>>('spine_skeleton_data_find_animation');
late final _spine_skeleton_data_find_animation =
_spine_skeleton_data_find_animationPtr.asFunction<
- spine_animation Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_animation Function(spine_skeleton_data, ffi.Pointer)>();
spine_ik_constraint_data spine_skeleton_data_find_ik_constraint(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_ik_constraint(
data,
@@ -229,18 +457,17 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_find_ik_constraintPtr = _lookup<
- ffi.NativeFunction<
- spine_ik_constraint_data Function(
- spine_skeleton_data, ffi.Pointer)>>(
- 'spine_skeleton_data_find_ik_constraint');
+ ffi.NativeFunction<
+ spine_ik_constraint_data Function(spine_skeleton_data,
+ ffi.Pointer)>>('spine_skeleton_data_find_ik_constraint');
late final _spine_skeleton_data_find_ik_constraint =
_spine_skeleton_data_find_ik_constraintPtr.asFunction<
spine_ik_constraint_data Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_skeleton_data, ffi.Pointer)>();
spine_transform_constraint_data spine_skeleton_data_find_transform_constraint(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_transform_constraint(
data,
@@ -251,16 +478,16 @@ class SpineFlutterBindings {
late final _spine_skeleton_data_find_transform_constraintPtr = _lookup<
ffi.NativeFunction<
spine_transform_constraint_data Function(
- spine_skeleton_data, ffi.Pointer)>>(
+ spine_skeleton_data, ffi.Pointer)>>(
'spine_skeleton_data_find_transform_constraint');
late final _spine_skeleton_data_find_transform_constraint =
_spine_skeleton_data_find_transform_constraintPtr.asFunction<
spine_transform_constraint_data Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_skeleton_data, ffi.Pointer)>();
spine_path_constraint_data spine_skeleton_data_find_path_constraint(
spine_skeleton_data data,
- ffi.Pointer name,
+ ffi.Pointer name,
) {
return _spine_skeleton_data_find_path_constraint(
data,
@@ -269,16 +496,15 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_find_path_constraintPtr = _lookup<
- ffi.NativeFunction<
- spine_path_constraint_data Function(
- spine_skeleton_data, ffi.Pointer)>>(
- 'spine_skeleton_data_find_path_constraint');
+ ffi.NativeFunction<
+ spine_path_constraint_data Function(spine_skeleton_data,
+ ffi.Pointer)>>('spine_skeleton_data_find_path_constraint');
late final _spine_skeleton_data_find_path_constraint =
_spine_skeleton_data_find_path_constraintPtr.asFunction<
spine_path_constraint_data Function(
- spine_skeleton_data, ffi.Pointer)>();
+ spine_skeleton_data, ffi.Pointer)>();
- ffi.Pointer spine_skeleton_data_get_name(
+ ffi.Pointer spine_skeleton_data_get_name(
spine_skeleton_data data,
) {
return _spine_skeleton_data_get_name(
@@ -287,11 +513,10 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_namePtr = _lookup<
- ffi.NativeFunction<
- ffi.Pointer Function(
- spine_skeleton_data)>>('spine_skeleton_data_get_name');
+ ffi.NativeFunction Function(spine_skeleton_data)>>(
+ 'spine_skeleton_data_get_name');
late final _spine_skeleton_data_get_name = _spine_skeleton_data_get_namePtr
- .asFunction Function(spine_skeleton_data)>();
+ .asFunction Function(spine_skeleton_data)>();
/// OMITTED setName()
int spine_skeleton_data_get_num_bones(
@@ -303,7 +528,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_bonesPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_bones');
late final _spine_skeleton_data_get_num_bones =
_spine_skeleton_data_get_num_bonesPtr
@@ -333,7 +558,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_slotsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_slots');
late final _spine_skeleton_data_get_num_slots =
_spine_skeleton_data_get_num_slotsPtr
@@ -363,7 +588,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_skinsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_skins');
late final _spine_skeleton_data_get_num_skins =
_spine_skeleton_data_get_num_skinsPtr
@@ -426,7 +651,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_eventsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_events');
late final _spine_skeleton_data_get_num_events =
_spine_skeleton_data_get_num_eventsPtr
@@ -457,7 +682,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_animationsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_animations');
late final _spine_skeleton_data_get_num_animations =
_spine_skeleton_data_get_num_animationsPtr
@@ -488,7 +713,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_ik_constraintsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_ik_constraints');
late final _spine_skeleton_data_get_num_ik_constraints =
_spine_skeleton_data_get_num_ik_constraintsPtr
@@ -520,7 +745,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_transform_constraintsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_transform_constraints');
late final _spine_skeleton_data_get_num_transform_constraints =
_spine_skeleton_data_get_num_transform_constraintsPtr
@@ -554,7 +779,7 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_num_path_constraintsPtr =
- _lookup>(
+ _lookup>(
'spine_skeleton_data_get_num_path_constraints');
late final _spine_skeleton_data_get_num_path_constraints =
_spine_skeleton_data_get_num_path_constraintsPtr
@@ -705,7 +930,7 @@ class SpineFlutterBindings {
_spine_skeleton_data_set_heightPtr
.asFunction();
- ffi.Pointer spine_skeleton_data_get_version(
+ ffi.Pointer spine_skeleton_data_get_version(
spine_skeleton_data data,
) {
return _spine_skeleton_data_get_version(
@@ -714,15 +939,14 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_versionPtr = _lookup<
- ffi.NativeFunction<
- ffi.Pointer Function(
- spine_skeleton_data)>>('spine_skeleton_data_get_version');
+ ffi.NativeFunction Function(spine_skeleton_data)>>(
+ 'spine_skeleton_data_get_version');
late final _spine_skeleton_data_get_version =
_spine_skeleton_data_get_versionPtr
- .asFunction Function(spine_skeleton_data)>();
+ .asFunction Function(spine_skeleton_data)>();
/// OMITTED setVersion()
- ffi.Pointer spine_skeleton_data_get_hash(
+ ffi.Pointer spine_skeleton_data_get_hash(
spine_skeleton_data data,
) {
return _spine_skeleton_data_get_hash(
@@ -731,14 +955,13 @@ class SpineFlutterBindings {
}
late final _spine_skeleton_data_get_hashPtr = _lookup<
- ffi.NativeFunction<
- ffi.Pointer Function(
- spine_skeleton_data)>>('spine_skeleton_data_get_hash');
+ ffi.NativeFunction Function(spine_skeleton_data)>>(
+ 'spine_skeleton_data_get_hash');
late final _spine_skeleton_data_get_hash = _spine_skeleton_data_get_hashPtr
- .asFunction Function(spine_skeleton_data)>();
+ .asFunction