Browse Source

[flutter] Web support through WASM

Massive refactor, no more passing/returning structs by value and explicit initialization.
Mario Zechner 2 years ago
parent
commit
35a0aaf8dc

+ 6 - 0
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() {
+}

+ 4 - 1
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()

+ 21 - 0
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"

+ 0 - 2
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

BIN
spine-flutter/example/web/favicon.png


BIN
spine-flutter/example/web/icons/Icon-192.png


BIN
spine-flutter/example/web/icons/Icon-512.png


BIN
spine-flutter/example/web/icons/Icon-maskable-192.png


BIN
spine-flutter/example/web/icons/Icon-maskable-512.png


+ 58 - 0
spine-flutter/example/web/index.html

@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <!--
+    If you are serving your web app in a path other than the root, change the
+    href value below to reflect the base path you are serving from.
+
+    The path provided below has to start and end with a slash "/" in order for
+    it to work correctly.
+
+    For more details:
+    * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
+
+    This is a placeholder for base href that will be replaced by the value of
+    the `--base-href` argument provided to `flutter build`.
+  -->
+  <base href="$FLUTTER_BASE_HREF">
+
+  <meta charset="UTF-8">
+  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
+  <meta name="description" content="A new Flutter project.">
+
+  <!-- iOS meta tags & icons -->
+  <meta name="apple-mobile-web-app-capable" content="yes">
+  <meta name="apple-mobile-web-app-status-bar-style" content="black">
+  <meta name="apple-mobile-web-app-title" content="example">
+  <link rel="apple-touch-icon" href="icons/Icon-192.png">
+
+  <!-- Favicon -->
+  <link rel="icon" type="image/png" href="favicon.png"/>
+
+  <title>example</title>
+  <link rel="manifest" href="manifest.json">
+
+  <script>
+    // The value below is injected by flutter build, do not touch.
+    var serviceWorkerVersion = null;
+  </script>
+  <!-- This script adds the flutter initialization JS code -->
+  <script src="flutter.js" defer></script>
+</head>
+<body>
+  <script>
+    window.addEventListener('load', function(ev) {
+      // Download main.dart.js
+      _flutter.loader.loadEntrypoint({
+        serviceWorker: {
+          serviceWorkerVersion: serviceWorkerVersion,
+        }
+      }).then(function(engineInitializer) {
+        return engineInitializer.initializeEngine();
+      }).then(function(appRunner) {
+        return appRunner.runApp();
+      });
+    });
+  </script>
+</body>
+</html>

+ 35 - 0
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"
+        }
+    ]
+}

+ 1 - 0
spine-flutter/lib/ffi_proxy.dart

@@ -0,0 +1 @@
+export 'dart:ffi' if (dart.library.html) 'package:web_ffi/web_ffi.dart';

+ 87 - 0
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<Utf8>` 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<Utf8>` to a [String].
+extension Utf8Pointer on Pointer<Utf8> {
+  /// 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<Uint8>();
+    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<Uint8>();
+    if (length != null) {
+      RangeError.checkNotNegative(length, 'length');
+    } else {
+      length = _length(codeUnits);
+    }
+    return utf8.decode(codeUnits.asTypedList(length));
+  }
+
+  static int _length(Pointer<Uint8> 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<Utf8>`.
+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<Utf8> toNativeUtf8(Allocator allocator) {
+    final units = utf8.encode(this);
+    final Pointer<Uint8> result = allocator<Uint8>(units.length + 1);
+    final Uint8List nativeString = result.asTypedList(units.length + 1);
+    nativeString.setAll(0, units);
+    nativeString[units.length] = 0;
+    return result.cast();
+  }
+}

+ 28 - 0
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<SpineFlutterFFI> initSpineFlutterFFI() async {
+  return SpineFlutterFFI(_dylib, malloc);
+}

+ 77 - 0
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<SpineFlutterFFI> initSpineFlutterFFI() async {
+  if (_module == null) {
+    Memory.init();
+
+    registerOpaqueType<Utf8>();
+    registerOpaqueType<spine_skeleton_wrapper>();
+    registerOpaqueType<spine_skeleton_data_wrapper>();
+    registerOpaqueType<spine_bone_wrapper>();
+    registerOpaqueType<spine_bone_data_wrapper>();
+    registerOpaqueType<spine_slot_wrapper>();
+    registerOpaqueType<spine_slot_data_wrapper>();
+    registerOpaqueType<spine_skin_wrapper>();
+    registerOpaqueType<spine_attachment_wrapper>();
+    registerOpaqueType<spine_region_attachment_wrapper>();
+    registerOpaqueType<spine_vertex_attachment_wrapper>();
+    registerOpaqueType<spine_mesh_attachment_wrapper>();
+    registerOpaqueType<spine_clipping_attachment_wrapper>();
+    registerOpaqueType<spine_bounding_box_attachment_wrapper>();
+    registerOpaqueType<spine_path_attachment_wrapper>();
+    registerOpaqueType<spine_point_attachment_wrapper>();
+    registerOpaqueType<spine_texture_region_wrapper>();
+    registerOpaqueType<spine_sequence_wrapper>();
+    registerOpaqueType<spine_constraint_wrapper>();
+    registerOpaqueType<spine_constraint_data_wrapper>();
+    registerOpaqueType<spine_ik_constraint_wrapper>();
+    registerOpaqueType<spine_ik_constraint_data_wrapper>();
+    registerOpaqueType<spine_transform_constraint_wrapper>();
+    registerOpaqueType<spine_transform_constraint_data_wrapper>();
+    registerOpaqueType<spine_path_constraint_wrapper>();
+    registerOpaqueType<spine_path_constraint_data_wrapper>();
+    registerOpaqueType<spine_animation_state_wrapper>();
+    registerOpaqueType<spine_animation_state_data_wrapper>();
+    registerOpaqueType<spine_animation_state_events_wrapper>();
+    registerOpaqueType<spine_event_wrapper>();
+    registerOpaqueType<spine_event_data_wrapper>();
+    registerOpaqueType<spine_track_entry_wrapper>();
+    registerOpaqueType<spine_animation_wrapper>();
+    registerOpaqueType<spine_atlas_wrapper>();
+    registerOpaqueType<spine_skeleton_data_result_wrapper>();
+    registerOpaqueType<spine_render_command_wrapper>();
+    registerOpaqueType<spine_bounds_wrapper>();
+    registerOpaqueType<spine_color_wrapper>();
+    registerOpaqueType<spine_vector_wrapper>();
+    registerOpaqueType<spine_skeleton_drawable_wrapper>();
+    registerOpaqueType<spine_skin_entry_wrapper>();
+    registerOpaqueType<spine_skin_entries_wrapper>();
+
+    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");
+  }
+}

+ 227 - 153
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<void> 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<spine_atlas> _atlas;
+  final spine_atlas _atlas;
   final List<Image> atlasPages;
   final List<Paint> atlasPagePaints;
   bool _disposed;
@@ -56,11 +68,11 @@ class Atlas {
   static Future<Atlas> _load(String atlasFileName, Future<Uint8List> 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<Utf8> error = atlas.ref.error.cast();
+    _allocator.free(atlasDataNative);
+    if (_bindings.spine_atlas_get_error(atlas).address != nullptr.address) {
+      final Pointer<Utf8> 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<Image> atlasPages = [];
     List<Paint> atlasPagePaints = [];
-    for (int i = 0; i < atlas.ref.numImagePaths; i++) {
-      final Pointer<Utf8> 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<Utf8> 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<Utf8> error = result.error.cast();
+    _allocator.free(jsonNative);
+    if (_bindings.spine_skeleton_data_result_get_error(result).address != nullptr.address) {
+      final Pointer<Utf8> 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<Uint8> binaryNative = malloc.allocate(binary.lengthInBytes);
+    final Pointer<Uint8> 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<Utf8> error = result.error.cast();
+    _allocator.free(binaryNative);
+    if (_bindings.spine_skeleton_data_result_get_error(result).address != nullptr.address) {
+      final Pointer<Utf8> 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<SkeletonData> 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<Utf8> 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<spine_region_attachment> {
   RegionAttachment._(spine_region_attachment attachment) : super._(attachment);
 
   List<double> computeWorldVertices(Slot slot) {
-    Pointer<Float> vertices = malloc.allocate(4 * 8).cast();
+    Pointer<Float> 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<spine_region_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<T extends Pointer> extends Attachment<T> {
 
   List<double> computeWorldVertices(Slot slot) {
     final worldVerticesLength = _bindings.spine_vertex_attachment_get_world_vertices_length(_attachment.cast());
-    Pointer<Float> vertices = malloc.allocate(4 * worldVerticesLength).cast();
+    Pointer<Float> 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<spine_mesh_attachment> {
 
   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<spine_clipping_attachment> {
 
   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<spine_bounding_box_attachme
 
   Color getColor() {
     final color = _bindings.spine_bounding_box_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) {
@@ -1521,7 +1578,11 @@ class PathAttachment extends VertexAttachment<spine_path_attachment> {
 
   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<spine_point_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<spine_point_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<SkinEntry> getEntries() {
     List<SkinEntry> 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<Utf8> 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<Utf8> 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<spine_skeleton_drawable> _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<SkeletonDrawable> 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<RenderCommand> render() {
     if (_disposed) return [];
-    Pointer<spine_render_command> nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
+    spine_render_command nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
     List<RenderCommand> 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<spine_render_command> 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));
-  }
-}
-
-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');
+    final colors = _bindings.spine_render_command_get_colors(nativeCmd).asTypedList(numVertices);
+    final indices = _bindings.spine_render_command_get_indices(nativeCmd).asTypedList(numIndices);
+
+    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);
+    }
   }
-  throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
-}();
-
-final SpineFlutterBindings _bindings = SpineFlutterBindings(_dylib);
+}

File diff suppressed because it is too large
+ 544 - 124
spine-flutter/lib/spine_flutter_bindings_generated.dart


+ 2 - 0
spine-flutter/pubspec.yaml

@@ -12,6 +12,8 @@ dependencies:
     sdk: flutter
   plugin_platform_interface: ^2.0.2
   ffi: ^2.0.1
+  web_ffi: ^0.7.2
+  inject_js: ^2.0.0
   http: ^0.13.5
 
 dev_dependencies:

+ 5 - 0
spine-flutter/src/compile-wasm.sh

@@ -0,0 +1,5 @@
+#!/bin/sh
+dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+pushd $dir > /dev/null
+emcc -Ispine-cpp/include --closure 1 -O3 -fno-rtti -fno-exceptions -s MAIN_MODULE=1 -s EXPORT_NAME=libspine_flutter -s MODULARIZE=1 spine_flutter.cpp `find spine-cpp/src -type f` -o ../lib/assets/libspine_flutter.js
+popd

File diff suppressed because it is too large
+ 385 - 174
spine-flutter/src/spine_flutter.cpp


+ 233 - 240
spine-flutter/src/spine_flutter.h

@@ -82,18 +82,17 @@ SPINE_OPAQUE_TYPE(spine_event)
 SPINE_OPAQUE_TYPE(spine_event_data)
 SPINE_OPAQUE_TYPE(spine_track_entry)
 SPINE_OPAQUE_TYPE(spine_animation)
-
-typedef struct spine_atlas {
-    void *atlas;
-    char **imagePaths;
-    int numImagePaths;
-    char *error;
-} spine_atlas;
-
-typedef struct spine_skeleton_data_result {
-    spine_skeleton_data skeletonData;
-    char *error;
-} spine_skeleton_data_result;
+SPINE_OPAQUE_TYPE(spine_atlas)
+SPINE_OPAQUE_TYPE(spine_skeleton_data_result)
+SPINE_OPAQUE_TYPE(spine_render_command)
+SPINE_OPAQUE_TYPE(spine_bounds)
+SPINE_OPAQUE_TYPE(spine_color)
+SPINE_OPAQUE_TYPE(spine_vector)
+SPINE_OPAQUE_TYPE(spine_skeleton_drawable)
+SPINE_OPAQUE_TYPE(spine_skin_entry)
+SPINE_OPAQUE_TYPE(spine_skin_entries)
+
+typedef uint8_t utf8;
 
 typedef enum spine_blend_mode {
     SPINE_BLEND_MODE_NORMAL = 0,
@@ -159,86 +158,61 @@ typedef enum spine_rotate_mode {
     SPINE_ROTATE_MODE_CHAIN_SCALE
 } spine_rotate_mode;
 
-typedef struct spine_render_command {
-    float *positions;
-    float *uvs;
-    int32_t *colors;
-    int numVertices;
-    uint16_t *indices;
-    int numIndices;
-    int atlasPage;
-    spine_blend_mode blendMode;
-    struct spine_render_command *next;
-} spine_render_command;
-
-typedef struct spine_bounds {
-    float x, y, width, height;
-} spine_bounds;
-
-typedef struct spine_color {
-    float r, g, b, a;
-} spine_color;
-
-typedef struct spine_vector {
-    float x, y;
-} spine_vector;
-
-typedef struct spine_skeleton_drawable {
-    spine_skeleton skeleton;
-    spine_animation_state animationState;
-    spine_animation_state_data animationStateData;
-    spine_animation_state_events animationStateEvents;
-    void *clipping;
-    spine_render_command *renderCommand;
-} spine_skeleton_drawable;
-
-typedef struct spine_skin_entry {
-    int slotIndex;
-    const char* name;
-    spine_attachment attachment;
-} spine_skin_entry;
-
-typedef struct spine_skin_entries {
-    int numEntries;
-    spine_skin_entry* entries;
-} spine_skin_entries;
-
-FFI_PLUGIN_EXPORT int spine_major_version();
-FFI_PLUGIN_EXPORT int spine_minor_version();
+FFI_PLUGIN_EXPORT int32_t spine_major_version();
+FFI_PLUGIN_EXPORT int32_t spine_minor_version();
 FFI_PLUGIN_EXPORT void spine_report_leaks();
 
-FFI_PLUGIN_EXPORT spine_atlas* spine_atlas_load(const char *atlasData);
-FFI_PLUGIN_EXPORT void spine_atlas_dispose(spine_atlas *atlas);
-
-FFI_PLUGIN_EXPORT spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas *atlas, const char *skeletonData);
-FFI_PLUGIN_EXPORT spine_skeleton_data_result spine_skeleton_data_load_binary(spine_atlas *atlas, const unsigned char *skeletonData, int length);
-FFI_PLUGIN_EXPORT spine_bone_data spine_skeleton_data_find_bone(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_slot_data spine_skeleton_data_find_slot(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_skin spine_skeleton_data_find_skin(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_event_data spine_skeleton_data_find_event(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_animation spine_skeleton_data_find_animation(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_ik_constraint_data spine_skeleton_data_find_ik_constraint(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_transform_constraint_data spine_skeleton_data_find_transform_constraint(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT spine_path_constraint_data spine_skeleton_data_find_path_constraint(spine_skeleton_data data, const char *name);
-FFI_PLUGIN_EXPORT const char* spine_skeleton_data_get_name(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT float spine_color_get_r(spine_color color);
+FFI_PLUGIN_EXPORT float spine_color_get_g(spine_color color);
+FFI_PLUGIN_EXPORT float spine_color_get_b(spine_color color);
+FFI_PLUGIN_EXPORT float spine_color_get_a(spine_color color);
+
+FFI_PLUGIN_EXPORT float spine_bounds_get_x(spine_bounds bounds);
+FFI_PLUGIN_EXPORT float spine_bounds_get_y(spine_bounds bounds);
+FFI_PLUGIN_EXPORT float spine_bounds_get_width(spine_bounds bounds);
+FFI_PLUGIN_EXPORT float spine_bounds_get_height(spine_bounds bounds);
+
+FFI_PLUGIN_EXPORT float spine_vector_get_x(spine_vector vector);
+FFI_PLUGIN_EXPORT float spine_vector_get_y(spine_vector vector);
+
+FFI_PLUGIN_EXPORT spine_atlas spine_atlas_load(const utf8 *atlasData);
+FFI_PLUGIN_EXPORT int32_t spine_atlas_get_num_image_paths(spine_atlas atlas);
+FFI_PLUGIN_EXPORT utf8 *spine_atlas_get_image_path(spine_atlas atlas, int32_t index);
+FFI_PLUGIN_EXPORT utf8 *spine_atlas_get_error(spine_atlas atlas);
+FFI_PLUGIN_EXPORT void spine_atlas_dispose(spine_atlas atlas);
+
+FFI_PLUGIN_EXPORT spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const utf8 *skeletonData);
+FFI_PLUGIN_EXPORT spine_skeleton_data_result spine_skeleton_data_load_binary(spine_atlas atlas, const uint8_t *skeletonData, int32_t length);
+FFI_PLUGIN_EXPORT utf8 *spine_skeleton_data_result_get_error(spine_skeleton_data_result result);
+FFI_PLUGIN_EXPORT spine_skeleton_data spine_skeleton_data_result_get_data(spine_skeleton_data_result result);
+FFI_PLUGIN_EXPORT void spine_skeleton_data_result_dispose(spine_skeleton_data_result result);
+FFI_PLUGIN_EXPORT spine_bone_data spine_skeleton_data_find_bone(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_slot_data spine_skeleton_data_find_slot(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_skin spine_skeleton_data_find_skin(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_event_data spine_skeleton_data_find_event(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_animation spine_skeleton_data_find_animation(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_ik_constraint_data spine_skeleton_data_find_ik_constraint(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_transform_constraint_data spine_skeleton_data_find_transform_constraint(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT spine_path_constraint_data spine_skeleton_data_find_path_constraint(spine_skeleton_data data, const utf8 *name);
+FFI_PLUGIN_EXPORT const utf8* spine_skeleton_data_get_name(spine_skeleton_data data);
 // OMITTED setName()
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_bones(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_bones(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_bone_data* spine_skeleton_data_get_bones(spine_skeleton_data data);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_slots(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_slots(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_slot_data* spine_skeleton_data_get_slots(spine_skeleton_data data);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_skins(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_skins(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_skin* spine_skeleton_data_get_skins(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_skin spine_skeleton_data_get_default_skin(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT void spine_skeleton_data_set_default_skin(spine_skeleton_data data, spine_skin skin);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_events(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_events(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_event_data* spine_skeleton_data_get_events(spine_skeleton_data data);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_animations(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_animations(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_animation* spine_skeleton_data_get_animations(spine_skeleton_data data);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_ik_constraints(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_ik_constraints(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_ik_constraint_data* spine_skeleton_data_get_ik_constraints(spine_skeleton_data data);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_transform_constraints(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_transform_constraints(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_transform_constraint_data* spine_skeleton_data_get_transform_constraints(spine_skeleton_data data);
-FFI_PLUGIN_EXPORT int spine_skeleton_data_get_num_path_constraints(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_data_get_num_path_constraints(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT spine_path_constraint_data* spine_skeleton_data_get_path_constraints(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT float spine_skeleton_data_get_x(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT void spine_skeleton_data_set_x(spine_skeleton_data data, float x);
@@ -248,23 +222,37 @@ FFI_PLUGIN_EXPORT float spine_skeleton_data_get_width(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT void spine_skeleton_data_set_width(spine_skeleton_data data, float width);
 FFI_PLUGIN_EXPORT float spine_skeleton_data_get_height(spine_skeleton_data data);
 FFI_PLUGIN_EXPORT void spine_skeleton_data_set_height(spine_skeleton_data data, float height);
-FFI_PLUGIN_EXPORT const char* spine_skeleton_data_get_version(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT const utf8 *spine_skeleton_data_get_version(spine_skeleton_data data);
 // OMITTED setVersion()
-FFI_PLUGIN_EXPORT const char* spine_skeleton_data_get_hash(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT const utf8 *spine_skeleton_data_get_hash(spine_skeleton_data data);
 // OMITTED setHash()
-FFI_PLUGIN_EXPORT const char* spine_skeleton_data_get_images_path(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT const utf8 *spine_skeleton_data_get_images_path(spine_skeleton_data data);
 // OMITTED setImagesPath()
-FFI_PLUGIN_EXPORT const char* spine_skeleton_data_get_audio_path(spine_skeleton_data data);
+FFI_PLUGIN_EXPORT const utf8 *spine_skeleton_data_get_audio_path(spine_skeleton_data data);
 // OMITTED setAudioPath()
 FFI_PLUGIN_EXPORT float spine_skeleton_data_get_fps(spine_skeleton_data data);
 // OMITTED setFps()
 FFI_PLUGIN_EXPORT void spine_skeleton_data_dispose(spine_skeleton_data data);
 
-FFI_PLUGIN_EXPORT spine_skeleton_drawable *spine_skeleton_drawable_create(spine_skeleton_data skeletonData);
-FFI_PLUGIN_EXPORT spine_render_command *spine_skeleton_drawable_render(spine_skeleton_drawable *drawable);
-FFI_PLUGIN_EXPORT void spine_skeleton_drawable_dispose(spine_skeleton_drawable *drawable);
-
-FFI_PLUGIN_EXPORT const char* spine_animation_get_name(spine_animation animation);
+FFI_PLUGIN_EXPORT spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skeletonData);
+FFI_PLUGIN_EXPORT spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable drawable);
+FFI_PLUGIN_EXPORT void spine_skeleton_drawable_dispose(spine_skeleton_drawable drawable);
+FFI_PLUGIN_EXPORT spine_skeleton spine_skeleton_drawable_get_skeleton(spine_skeleton_drawable drawable);
+FFI_PLUGIN_EXPORT spine_animation_state spine_skeleton_drawable_get_animation_state(spine_skeleton_drawable drawable);
+FFI_PLUGIN_EXPORT spine_animation_state_data spine_skeleton_drawable_get_animation_state_data(spine_skeleton_drawable drawable);
+FFI_PLUGIN_EXPORT spine_animation_state_events spine_skeleton_drawable_get_animation_state_events(spine_skeleton_drawable drawable);
+
+FFI_PLUGIN_EXPORT float *spine_render_command_get_positions(spine_render_command command);
+FFI_PLUGIN_EXPORT float *spine_render_command_get_uvs(spine_render_command command);
+FFI_PLUGIN_EXPORT int32_t *spine_render_command_get_colors(spine_render_command command);
+FFI_PLUGIN_EXPORT int32_t spine_render_command_get_num_vertices(spine_render_command command);
+FFI_PLUGIN_EXPORT uint16_t *spine_render_command_get_indices(spine_render_command command);
+FFI_PLUGIN_EXPORT int32_t spine_render_command_get_num_indices(spine_render_command command);
+FFI_PLUGIN_EXPORT int32_t spine_render_command_get_atlas_page(spine_render_command command);
+FFI_PLUGIN_EXPORT spine_blend_mode spine_render_command_get_blend_mode(spine_render_command command);
+FFI_PLUGIN_EXPORT spine_render_command spine_render_command_get_next(spine_render_command command);
+
+FFI_PLUGIN_EXPORT const utf8* spine_animation_get_name(spine_animation animation);
 // OMITTED getTimelines()
 // OMITTED hasTimeline()
 FFI_PLUGIN_EXPORT float spine_animation_get_duration(spine_animation animation);
@@ -275,23 +263,23 @@ FFI_PLUGIN_EXPORT float spine_animation_state_data_get_default_mix(spine_animati
 FFI_PLUGIN_EXPORT void spine_animation_state_data_set_default_mix(spine_animation_state_data stateData, float defaultMix);
 FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to, float duration);
 FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to);
-FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix_by_name(spine_animation_state_data stateData, const char* fromName, const char* toName, float duration);
-FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix_by_name(spine_animation_state_data stateData, const char* fromName, const char* toName);
+FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix_by_name(spine_animation_state_data stateData, const utf8* fromName, const utf8* toName, float duration);
+FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix_by_name(spine_animation_state_data stateData, const utf8* fromName, const utf8* toName);
 FFI_PLUGIN_EXPORT void spine_animation_state_data_clear(spine_animation_state_data stateData);
 
 FFI_PLUGIN_EXPORT void spine_animation_state_update(spine_animation_state state, float delta);
 FFI_PLUGIN_EXPORT void spine_animation_state_apply(spine_animation_state state, spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT void spine_animation_state_clear_tracks(spine_animation_state state);
-FFI_PLUGIN_EXPORT void spine_animation_state_clear_track(spine_animation_state state, int trackIndex);
-FFI_PLUGIN_EXPORT int spine_animation_state_get_num_tracks(spine_animation_state state);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_set_animation_by_name(spine_animation_state state, int trackIndex, const char* animationName, int loop);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_set_animation(spine_animation_state state, int trackIndex, spine_animation animation, int loop);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_add_animation_by_name(spine_animation_state state, int trackIndex, const char* animationName, int loop, float delay);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_add_animation(spine_animation_state state, int trackIndex, spine_animation animation, int loop, float delay);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_set_empty_animation(spine_animation_state state, int trackIndex, float mixDuration);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_add_empty_animation(spine_animation_state state, int trackIndex, float mixDuration, float delay);
+FFI_PLUGIN_EXPORT void spine_animation_state_clear_track(spine_animation_state state, int32_t trackIndex);
+FFI_PLUGIN_EXPORT int32_t spine_animation_state_get_num_tracks(spine_animation_state state);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_set_animation_by_name(spine_animation_state state, int32_t trackIndex, const utf8* animationName, int32_t loop);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_set_animation(spine_animation_state state, int32_t trackIndex, spine_animation animation, int32_t loop);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_add_animation_by_name(spine_animation_state state, int32_t trackIndex, const utf8* animationName, int32_t loop, float delay);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_add_animation(spine_animation_state state, int32_t trackIndex, spine_animation animation, int32_t loop, float delay);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_set_empty_animation(spine_animation_state state, int32_t trackIndex, float mixDuration);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_add_empty_animation(spine_animation_state state, int32_t trackIndex, float mixDuration, float delay);
 FFI_PLUGIN_EXPORT void spine_animation_state_set_empty_animations(spine_animation_state state, float mixDuration);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_get_current(spine_animation_state state, int trackIndex);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_get_current(spine_animation_state state, int32_t trackIndex);
 FFI_PLUGIN_EXPORT spine_animation_state_data spine_animation_state_get_data(spine_animation_state state);
 FFI_PLUGIN_EXPORT float spine_animation_state_get_time_scale(spine_animation_state state);
 FFI_PLUGIN_EXPORT void spine_animation_state_set_time_scale(spine_animation_state state, float timeScale);
@@ -303,23 +291,23 @@ FFI_PLUGIN_EXPORT void spine_animation_state_set_time_scale(spine_animation_stat
 // OMITTED getManualTrackEntryDisposal()
 FFI_PLUGIN_EXPORT void spine_animation_state_dispose_track_entry(spine_animation_state state, spine_track_entry entry);
 
-FFI_PLUGIN_EXPORT int spine_animation_state_events_get_num_events(spine_animation_state_events events);
-FFI_PLUGIN_EXPORT spine_event_type spine_animation_state_events_get_event_type(spine_animation_state_events events, int index);
-FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_events_get_track_entry(spine_animation_state_events events, int index);
-FFI_PLUGIN_EXPORT spine_event spine_animation_state_events_get_event(spine_animation_state_events events, int index);
+FFI_PLUGIN_EXPORT int32_t spine_animation_state_events_get_num_events(spine_animation_state_events events);
+FFI_PLUGIN_EXPORT spine_event_type spine_animation_state_events_get_event_type(spine_animation_state_events events, int32_t index);
+FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_events_get_track_entry(spine_animation_state_events events, int32_t index);
+FFI_PLUGIN_EXPORT spine_event spine_animation_state_events_get_event(spine_animation_state_events events, int32_t index);
 FFI_PLUGIN_EXPORT void spine_animation_state_events_reset(spine_animation_state_events events);
 
-FFI_PLUGIN_EXPORT int spine_track_entry_get_track_index(spine_track_entry entry);
+FFI_PLUGIN_EXPORT int32_t spine_track_entry_get_track_index(spine_track_entry entry);
 FFI_PLUGIN_EXPORT spine_animation spine_track_entry_get_animation(spine_track_entry entry);
 FFI_PLUGIN_EXPORT spine_track_entry spine_track_entry_get_previous(spine_track_entry entry);
-FFI_PLUGIN_EXPORT int spine_track_entry_get_loop(spine_track_entry entry);
-FFI_PLUGIN_EXPORT void spine_track_entry_set_loop(spine_track_entry entry, int loop);
-FFI_PLUGIN_EXPORT int spine_track_entry_get_hold_previous(spine_track_entry entry);
-FFI_PLUGIN_EXPORT void spine_track_entry_set_hold_previous(spine_track_entry entry, int holdPrevious);
-FFI_PLUGIN_EXPORT int spine_track_entry_get_reverse(spine_track_entry entry);
-FFI_PLUGIN_EXPORT void spine_track_entry_set_reverse(spine_track_entry entry, int reverse);
-FFI_PLUGIN_EXPORT int spine_track_entry_get_shortest_rotation(spine_track_entry entry);
-FFI_PLUGIN_EXPORT void spine_track_entry_set_shortest_rotation(spine_track_entry entry, int shortestRotation);
+FFI_PLUGIN_EXPORT int32_t spine_track_entry_get_loop(spine_track_entry entry);
+FFI_PLUGIN_EXPORT void spine_track_entry_set_loop(spine_track_entry entry, int32_t loop);
+FFI_PLUGIN_EXPORT int32_t spine_track_entry_get_hold_previous(spine_track_entry entry);
+FFI_PLUGIN_EXPORT void spine_track_entry_set_hold_previous(spine_track_entry entry, int32_t holdPrevious);
+FFI_PLUGIN_EXPORT int32_t spine_track_entry_get_reverse(spine_track_entry entry);
+FFI_PLUGIN_EXPORT void spine_track_entry_set_reverse(spine_track_entry entry, int32_t reverse);
+FFI_PLUGIN_EXPORT int32_t spine_track_entry_get_shortest_rotation(spine_track_entry entry);
+FFI_PLUGIN_EXPORT void spine_track_entry_set_shortest_rotation(spine_track_entry entry, int32_t shortestRotation);
 FFI_PLUGIN_EXPORT float spine_track_entry_get_delay(spine_track_entry entry);
 FFI_PLUGIN_EXPORT void spine_track_entry_set_delay(spine_track_entry entry, float delay);
 FFI_PLUGIN_EXPORT float spine_track_entry_get_track_time(spine_track_entry entry);
@@ -344,7 +332,7 @@ FFI_PLUGIN_EXPORT void spine_track_entry_set_attachment_threshold(spine_track_en
 FFI_PLUGIN_EXPORT float spine_track_entry_get_draw_order_threshold(spine_track_entry entry);
 FFI_PLUGIN_EXPORT void spine_track_entry_set_draw_order_threshold(spine_track_entry entry, float drawOrderThreshold);
 FFI_PLUGIN_EXPORT spine_track_entry spine_track_entry_get_next(spine_track_entry entry);
-FFI_PLUGIN_EXPORT int spine_track_entry_is_complete(spine_track_entry entry);
+FFI_PLUGIN_EXPORT int32_t spine_track_entry_is_complete(spine_track_entry entry);
 FFI_PLUGIN_EXPORT float spine_track_entry_get_mix_time(spine_track_entry entry);
 FFI_PLUGIN_EXPORT void spine_track_entry_set_mix_time(spine_track_entry entry, float mixTime);
 FFI_PLUGIN_EXPORT float spine_track_entry_get_mix_duration(spine_track_entry entry);
@@ -365,31 +353,31 @@ FFI_PLUGIN_EXPORT void spine_skeleton_update_world_transform_bone(spine_skeleton
 FFI_PLUGIN_EXPORT void spine_skeleton_set_to_setup_pose(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT void spine_skeleton_set_bones_to_setup_pose(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT void spine_skeleton_set_slots_to_setup_pose(spine_skeleton skeleton);
-FFI_PLUGIN_EXPORT spine_bone spine_skeleton_find_bone(spine_skeleton skeleton, const char* boneName);
-FFI_PLUGIN_EXPORT spine_slot spine_skeleton_find_slot(spine_skeleton skeleton, const char* slotName);
-FFI_PLUGIN_EXPORT void spine_skeleton_set_skin_by_name(spine_skeleton skeleton, const char* skinName);
+FFI_PLUGIN_EXPORT spine_bone spine_skeleton_find_bone(spine_skeleton skeleton, const utf8* boneName);
+FFI_PLUGIN_EXPORT spine_slot spine_skeleton_find_slot(spine_skeleton skeleton, const utf8* slotName);
+FFI_PLUGIN_EXPORT void spine_skeleton_set_skin_by_name(spine_skeleton skeleton, const utf8* skinName);
 FFI_PLUGIN_EXPORT void spine_skeleton_set_skin(spine_skeleton skeleton, spine_skin skin);
-FFI_PLUGIN_EXPORT spine_attachment spine_skeleton_get_attachment_by_name(spine_skeleton skeleton, const char* slotName, const char* attachmentName);
-FFI_PLUGIN_EXPORT spine_attachment spine_skeleton_get_attachment(spine_skeleton skeleton, int slotIndex, const char* attachmentName);
-FFI_PLUGIN_EXPORT void spine_skeleton_set_attachment(spine_skeleton skeleton, const char* slotName, const char* attachmentName);
-FFI_PLUGIN_EXPORT spine_ik_constraint spine_skeleton_find_ik_constraint(spine_skeleton skeleton, const char* constraintName);
-FFI_PLUGIN_EXPORT spine_transform_constraint spine_skeleton_find_transform_constraint(spine_skeleton skeleton, const char* constraintName);
-FFI_PLUGIN_EXPORT spine_path_constraint spine_skeleton_find_path_constraint(spine_skeleton skeleton, const char* constraintName);
+FFI_PLUGIN_EXPORT spine_attachment spine_skeleton_get_attachment_by_name(spine_skeleton skeleton, const utf8* slotName, const utf8* attachmentName);
+FFI_PLUGIN_EXPORT spine_attachment spine_skeleton_get_attachment(spine_skeleton skeleton, int32_t slotIndex, const utf8* attachmentName);
+FFI_PLUGIN_EXPORT void spine_skeleton_set_attachment(spine_skeleton skeleton, const utf8* slotName, const utf8* attachmentName);
+FFI_PLUGIN_EXPORT spine_ik_constraint spine_skeleton_find_ik_constraint(spine_skeleton skeleton, const utf8* constraintName);
+FFI_PLUGIN_EXPORT spine_transform_constraint spine_skeleton_find_transform_constraint(spine_skeleton skeleton, const utf8* constraintName);
+FFI_PLUGIN_EXPORT spine_path_constraint spine_skeleton_find_path_constraint(spine_skeleton skeleton, const utf8* constraintName);
 FFI_PLUGIN_EXPORT spine_bounds spine_skeleton_get_bounds(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_bone spine_skeleton_get_root_bone(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_skeleton_data spine_skeleton_get_data(spine_skeleton skeleton);
-FFI_PLUGIN_EXPORT int spine_skeleton_get_num_bones(spine_skeleton skeleton);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_get_num_bones(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_bone* spine_skeleton_get_bones(spine_skeleton skeleton);
 // OMITTED getUpdateCacheList()
-FFI_PLUGIN_EXPORT int spine_skeleton_get_num_slots(spine_skeleton skeleton);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_get_num_slots(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_slot* spine_skeleton_get_slots(spine_skeleton skeleton);
-FFI_PLUGIN_EXPORT int spine_skeleton_get_num_draw_order(spine_skeleton skeleton);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_get_num_draw_order(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_slot* spine_skeleton_get_draw_order(spine_skeleton skeleton);
-FFI_PLUGIN_EXPORT int spine_skeleton_get_num_ik_constraints(spine_skeleton skeleton);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_get_num_ik_constraints(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_ik_constraint* spine_skeleton_get_ik_constraints(spine_skeleton skeleton);
-FFI_PLUGIN_EXPORT int spine_skeleton_get_num_transform_constraints(spine_skeleton skeleton);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_get_num_transform_constraints(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_transform_constraint* spine_skeleton_get_transform_constraints(spine_skeleton skeleton);
-FFI_PLUGIN_EXPORT int spine_skeleton_get_num_path_constraints(spine_skeleton skeleton);
+FFI_PLUGIN_EXPORT int32_t spine_skeleton_get_num_path_constraints(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_path_constraint* spine_skeleton_get_path_constraints(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_skin spine_skeleton_get_skin(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT spine_color spine_skeleton_get_color(spine_skeleton skeleton);
@@ -404,14 +392,14 @@ FFI_PLUGIN_EXPORT void spine_skeleton_set_scale_x(spine_skeleton skeleton, float
 FFI_PLUGIN_EXPORT float spine_skeleton_get_scale_y(spine_skeleton skeleton);
 FFI_PLUGIN_EXPORT void spine_skeleton_set_scale_y(spine_skeleton skeleton, float scaleY);
 
-FFI_PLUGIN_EXPORT const char* spine_event_data_get_name(spine_event_data event);
-FFI_PLUGIN_EXPORT int spine_event_data_get_int_value(spine_event_data event);
-FFI_PLUGIN_EXPORT void spine_event_data_set_int_value(spine_event_data event, int value);
+FFI_PLUGIN_EXPORT const utf8* spine_event_data_get_name(spine_event_data event);
+FFI_PLUGIN_EXPORT int32_t spine_event_data_get_int_value(spine_event_data event);
+FFI_PLUGIN_EXPORT void spine_event_data_set_int_value(spine_event_data event, int32_t value);
 FFI_PLUGIN_EXPORT float spine_event_data_get_float_value(spine_event_data event);
 FFI_PLUGIN_EXPORT void spine_event_data_set_float_value(spine_event_data event, float value);
-FFI_PLUGIN_EXPORT const char* spine_event_data_get_string_value(spine_event_data event);
-FFI_PLUGIN_EXPORT void spine_event_data_set_string_value(spine_event_data event, const char *value);
-FFI_PLUGIN_EXPORT const char* spine_event_data_get_audio_path(spine_event_data event);
+FFI_PLUGIN_EXPORT const utf8* spine_event_data_get_string_value(spine_event_data event);
+FFI_PLUGIN_EXPORT void spine_event_data_set_string_value(spine_event_data event, const utf8 *value);
+FFI_PLUGIN_EXPORT const utf8* spine_event_data_get_audio_path(spine_event_data event);
 // OMITTED setAudioPath()
 FFI_PLUGIN_EXPORT float spine_event_data_get_volume(spine_event_data event);
 FFI_PLUGIN_EXPORT void spine_event_data_set_volume(spine_event_data event, float volume);
@@ -420,28 +408,28 @@ FFI_PLUGIN_EXPORT void spine_event_data_set_balance(spine_event_data event, floa
 
 FFI_PLUGIN_EXPORT spine_event_data spine_event_get_data(spine_event event);
 FFI_PLUGIN_EXPORT float spine_event_get_time(spine_event event);
-FFI_PLUGIN_EXPORT int spine_event_get_int_value(spine_event event);
-FFI_PLUGIN_EXPORT void spine_event_set_int_value(spine_event event, int value);
+FFI_PLUGIN_EXPORT int32_t spine_event_get_int_value(spine_event event);
+FFI_PLUGIN_EXPORT void spine_event_set_int_value(spine_event event, int32_t value);
 FFI_PLUGIN_EXPORT float spine_event_get_float_value(spine_event event);
 FFI_PLUGIN_EXPORT void spine_event_set_float_value(spine_event event, float value);
-FFI_PLUGIN_EXPORT const char* spine_event_get_string_value(spine_event event);
-FFI_PLUGIN_EXPORT void spine_event_set_string_value(spine_event event, const char *value);
+FFI_PLUGIN_EXPORT const utf8* spine_event_get_string_value(spine_event event);
+FFI_PLUGIN_EXPORT void spine_event_set_string_value(spine_event event, const utf8 *value);
 FFI_PLUGIN_EXPORT float spine_event_get_volume(spine_event event);
 FFI_PLUGIN_EXPORT void spine_event_set_volume(spine_event event, float volume);
 FFI_PLUGIN_EXPORT float spine_event_get_balance(spine_event event);
 FFI_PLUGIN_EXPORT void spine_event_set_balance(spine_event event, float balance);
 
-FFI_PLUGIN_EXPORT int spine_slot_data_get_index(spine_slot_data slot);
-FFI_PLUGIN_EXPORT const char* spine_slot_data_get_name(spine_slot_data slot);
+FFI_PLUGIN_EXPORT int32_t spine_slot_data_get_index(spine_slot_data slot);
+FFI_PLUGIN_EXPORT const utf8* spine_slot_data_get_name(spine_slot_data slot);
 FFI_PLUGIN_EXPORT spine_bone_data spine_slot_data_get_bone_data(spine_slot_data slot);
 FFI_PLUGIN_EXPORT spine_color spine_slot_data_get_color(spine_slot_data slot);
 FFI_PLUGIN_EXPORT void spine_slot_data_set_color(spine_slot_data slot, float r, float g, float b, float a);
 FFI_PLUGIN_EXPORT spine_color spine_slot_data_get_dark_color(spine_slot_data slot);
 FFI_PLUGIN_EXPORT void spine_slot_data_set_dark_color(spine_slot_data slot, float r, float g, float b, float a);
-FFI_PLUGIN_EXPORT int spine_slot_data_has_dark_color(spine_slot_data slot);
-FFI_PLUGIN_EXPORT void spine_slot_data_set_has_dark_color(spine_slot_data slot, int hasDarkColor);
-FFI_PLUGIN_EXPORT const char* spine_slot_data_get_attachment_name(spine_slot_data slot);
-FFI_PLUGIN_EXPORT void spine_slot_data_set_attachment_name(spine_slot_data slot, const char *attachmentName);
+FFI_PLUGIN_EXPORT int32_t spine_slot_data_has_dark_color(spine_slot_data slot);
+FFI_PLUGIN_EXPORT void spine_slot_data_set_has_dark_color(spine_slot_data slot, int32_t hasDarkColor);
+FFI_PLUGIN_EXPORT const utf8* spine_slot_data_get_attachment_name(spine_slot_data slot);
+FFI_PLUGIN_EXPORT void spine_slot_data_set_attachment_name(spine_slot_data slot, const utf8 *attachmentName);
 FFI_PLUGIN_EXPORT spine_blend_mode spine_slot_data_get_blend_mode(spine_slot_data slot);
 FFI_PLUGIN_EXPORT void spine_slot_data_set_blend_mode(spine_slot_data slot, spine_blend_mode blendMode);
 
@@ -453,16 +441,16 @@ FFI_PLUGIN_EXPORT spine_color spine_slot_get_color(spine_slot slot);
 FFI_PLUGIN_EXPORT void spine_slot_set_color(spine_slot slot, float r, float g, float b, float a);
 FFI_PLUGIN_EXPORT spine_color spine_slot_get_dark_color(spine_slot slot);
 FFI_PLUGIN_EXPORT void spine_slot_set_dark_color(spine_slot slot, float r, float g, float b, float a);
-FFI_PLUGIN_EXPORT int spine_slot_has_dark_color(spine_slot slot);
+FFI_PLUGIN_EXPORT int32_t spine_slot_has_dark_color(spine_slot slot);
 FFI_PLUGIN_EXPORT spine_attachment spine_slot_get_attachment(spine_slot slot);
 FFI_PLUGIN_EXPORT void spine_slot_set_attachment(spine_slot slot, spine_attachment attachment);
 // OMITTED getDeform()
-FFI_PLUGIN_EXPORT int spine_slot_get_sequence_index(spine_slot slot);
-FFI_PLUGIN_EXPORT void spine_slot_set_sequence_index(spine_slot slot, int sequenceIndex);
+FFI_PLUGIN_EXPORT int32_t spine_slot_get_sequence_index(spine_slot slot);
+FFI_PLUGIN_EXPORT void spine_slot_set_sequence_index(spine_slot slot, int32_t sequenceIndex);
 
 
-FFI_PLUGIN_EXPORT int spine_bone_data_get_index(spine_bone_data data);
-FFI_PLUGIN_EXPORT const char* spine_bone_data_get_name(spine_bone_data data);
+FFI_PLUGIN_EXPORT int32_t spine_bone_data_get_index(spine_bone_data data);
+FFI_PLUGIN_EXPORT const utf8* spine_bone_data_get_name(spine_bone_data data);
 FFI_PLUGIN_EXPORT spine_bone_data spine_bone_data_get_parent(spine_bone_data data);
 FFI_PLUGIN_EXPORT float spine_bone_data_get_length(spine_bone_data data);
 FFI_PLUGIN_EXPORT void spine_bone_data_set_length(spine_bone_data data, float length);
@@ -482,13 +470,13 @@ FFI_PLUGIN_EXPORT float spine_bone_data_get_shear_y(spine_bone_data data);
 FFI_PLUGIN_EXPORT void spine_bone_data_set_shear_y(spine_bone_data data, float shearY);
 FFI_PLUGIN_EXPORT spine_transform_mode spine_bone_data_get_transform_mode(spine_bone_data data);
 FFI_PLUGIN_EXPORT void spine_bone_data_set_transform_mode(spine_bone_data data, spine_transform_mode mode);
-FFI_PLUGIN_EXPORT int spine_bone_data_is_skin_required(spine_bone_data data);
-FFI_PLUGIN_EXPORT void spine_bone_data_set_is_skin_required(spine_bone_data data, int isSkinRequired);
+FFI_PLUGIN_EXPORT int32_t spine_bone_data_is_skin_required(spine_bone_data data);
+FFI_PLUGIN_EXPORT void spine_bone_data_set_is_skin_required(spine_bone_data data, int32_t isSkinRequired);
 FFI_PLUGIN_EXPORT spine_color spine_bone_data_get_color(spine_bone_data data);
 FFI_PLUGIN_EXPORT void spine_bone_data_set_color(spine_bone_data data, float r, float g, float b, float a);
 
-FFI_PLUGIN_EXPORT void spine_bone_set_is_y_down(int yDown);
-FFI_PLUGIN_EXPORT int spine_bone_get_is_y_down();
+FFI_PLUGIN_EXPORT void spine_bone_set_is_y_down(int32_t yDown);
+FFI_PLUGIN_EXPORT int32_t spine_bone_get_is_y_down();
 FFI_PLUGIN_EXPORT void spine_bone_update(spine_bone bone);
 FFI_PLUGIN_EXPORT void spine_bone_update_world_transform(spine_bone bone);
 FFI_PLUGIN_EXPORT void spine_bone_update_world_transform_with(spine_bone bone, float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY);
@@ -503,7 +491,7 @@ FFI_PLUGIN_EXPORT float spine_bone_get_world_to_local_rotation_y(spine_bone bone
 FFI_PLUGIN_EXPORT spine_bone_data spine_bone_get_data(spine_bone bone);
 FFI_PLUGIN_EXPORT spine_skeleton spine_bone_get_skeleton(spine_bone bone);
 FFI_PLUGIN_EXPORT spine_bone spine_bone_get_parent(spine_bone bone);
-FFI_PLUGIN_EXPORT int spine_bone_get_num_children(spine_bone bone);
+FFI_PLUGIN_EXPORT int32_t spine_bone_get_num_children(spine_bone bone);
 FFI_PLUGIN_EXPORT spine_bone* spine_bone_get_children(spine_bone bone);
 FFI_PLUGIN_EXPORT float spine_bone_get_x(spine_bone bone);
 FFI_PLUGIN_EXPORT void spine_bone_set_x(spine_bone bone, float x);
@@ -549,10 +537,10 @@ FFI_PLUGIN_EXPORT float spine_bone_get_world_rotation_x(spine_bone bone);
 FFI_PLUGIN_EXPORT float spine_bone_get_world_rotation_y(spine_bone bone);
 FFI_PLUGIN_EXPORT float spine_bone_get_world_scale_x(spine_bone bone);
 FFI_PLUGIN_EXPORT float spine_bone_get_world_scale_y(spine_bone bone);
-FFI_PLUGIN_EXPORT int spine_bone_get_is_active(spine_bone bone);
-FFI_PLUGIN_EXPORT void spine_bone_set_is_active(spine_bone bone, int isActive);
+FFI_PLUGIN_EXPORT int32_t spine_bone_get_is_active(spine_bone bone);
+FFI_PLUGIN_EXPORT void spine_bone_set_is_active(spine_bone bone, int32_t isActive);
 
-FFI_PLUGIN_EXPORT const char* spine_attachment_get_name(spine_attachment attachment);
+FFI_PLUGIN_EXPORT const utf8* spine_attachment_get_name(spine_attachment attachment);
 FFI_PLUGIN_EXPORT spine_attachment_type spine_attachment_get_type(spine_attachment attachment);
 FFI_PLUGIN_EXPORT spine_attachment spine_attachment_copy(spine_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_attachment_dispose(spine_attachment attachment);
@@ -586,40 +574,40 @@ FFI_PLUGIN_EXPORT float spine_region_attachment_get_height(spine_region_attachme
 FFI_PLUGIN_EXPORT void spine_region_attachment_set_height(spine_region_attachment attachment, float height);
 FFI_PLUGIN_EXPORT spine_color spine_region_attachment_get_color(spine_region_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_region_attachment_set_color(spine_region_attachment attachment, float r, float g, float b, float a);
-FFI_PLUGIN_EXPORT const char *spine_region_attachment_get_path(spine_region_attachment attachment);
+FFI_PLUGIN_EXPORT const utf8 *spine_region_attachment_get_path(spine_region_attachment attachment);
 // OMITTED setPath()
 FFI_PLUGIN_EXPORT spine_texture_region spine_region_attachment_get_region(spine_region_attachment attachment);
 // OMITTED setRegion()
 FFI_PLUGIN_EXPORT spine_sequence spine_region_attachment_get_sequence(spine_region_attachment attachment);
 // OMITTED setSequence()
-FFI_PLUGIN_EXPORT int spine_region_attachment_get_num_offset(spine_region_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_region_attachment_get_num_offset(spine_region_attachment attachment);
 FFI_PLUGIN_EXPORT float *spine_region_attachment_get_offset(spine_region_attachment attachment);
-FFI_PLUGIN_EXPORT int spine_region_attachment_get_num_uvs(spine_region_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_region_attachment_get_num_uvs(spine_region_attachment attachment);
 FFI_PLUGIN_EXPORT float *spine_region_attachment_get_uvs(spine_region_attachment attachment);
 
-FFI_PLUGIN_EXPORT int spine_vertex_attachment_get_world_vertices_length(spine_vertex_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_vertex_attachment_get_world_vertices_length(spine_vertex_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_vertex_attachment_compute_world_vertices(spine_vertex_attachment attachment, spine_slot slot, float *worldVertices);
 // OMITTED getId()
-FFI_PLUGIN_EXPORT int spine_vertex_attachment_get_num_bones(spine_vertex_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_vertex_attachment_get_num_bones(spine_vertex_attachment attachment);
 FFI_PLUGIN_EXPORT int32_t *spine_vertex_attachment_get_bones(spine_vertex_attachment attachment);
-FFI_PLUGIN_EXPORT int spine_vertex_attachment_get_num_vertices(spine_vertex_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_vertex_attachment_get_num_vertices(spine_vertex_attachment attachment);
 FFI_PLUGIN_EXPORT float *spine_vertex_attachment_get_vertices(spine_vertex_attachment attachment);
 FFI_PLUGIN_EXPORT spine_attachment spine_vertex_attachment_get_timeline_attachment(spine_vertex_attachment timelineAttachment);
 FFI_PLUGIN_EXPORT void spine_vertex_attachment_set_timeline_attachment(spine_vertex_attachment attachment, spine_attachment timelineAttachment);
 // OMITTED copyTo()
 
 FFI_PLUGIN_EXPORT void spine_mesh_attachment_update_region(spine_mesh_attachment attachment);
-FFI_PLUGIN_EXPORT int spine_mesh_attachment_get_hull_length(spine_mesh_attachment attachment);
-FFI_PLUGIN_EXPORT void spine_mesh_attachment_set_hull_length(spine_mesh_attachment attachment, int hullLength);
-FFI_PLUGIN_EXPORT int spine_mesh_attachment_get_num_region_uvs(spine_mesh_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_mesh_attachment_get_hull_length(spine_mesh_attachment attachment);
+FFI_PLUGIN_EXPORT void spine_mesh_attachment_set_hull_length(spine_mesh_attachment attachment, int32_t hullLength);
+FFI_PLUGIN_EXPORT int32_t spine_mesh_attachment_get_num_region_uvs(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT float *spine_mesh_attachment_get_region_uvs(spine_mesh_attachment attachment);
-FFI_PLUGIN_EXPORT int spine_mesh_attachment_get_num_uvs(spine_mesh_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_mesh_attachment_get_num_uvs(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT float *spine_mesh_attachment_get_uvs(spine_mesh_attachment attachment);
-FFI_PLUGIN_EXPORT int spine_mesh_attachment_get_num_triangles(spine_mesh_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_mesh_attachment_get_num_triangles(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT uint16_t *spine_mesh_attachment_get_triangles(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT spine_color spine_mesh_attachment_get_color(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_mesh_attachment_set_color(spine_mesh_attachment attachment, float r, float g, float b, float a);
-FFI_PLUGIN_EXPORT const char *spine_mesh_attachment_get_path(spine_mesh_attachment attachment);
+FFI_PLUGIN_EXPORT const utf8 *spine_mesh_attachment_get_path(spine_mesh_attachment attachment);
 // OMITTED setPath()
 FFI_PLUGIN_EXPORT spine_texture_region spine_mesh_attachment_get_region(spine_mesh_attachment attachment);
 // OMITTED setRegion()
@@ -627,7 +615,7 @@ FFI_PLUGIN_EXPORT spine_sequence spine_mesh_attachment_get_sequence(spine_mesh_a
 // OMITTED setSequence()
 FFI_PLUGIN_EXPORT spine_mesh_attachment spine_mesh_attachment_get_parent_mesh(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_mesh_attachment_set_parent_mesh(spine_mesh_attachment attachment, spine_mesh_attachment parentMesh);
-FFI_PLUGIN_EXPORT int spine_mesh_attachment_get_num_edges(spine_mesh_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_mesh_attachment_get_num_edges(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT uint16_t *spine_mesh_attachment_get_edges(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT float spine_mesh_attachment_get_width(spine_mesh_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_mesh_attachment_set_width(spine_mesh_attachment attachment, float width);
@@ -643,77 +631,82 @@ FFI_PLUGIN_EXPORT void spine_clipping_attachment_set_color(spine_clipping_attach
 FFI_PLUGIN_EXPORT spine_color spine_bounding_box_attachment_get_color(spine_bounding_box_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_bounding_box_attachment_set_color(spine_bounding_box_attachment attachment, float r, float g, float b, float a);
 
-FFI_PLUGIN_EXPORT int spine_path_attachment_get_num_lengths(spine_path_attachment attachment);
+FFI_PLUGIN_EXPORT int32_t spine_path_attachment_get_num_lengths(spine_path_attachment attachment);
 FFI_PLUGIN_EXPORT float *spine_path_attachment_get_lengths(spine_path_attachment attachment);
-FFI_PLUGIN_EXPORT int spine_path_attachment_get_is_closed(spine_path_attachment attachment);
-FFI_PLUGIN_EXPORT void spine_path_attachment_set_is_closed(spine_path_attachment attachment, int isClosed);
-FFI_PLUGIN_EXPORT int spine_path_attachment_get_is_constant_speed(spine_path_attachment attachment);
-FFI_PLUGIN_EXPORT void spine_path_attachment_set_is_constant_speed(spine_path_attachment attachment, int isConstantSpeed);
+FFI_PLUGIN_EXPORT int32_t spine_path_attachment_get_is_closed(spine_path_attachment attachment);
+FFI_PLUGIN_EXPORT void spine_path_attachment_set_is_closed(spine_path_attachment attachment, int32_t isClosed);
+FFI_PLUGIN_EXPORT int32_t spine_path_attachment_get_is_constant_speed(spine_path_attachment attachment);
+FFI_PLUGIN_EXPORT void spine_path_attachment_set_is_constant_speed(spine_path_attachment attachment, int32_t isConstantSpeed);
 FFI_PLUGIN_EXPORT spine_color spine_path_attachment_get_color(spine_path_attachment attachment);
 FFI_PLUGIN_EXPORT void spine_path_attachment_set_color(spine_path_attachment attachment, float r, float g, float b, float a);
 
-FFI_PLUGIN_EXPORT void spine_skin_set_attachment(spine_skin skin, int slotIndex, const char* name, spine_attachment attachment);
-FFI_PLUGIN_EXPORT spine_attachment spine_skin_get_attachment(spine_skin skin, int slotIndex, const char* name);
-FFI_PLUGIN_EXPORT void spine_skin_remove_attachment(spine_skin skin, int slotIndex, const char* name);
+FFI_PLUGIN_EXPORT void spine_skin_set_attachment(spine_skin skin, int32_t slotIndex, const utf8* name, spine_attachment attachment);
+FFI_PLUGIN_EXPORT spine_attachment spine_skin_get_attachment(spine_skin skin, int32_t slotIndex, const utf8* name);
+FFI_PLUGIN_EXPORT void spine_skin_remove_attachment(spine_skin skin, int32_t slotIndex, const utf8* name);
 // OMITTED findNamesForSlot()
 // OMITTED findAttachmentsForSlot()
-FFI_PLUGIN_EXPORT const char* spine_skin_get_name(spine_skin skin);
+FFI_PLUGIN_EXPORT const utf8* spine_skin_get_name(spine_skin skin);
 FFI_PLUGIN_EXPORT void spine_skin_add_skin(spine_skin skin, spine_skin other);
 FFI_PLUGIN_EXPORT void spine_skin_copy_skin(spine_skin skin, spine_skin other);
-FFI_PLUGIN_EXPORT spine_skin_entries *spine_skin_get_entries(spine_skin skin);
-FFI_PLUGIN_EXPORT void spine_skin_entries_dispose(spine_skin_entries *entries);
-FFI_PLUGIN_EXPORT int spine_skin_get_num_bones(spine_skin skin);
+FFI_PLUGIN_EXPORT spine_skin_entries spine_skin_get_entries(spine_skin skin);
+FFI_PLUGIN_EXPORT int32_t spine_skin_entries_get_num_entries(spine_skin_entries entries);
+FFI_PLUGIN_EXPORT spine_skin_entry spine_skin_entries_get_entry(spine_skin_entries entries, int32_t index);
+FFI_PLUGIN_EXPORT void spine_skin_entries_dispose(spine_skin_entries entries);
+FFI_PLUGIN_EXPORT int32_t spine_skin_entry_get_slot_index(spine_skin_entry entry);
+FFI_PLUGIN_EXPORT utf8 *spine_skin_entry_get_name(spine_skin_entry entry);
+FFI_PLUGIN_EXPORT spine_attachment spine_skin_entry_get_attachment(spine_skin_entry entry);
+FFI_PLUGIN_EXPORT int32_t spine_skin_get_num_bones(spine_skin skin);
 FFI_PLUGIN_EXPORT spine_bone_data* spine_skin_get_bones(spine_skin skin);
-FFI_PLUGIN_EXPORT int spine_skin_get_num_constraints(spine_skin skin);
+FFI_PLUGIN_EXPORT int32_t spine_skin_get_num_constraints(spine_skin skin);
 FFI_PLUGIN_EXPORT spine_constraint_data* spine_skin_get_constraints(spine_skin skin);
-FFI_PLUGIN_EXPORT spine_skin spine_skin_create(const char* name);
+FFI_PLUGIN_EXPORT spine_skin spine_skin_create(const utf8* name);
 FFI_PLUGIN_EXPORT void spine_skin_dispose(spine_skin skin);
 
 FFI_PLUGIN_EXPORT spine_constraint_type spine_constraint_data_get_type(spine_constraint_data data);
-FFI_PLUGIN_EXPORT const char* spine_constraint_data_get_name(spine_constraint_data data);
+FFI_PLUGIN_EXPORT const utf8* spine_constraint_data_get_name(spine_constraint_data data);
 FFI_PLUGIN_EXPORT uint64_t spine_constraint_data_get_order(spine_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_constraint_data_set_order(spine_constraint_data data, uint64_t order);
-FFI_PLUGIN_EXPORT int spine_constraint_data_get_is_skin_required(spine_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_constraint_data_set_is_skin_required(spine_constraint_data data, int isSkinRequired);
+FFI_PLUGIN_EXPORT int32_t spine_constraint_data_get_is_skin_required(spine_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_constraint_data_set_is_skin_required(spine_constraint_data data, int32_t isSkinRequired);
 
-FFI_PLUGIN_EXPORT int spine_ik_constraint_data_get_num_bones(spine_ik_constraint_data data);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_data_get_num_bones(spine_ik_constraint_data data);
 FFI_PLUGIN_EXPORT spine_bone_data* spine_ik_constraint_data_get_bones(spine_ik_constraint_data data);
 FFI_PLUGIN_EXPORT spine_bone_data spine_ik_constraint_data_get_target(spine_ik_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_target(spine_ik_constraint_data data, spine_bone_data target);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_data_get_bend_direction(spine_ik_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_bend_direction(spine_ik_constraint_data data, int bendDirection);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_data_get_compress(spine_ik_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_compress(spine_ik_constraint_data data, int compress);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_data_get_stretch(spine_ik_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_stretch(spine_ik_constraint_data data, int stretch);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_data_get_uniform(spine_ik_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_uniform(spine_ik_constraint_data data, int uniform);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_data_get_bend_direction(spine_ik_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_bend_direction(spine_ik_constraint_data data, int32_t bendDirection);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_data_get_compress(spine_ik_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_compress(spine_ik_constraint_data data, int32_t compress);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_data_get_stretch(spine_ik_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_stretch(spine_ik_constraint_data data, int32_t stretch);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_data_get_uniform(spine_ik_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_uniform(spine_ik_constraint_data data, int32_t uniform);
 FFI_PLUGIN_EXPORT float spine_ik_constraint_data_get_mix(spine_ik_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_mix(spine_ik_constraint_data data, float mix);
 FFI_PLUGIN_EXPORT float spine_ik_constraint_data_get_softness(spine_ik_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_ik_constraint_data_set_softness(spine_ik_constraint_data data, float softness);
 
 FFI_PLUGIN_EXPORT void spine_ik_constraint_update(spine_ik_constraint constraint);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_get_order(spine_ik_constraint constraint);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_get_order(spine_ik_constraint constraint);
 FFI_PLUGIN_EXPORT spine_ik_constraint_data spine_ik_constraint_get_data(spine_ik_constraint constraint);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_get_num_bones(spine_ik_constraint constraint);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_get_num_bones(spine_ik_constraint constraint);
 FFI_PLUGIN_EXPORT spine_bone* spine_ik_constraint_get_bones(spine_ik_constraint constraint);
 FFI_PLUGIN_EXPORT spine_bone spine_ik_constraint_get_target(spine_ik_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_ik_constraint_set_target(spine_ik_constraint constraint, spine_bone target);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_get_bend_direction(spine_ik_constraint constraint);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_set_bend_direction(spine_ik_constraint constraint, int bendDirection);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_get_compress(spine_ik_constraint constraint);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_set_compress(spine_ik_constraint constraint, int compress);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_get_stretch(spine_ik_constraint constraint);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_set_stretch(spine_ik_constraint constraint, int stretch);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_get_bend_direction(spine_ik_constraint constraint);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_set_bend_direction(spine_ik_constraint constraint, int32_t bendDirection);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_get_compress(spine_ik_constraint constraint);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_set_compress(spine_ik_constraint constraint, int32_t compress);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_get_stretch(spine_ik_constraint constraint);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_set_stretch(spine_ik_constraint constraint, int32_t stretch);
 FFI_PLUGIN_EXPORT float spine_ik_constraint_get_mix(spine_ik_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_ik_constraint_set_mix(spine_ik_constraint constraint, float mix);
 FFI_PLUGIN_EXPORT float spine_ik_constraint_get_softness(spine_ik_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_ik_constraint_set_softness(spine_ik_constraint constraint, float softness);
-FFI_PLUGIN_EXPORT int spine_ik_constraint_get_is_active(spine_ik_constraint constraint);
-FFI_PLUGIN_EXPORT void spine_ik_constraint_set_is_active(spine_ik_constraint constraint, int isActive);
+FFI_PLUGIN_EXPORT int32_t spine_ik_constraint_get_is_active(spine_ik_constraint constraint);
+FFI_PLUGIN_EXPORT void spine_ik_constraint_set_is_active(spine_ik_constraint constraint, int32_t isActive);
 
-FFI_PLUGIN_EXPORT int spine_transform_constraint_data_get_num_bones(spine_transform_constraint_data data);
+FFI_PLUGIN_EXPORT int32_t spine_transform_constraint_data_get_num_bones(spine_transform_constraint_data data);
 FFI_PLUGIN_EXPORT spine_bone_data* spine_transform_constraint_data_get_bones(spine_transform_constraint_data data);
 FFI_PLUGIN_EXPORT spine_bone_data spine_transform_constraint_data_get_target(spine_transform_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_target(spine_transform_constraint_data data, spine_bone_data target);
@@ -741,15 +734,15 @@ FFI_PLUGIN_EXPORT float spine_transform_constraint_data_get_offset_scale_y(spine
 FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_offset_scale_y(spine_transform_constraint_data data, float offsetScaleY);
 FFI_PLUGIN_EXPORT float spine_transform_constraint_data_get_offset_shear_y(spine_transform_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_offset_shear_y(spine_transform_constraint_data data, float offsetShearY);
-FFI_PLUGIN_EXPORT int spine_transform_constraint_data_get_is_relative(spine_transform_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_is_relative(spine_transform_constraint_data data, int isRelative);
-FFI_PLUGIN_EXPORT int spine_transform_constraint_data_get_is_local(spine_transform_constraint_data data);
-FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_is_local(spine_transform_constraint_data data, int isLocal);
+FFI_PLUGIN_EXPORT int32_t spine_transform_constraint_data_get_is_relative(spine_transform_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_is_relative(spine_transform_constraint_data data, int32_t isRelative);
+FFI_PLUGIN_EXPORT int32_t spine_transform_constraint_data_get_is_local(spine_transform_constraint_data data);
+FFI_PLUGIN_EXPORT void spine_transform_constraint_data_set_is_local(spine_transform_constraint_data data, int32_t isLocal);
 
 FFI_PLUGIN_EXPORT void spine_transform_constraint_update(spine_transform_constraint constraint);
-FFI_PLUGIN_EXPORT int spine_transform_constraint_get_order(spine_transform_constraint constraint);
+FFI_PLUGIN_EXPORT int32_t spine_transform_constraint_get_order(spine_transform_constraint constraint);
 FFI_PLUGIN_EXPORT spine_transform_constraint_data spine_transform_constraint_get_data(spine_transform_constraint constraint);
-FFI_PLUGIN_EXPORT int spine_transform_constraint_get_num_bones(spine_transform_constraint constraint);
+FFI_PLUGIN_EXPORT int32_t spine_transform_constraint_get_num_bones(spine_transform_constraint constraint);
 FFI_PLUGIN_EXPORT spine_bone* spine_transform_constraint_get_bones(spine_transform_constraint constraint);
 FFI_PLUGIN_EXPORT spine_bone spine_transform_constraint_get_target(spine_transform_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_transform_constraint_set_target(spine_transform_constraint constraint, spine_bone target);
@@ -766,9 +759,9 @@ FFI_PLUGIN_EXPORT void spine_transform_constraint_set_mix_scale_y(spine_transfor
 FFI_PLUGIN_EXPORT float spine_transform_constraint_get_mix_shear_y(spine_transform_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_transform_constraint_set_mix_shear_y(spine_transform_constraint constraint, float mixShearY);
 FFI_PLUGIN_EXPORT float spine_transform_constraint_get_is_active(spine_transform_constraint constraint);
-FFI_PLUGIN_EXPORT void spine_transform_constraint_set_is_active(spine_transform_constraint constraint, int isActive);
+FFI_PLUGIN_EXPORT void spine_transform_constraint_set_is_active(spine_transform_constraint constraint, int32_t isActive);
 
-FFI_PLUGIN_EXPORT int spine_path_constraint_data_get_num_bones(spine_path_constraint_data data);
+FFI_PLUGIN_EXPORT int32_t spine_path_constraint_data_get_num_bones(spine_path_constraint_data data);
 FFI_PLUGIN_EXPORT spine_bone_data* spine_path_constraint_data_get_bones(spine_path_constraint_data data);
 FFI_PLUGIN_EXPORT spine_slot_data spine_path_constraint_data_get_target(spine_path_constraint_data data);
 FFI_PLUGIN_EXPORT void spine_path_constraint_data_set_target(spine_path_constraint_data data, spine_slot_data target);
@@ -792,9 +785,9 @@ FFI_PLUGIN_EXPORT float spine_path_constraint_data_get_mix_y(spine_path_constrai
 FFI_PLUGIN_EXPORT void spine_path_constraint_data_set_mix_y(spine_path_constraint_data data, float mixY);
 
 FFI_PLUGIN_EXPORT void spine_path_constraint_update(spine_path_constraint constraint);
-FFI_PLUGIN_EXPORT int spine_path_constraint_get_order(spine_path_constraint constraint);
+FFI_PLUGIN_EXPORT int32_t spine_path_constraint_get_order(spine_path_constraint constraint);
 FFI_PLUGIN_EXPORT spine_path_constraint_data spine_path_constraint_get_data(spine_path_constraint constraint);
-FFI_PLUGIN_EXPORT int spine_path_constraint_get_num_bones(spine_path_constraint constraint);
+FFI_PLUGIN_EXPORT int32_t spine_path_constraint_get_num_bones(spine_path_constraint constraint);
 FFI_PLUGIN_EXPORT spine_bone* spine_path_constraint_get_bones(spine_path_constraint constraint);
 FFI_PLUGIN_EXPORT spine_slot spine_path_constraint_get_target(spine_path_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_path_constraint_set_target(spine_path_constraint constraint, spine_slot target);
@@ -808,21 +801,21 @@ FFI_PLUGIN_EXPORT float spine_path_constraint_get_mix_x(spine_path_constraint co
 FFI_PLUGIN_EXPORT void spine_path_constraint_set_mix_x(spine_path_constraint constraint, float mixX);
 FFI_PLUGIN_EXPORT float spine_path_constraint_get_mix_y(spine_path_constraint constraint);
 FFI_PLUGIN_EXPORT void spine_path_constraint_set_mix_y(spine_path_constraint constraint, float mixY);
-FFI_PLUGIN_EXPORT int spine_path_constraint_get_is_active(spine_path_constraint constraint);
-FFI_PLUGIN_EXPORT void spine_path_constraint_set_is_active(spine_path_constraint constraint, int isActive);
+FFI_PLUGIN_EXPORT int32_t spine_path_constraint_get_is_active(spine_path_constraint constraint);
+FFI_PLUGIN_EXPORT void spine_path_constraint_set_is_active(spine_path_constraint constraint, int32_t isActive);
 
 // OMITTED copy()
 FFI_PLUGIN_EXPORT void spine_sequence_apply(spine_sequence sequence, spine_slot slot, spine_attachment attachment);
-FFI_PLUGIN_EXPORT const char* spine_sequence_get_path(spine_sequence sequence, const char *basePath, int index);
-FFI_PLUGIN_EXPORT int spine_sequence_get_id(spine_sequence sequence);
-FFI_PLUGIN_EXPORT void spine_sequence_set_id(spine_sequence sequence, int id);
-FFI_PLUGIN_EXPORT int spine_sequence_get_start(spine_sequence sequence);
-FFI_PLUGIN_EXPORT void spine_sequence_set_start(spine_sequence sequence, int start);
-FFI_PLUGIN_EXPORT int spine_sequence_get_digits(spine_sequence sequence);
-FFI_PLUGIN_EXPORT void spine_sequence_set_digits(spine_sequence sequence, int digits);
-FFI_PLUGIN_EXPORT int spine_sequence_get_setup_index(spine_sequence sequence);
-FFI_PLUGIN_EXPORT void spine_sequence_set_setup_index(spine_sequence sequence, int setupIndex);
-FFI_PLUGIN_EXPORT int spine_sequence_get_num_regions(spine_sequence sequence);
+FFI_PLUGIN_EXPORT const utf8* spine_sequence_get_path(spine_sequence sequence, const utf8 *basePath, int32_t index);
+FFI_PLUGIN_EXPORT int32_t spine_sequence_get_id(spine_sequence sequence);
+FFI_PLUGIN_EXPORT void spine_sequence_set_id(spine_sequence sequence, int32_t id);
+FFI_PLUGIN_EXPORT int32_t spine_sequence_get_start(spine_sequence sequence);
+FFI_PLUGIN_EXPORT void spine_sequence_set_start(spine_sequence sequence, int32_t start);
+FFI_PLUGIN_EXPORT int32_t spine_sequence_get_digits(spine_sequence sequence);
+FFI_PLUGIN_EXPORT void spine_sequence_set_digits(spine_sequence sequence, int32_t digits);
+FFI_PLUGIN_EXPORT int32_t spine_sequence_get_setup_index(spine_sequence sequence);
+FFI_PLUGIN_EXPORT void spine_sequence_set_setup_index(spine_sequence sequence, int32_t setupIndex);
+FFI_PLUGIN_EXPORT int32_t spine_sequence_get_num_regions(spine_sequence sequence);
 FFI_PLUGIN_EXPORT spine_texture_region* spine_sequence_get_regions(spine_sequence sequence);
 
 FFI_PLUGIN_EXPORT void* spine_texture_region_get_texture(spine_texture_region textureRegion);
@@ -835,19 +828,19 @@ FFI_PLUGIN_EXPORT float spine_texture_region_get_u2(spine_texture_region texture
 FFI_PLUGIN_EXPORT void spine_texture_region_set_u2(spine_texture_region textureRegion, float u2);
 FFI_PLUGIN_EXPORT float spine_texture_region_get_v2(spine_texture_region textureRegion);
 FFI_PLUGIN_EXPORT void spine_texture_region_set_v2(spine_texture_region textureRegion, float v2);
-FFI_PLUGIN_EXPORT int spine_texture_region_get_degrees(spine_texture_region textureRegion);
-FFI_PLUGIN_EXPORT void spine_texture_region_set_degrees(spine_texture_region textureRegion, int degrees);
+FFI_PLUGIN_EXPORT int32_t spine_texture_region_get_degrees(spine_texture_region textureRegion);
+FFI_PLUGIN_EXPORT void spine_texture_region_set_degrees(spine_texture_region textureRegion, int32_t degrees);
 FFI_PLUGIN_EXPORT float spine_texture_region_get_offset_x(spine_texture_region textureRegion);
 FFI_PLUGIN_EXPORT void spine_texture_region_set_offset_x(spine_texture_region textureRegion, float offsetX);
 FFI_PLUGIN_EXPORT float spine_texture_region_get_offset_y(spine_texture_region textureRegion);
 FFI_PLUGIN_EXPORT void spine_texture_region_set_offset_y(spine_texture_region textureRegion, float offsetY);
-FFI_PLUGIN_EXPORT int spine_texture_region_get_width(spine_texture_region textureRegion);
-FFI_PLUGIN_EXPORT void spine_texture_region_set_width(spine_texture_region textureRegion, int width);
-FFI_PLUGIN_EXPORT int spine_texture_region_get_height(spine_texture_region textureRegion);
-FFI_PLUGIN_EXPORT void spine_texture_region_set_height(spine_texture_region textureRegion, int height);
-FFI_PLUGIN_EXPORT int spine_texture_region_get_original_width(spine_texture_region textureRegion);
-FFI_PLUGIN_EXPORT void spine_texture_region_set_original_width(spine_texture_region textureRegion, int originalWidth);
-FFI_PLUGIN_EXPORT int spine_texture_region_get_original_height(spine_texture_region textureRegion);
-FFI_PLUGIN_EXPORT void spine_texture_region_set_original_height(spine_texture_region textureRegion, int originalHeight);
+FFI_PLUGIN_EXPORT int32_t spine_texture_region_get_width(spine_texture_region textureRegion);
+FFI_PLUGIN_EXPORT void spine_texture_region_set_width(spine_texture_region textureRegion, int32_t width);
+FFI_PLUGIN_EXPORT int32_t spine_texture_region_get_height(spine_texture_region textureRegion);
+FFI_PLUGIN_EXPORT void spine_texture_region_set_height(spine_texture_region textureRegion, int32_t height);
+FFI_PLUGIN_EXPORT int32_t spine_texture_region_get_original_width(spine_texture_region textureRegion);
+FFI_PLUGIN_EXPORT void spine_texture_region_set_original_width(spine_texture_region textureRegion, int32_t originalWidth);
+FFI_PLUGIN_EXPORT int32_t spine_texture_region_get_original_height(spine_texture_region textureRegion);
+FFI_PLUGIN_EXPORT void spine_texture_region_set_original_height(spine_texture_region textureRegion, int32_t originalHeight);
 
 #endif

Some files were not shown because too many files changed in this diff