瀏覽代碼

[flutter] Wrapper and binding generator complete.

Mario Zechner 1 月之前
父節點
當前提交
5c33aed9d6
共有 100 個文件被更改,包括 18316 次插入22 次删除
  1. 3 0
      spine-flutter/.gitignore
  2. 68 0
      spine-flutter/codegen/README.md
  3. 11 0
      spine-flutter/codegen/biome.json
  4. 861 0
      spine-flutter/codegen/package-lock.json
  5. 13 0
      spine-flutter/codegen/package.json
  6. 998 0
      spine-flutter/codegen/src/dart-writer.ts
  7. 132 0
      spine-flutter/codegen/src/index.ts
  8. 17 0
      spine-flutter/codegen/tsconfig.json
  9. 24 0
      spine-flutter/codegen/tsfmt.json
  10. 0 21
      spine-flutter/ffigen.yaml
  11. 20 0
      spine-flutter/generate-bindings.sh
  12. 911 0
      spine-flutter/generator.md
  13. 4288 0
      spine-flutter/lib/extensions.dart
  14. 1 1
      spine-flutter/lib/ffi_utf8.dart
  15. 162 0
      spine-flutter/lib/generated/alpha_timeline.dart
  16. 110 0
      spine-flutter/lib/generated/animation.dart
  17. 160 0
      spine-flutter/lib/generated/animation_state.dart
  18. 92 0
      spine-flutter/lib/generated/animation_state_data.dart
  19. 787 0
      spine-flutter/lib/generated/arrays.dart
  20. 72 0
      spine-flutter/lib/generated/atlas.dart
  21. 104 0
      spine-flutter/lib/generated/atlas_attachment_loader.dart
  22. 161 0
      spine-flutter/lib/generated/atlas_page.dart
  23. 265 0
      spine-flutter/lib/generated/atlas_region.dart
  24. 88 0
      spine-flutter/lib/generated/attachment.dart
  25. 92 0
      spine-flutter/lib/generated/attachment_loader.dart
  26. 116 0
      spine-flutter/lib/generated/attachment_timeline.dart
  27. 51 0
      spine-flutter/lib/generated/attachment_type.dart
  28. 48 0
      spine-flutter/lib/generated/blend_mode.dart
  29. 140 0
      spine-flutter/lib/generated/bone.dart
  30. 122 0
      spine-flutter/lib/generated/bone_data.dart
  31. 147 0
      spine-flutter/lib/generated/bone_local.dart
  32. 277 0
      spine-flutter/lib/generated/bone_pose.dart
  33. 73 0
      spine-flutter/lib/generated/bone_timeline.dart
  34. 157 0
      spine-flutter/lib/generated/bone_timeline1.dart
  35. 137 0
      spine-flutter/lib/generated/bone_timeline2.dart
  36. 153 0
      spine-flutter/lib/generated/bounding_box_attachment.dart
  37. 163 0
      spine-flutter/lib/generated/clipping_attachment.dart
  38. 148 0
      spine-flutter/lib/generated/color.dart
  39. 85 0
      spine-flutter/lib/generated/constraint.dart
  40. 82 0
      spine-flutter/lib/generated/constraint_data.dart
  41. 73 0
      spine-flutter/lib/generated/constraint_timeline.dart
  42. 157 0
      spine-flutter/lib/generated/constraint_timeline1.dart
  43. 119 0
      spine-flutter/lib/generated/curve_timeline.dart
  44. 148 0
      spine-flutter/lib/generated/curve_timeline1.dart
  45. 128 0
      spine-flutter/lib/generated/curve_timeline2.dart
  46. 152 0
      spine-flutter/lib/generated/deform_timeline.dart
  47. 106 0
      spine-flutter/lib/generated/draw_order_timeline.dart
  48. 115 0
      spine-flutter/lib/generated/event.dart
  49. 118 0
      spine-flutter/lib/generated/event_data.dart
  50. 88 0
      spine-flutter/lib/generated/event_queue_entry.dart
  51. 112 0
      spine-flutter/lib/generated/event_timeline.dart
  52. 50 0
      spine-flutter/lib/generated/event_type.dart
  53. 51 0
      spine-flutter/lib/generated/format.dart
  54. 83 0
      spine-flutter/lib/generated/from_property.dart
  55. 69 0
      spine-flutter/lib/generated/from_rotate.dart
  56. 69 0
      spine-flutter/lib/generated/from_scale_x.dart
  57. 69 0
      spine-flutter/lib/generated/from_scale_y.dart
  58. 69 0
      spine-flutter/lib/generated/from_shear_y.dart
  59. 69 0
      spine-flutter/lib/generated/from_x.dart
  60. 69 0
      spine-flutter/lib/generated/from_y.dart
  61. 153 0
      spine-flutter/lib/generated/ik_constraint.dart
  62. 122 0
      spine-flutter/lib/generated/ik_constraint_data.dart
  63. 107 0
      spine-flutter/lib/generated/ik_constraint_pose.dart
  64. 137 0
      spine-flutter/lib/generated/ik_constraint_timeline.dart
  65. 49 0
      spine-flutter/lib/generated/inherit.dart
  66. 116 0
      spine-flutter/lib/generated/inherit_timeline.dart
  67. 65 0
      spine-flutter/lib/generated/linked_mesh.dart
  68. 259 0
      spine-flutter/lib/generated/mesh_attachment.dart
  69. 48 0
      spine-flutter/lib/generated/mix_blend.dart
  70. 46 0
      spine-flutter/lib/generated/mix_direction.dart
  71. 180 0
      spine-flutter/lib/generated/path_attachment.dart
  72. 144 0
      spine-flutter/lib/generated/path_constraint.dart
  73. 152 0
      spine-flutter/lib/generated/path_constraint_data.dart
  74. 137 0
      spine-flutter/lib/generated/path_constraint_mix_timeline.dart
  75. 107 0
      spine-flutter/lib/generated/path_constraint_pose.dart
  76. 162 0
      spine-flutter/lib/generated/path_constraint_position_timeline.dart
  77. 162 0
      spine-flutter/lib/generated/path_constraint_spacing_timeline.dart
  78. 48 0
      spine-flutter/lib/generated/physics.dart
  79. 150 0
      spine-flutter/lib/generated/physics_constraint.dart
  80. 162 0
      spine-flutter/lib/generated/physics_constraint_damping_timeline.dart
  81. 233 0
      spine-flutter/lib/generated/physics_constraint_data.dart
  82. 162 0
      spine-flutter/lib/generated/physics_constraint_gravity_timeline.dart
  83. 162 0
      spine-flutter/lib/generated/physics_constraint_inertia_timeline.dart
  84. 162 0
      spine-flutter/lib/generated/physics_constraint_mass_timeline.dart
  85. 162 0
      spine-flutter/lib/generated/physics_constraint_mix_timeline.dart
  86. 125 0
      spine-flutter/lib/generated/physics_constraint_pose.dart
  87. 115 0
      spine-flutter/lib/generated/physics_constraint_reset_timeline.dart
  88. 162 0
      spine-flutter/lib/generated/physics_constraint_strength_timeline.dart
  89. 157 0
      spine-flutter/lib/generated/physics_constraint_timeline.dart
  90. 162 0
      spine-flutter/lib/generated/physics_constraint_wind_timeline.dart
  91. 133 0
      spine-flutter/lib/generated/point_attachment.dart
  92. 77 0
      spine-flutter/lib/generated/polygon.dart
  93. 66 0
      spine-flutter/lib/generated/posed.dart
  94. 62 0
      spine-flutter/lib/generated/posed_active.dart
  95. 73 0
      spine-flutter/lib/generated/posed_data.dart
  96. 46 0
      spine-flutter/lib/generated/position_mode.dart
  97. 75 0
      spine-flutter/lib/generated/property.dart
  98. 212 0
      spine-flutter/lib/generated/region_attachment.dart
  99. 74 0
      spine-flutter/lib/generated/render_command.dart
  100. 137 0
      spine-flutter/lib/generated/rgb2_timeline.dart

+ 3 - 0
spine-flutter/.gitignore

@@ -28,3 +28,6 @@ migrate_working_dir/
 .dart_tool/
 .packages
 build/
+ios/Classes/spine-c
+macos/Classes/spine-c
+src/spine-c

+ 68 - 0
spine-flutter/codegen/README.md

@@ -0,0 +1,68 @@
+# spine-flutter Code Generator
+
+This directory contains the TypeScript-based code generator that automatically creates Dart wrapper classes for the spine-flutter runtime.
+
+## Overview
+
+The generator:
+1. Reuses spine-c's C++ type extraction and IR generation
+2. Generates clean, type-safe Dart wrapper classes
+3. Creates a native Dart API over the raw FFI bindings
+
+## Architecture
+
+```
+spine-cpp (C++ source)
+    ↓ (spine-c type extraction)
+C++ Type Information
+    ↓ (spine-c IR generation)  
+C Intermediate Representation
+    ↓ (dart-generator.ts)
+Dart Wrapper Classes
+```
+
+## Setup
+
+```bash
+# Install dependencies
+npm install
+
+# Build the generator
+npm run build
+```
+
+## Usage
+
+```bash
+# Generate Dart wrapper classes
+npm run generate
+```
+
+This will:
+1. Extract types from spine-cpp headers
+2. Generate C intermediate representation
+3. Create Dart wrapper classes in `lib/src/generated/`
+
+## Generated Files
+
+- `lib/src/generated/` - Contains all generated wrapper classes
+- `lib/src/generated/array.dart` - Generic Array<T> implementation
+- `lib/src/generated/*.dart` - Individual wrapper classes for each Spine type
+- `lib/spine_flutter.dart` - Main export file
+
+## Development
+
+To watch for changes during development:
+```bash
+npm run watch
+```
+
+## Integration
+
+After generating the Dart wrappers, run ffigen to generate the raw FFI bindings:
+```bash
+cd ../..
+./generate_bindings.sh
+```
+
+The generated Dart wrappers depend on the FFI bindings generated by ffigen.

+ 11 - 0
spine-flutter/codegen/biome.json

@@ -0,0 +1,11 @@
+{
+	"formatter": {
+		"enabled": false
+	},
+	"linter": {
+		"enabled": true,
+		"rules": {
+			"recommended": true
+		}
+	}
+}

+ 861 - 0
spine-flutter/codegen/package-lock.json

@@ -0,0 +1,861 @@
+{
+  "name": "spine-flutter-codegen",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "spine-flutter-codegen",
+      "dependencies": {
+        "spine-c-codegen": "file:../../spine-c/codegen"
+      },
+      "devDependencies": {
+        "@biomejs/biome": "^2.1.1",
+        "@types/node": "^20.0.0",
+        "tsx": "^4.0.0",
+        "typescript-formatter": "^7.2.2"
+      }
+    },
+    "../../spine-c/codegen": {
+      "name": "spine-c-codegen",
+      "devDependencies": {
+        "@biomejs/biome": "^2.1.1",
+        "@types/node": "^20.0.0",
+        "tsx": "^4.0.0",
+        "typescript-formatter": "^7.2.2"
+      }
+    },
+    "node_modules/@biomejs/biome": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.1.2.tgz",
+      "integrity": "sha512-yq8ZZuKuBVDgAS76LWCfFKHSYIAgqkxVB3mGVVpOe2vSkUTs7xG46zXZeNPRNVjiJuw0SZ3+J2rXiYx0RUpfGg==",
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "bin": {
+        "biome": "bin/biome"
+      },
+      "engines": {
+        "node": ">=14.21.3"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/biome"
+      },
+      "optionalDependencies": {
+        "@biomejs/cli-darwin-arm64": "2.1.2",
+        "@biomejs/cli-darwin-x64": "2.1.2",
+        "@biomejs/cli-linux-arm64": "2.1.2",
+        "@biomejs/cli-linux-arm64-musl": "2.1.2",
+        "@biomejs/cli-linux-x64": "2.1.2",
+        "@biomejs/cli-linux-x64-musl": "2.1.2",
+        "@biomejs/cli-win32-arm64": "2.1.2",
+        "@biomejs/cli-win32-x64": "2.1.2"
+      }
+    },
+    "node_modules/@biomejs/cli-darwin-arm64": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.1.2.tgz",
+      "integrity": "sha512-leFAks64PEIjc7MY/cLjE8u5OcfBKkcDB0szxsWUB4aDfemBep1WVKt0qrEyqZBOW8LPHzrFMyDl3FhuuA0E7g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-darwin-x64": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.1.2.tgz",
+      "integrity": "sha512-Nmmv7wRX5Nj7lGmz0FjnWdflJg4zii8Ivruas6PBKzw5SJX/q+Zh2RfnO+bBnuKLXpj8kiI2x2X12otpH6a32A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-linux-arm64": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.1.2.tgz",
+      "integrity": "sha512-NWNy2Diocav61HZiv2enTQykbPP/KrA/baS7JsLSojC7Xxh2nl9IczuvE5UID7+ksRy2e7yH7klm/WkA72G1dw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-linux-arm64-musl": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.1.2.tgz",
+      "integrity": "sha512-qgHvafhjH7Oca114FdOScmIKf1DlXT1LqbOrrbR30kQDLFPEOpBG0uzx6MhmsrmhGiCFCr2obDamu+czk+X0HQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-linux-x64": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.1.2.tgz",
+      "integrity": "sha512-Km/UYeVowygTjpX6sGBzlizjakLoMQkxWbruVZSNE6osuSI63i4uCeIL+6q2AJlD3dxoiBJX70dn1enjQnQqwA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-linux-x64-musl": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.1.2.tgz",
+      "integrity": "sha512-xlB3mU14ZUa3wzLtXfmk2IMOGL+S0aHFhSix/nssWS/2XlD27q+S6f0dlQ8WOCbYoXcuz8BCM7rCn2lxdTrlQA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-win32-arm64": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.1.2.tgz",
+      "integrity": "sha512-G8KWZli5ASOXA3yUQgx+M4pZRv3ND16h77UsdunUL17uYpcL/UC7RkWTdkfvMQvogVsAuz5JUcBDjgZHXxlKoA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@biomejs/cli-win32-x64": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.1.2.tgz",
+      "integrity": "sha512-9zajnk59PMpjBkty3bK2IrjUsUHvqe9HWwyAWQBjGLE7MIBjbX2vwv1XPEhmO2RRuGoTkVx3WCanHrjAytICLA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT OR Apache-2.0",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=14.21.3"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz",
+      "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz",
+      "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz",
+      "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz",
+      "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz",
+      "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz",
+      "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz",
+      "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz",
+      "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz",
+      "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz",
+      "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz",
+      "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz",
+      "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz",
+      "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz",
+      "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz",
+      "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz",
+      "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz",
+      "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz",
+      "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz",
+      "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz",
+      "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz",
+      "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openharmony-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz",
+      "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz",
+      "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz",
+      "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz",
+      "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz",
+      "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@types/node": {
+      "version": "20.19.9",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz",
+      "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "undici-types": "~6.21.0"
+      }
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/commandpost": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz",
+      "integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/editorconfig": {
+      "version": "0.15.3",
+      "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
+      "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "commander": "^2.19.0",
+        "lru-cache": "^4.1.5",
+        "semver": "^5.6.0",
+        "sigmund": "^1.0.1"
+      },
+      "bin": {
+        "editorconfig": "bin/editorconfig"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.25.8",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz",
+      "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.25.8",
+        "@esbuild/android-arm": "0.25.8",
+        "@esbuild/android-arm64": "0.25.8",
+        "@esbuild/android-x64": "0.25.8",
+        "@esbuild/darwin-arm64": "0.25.8",
+        "@esbuild/darwin-x64": "0.25.8",
+        "@esbuild/freebsd-arm64": "0.25.8",
+        "@esbuild/freebsd-x64": "0.25.8",
+        "@esbuild/linux-arm": "0.25.8",
+        "@esbuild/linux-arm64": "0.25.8",
+        "@esbuild/linux-ia32": "0.25.8",
+        "@esbuild/linux-loong64": "0.25.8",
+        "@esbuild/linux-mips64el": "0.25.8",
+        "@esbuild/linux-ppc64": "0.25.8",
+        "@esbuild/linux-riscv64": "0.25.8",
+        "@esbuild/linux-s390x": "0.25.8",
+        "@esbuild/linux-x64": "0.25.8",
+        "@esbuild/netbsd-arm64": "0.25.8",
+        "@esbuild/netbsd-x64": "0.25.8",
+        "@esbuild/openbsd-arm64": "0.25.8",
+        "@esbuild/openbsd-x64": "0.25.8",
+        "@esbuild/openharmony-arm64": "0.25.8",
+        "@esbuild/sunos-x64": "0.25.8",
+        "@esbuild/win32-arm64": "0.25.8",
+        "@esbuild/win32-ia32": "0.25.8",
+        "@esbuild/win32-x64": "0.25.8"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/get-tsconfig": {
+      "version": "4.10.1",
+      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
+      "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "resolve-pkg-maps": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "node_modules/pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+      }
+    },
+    "node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/sigmund": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
+      "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/spine-c-codegen": {
+      "resolved": "../../spine-c/codegen",
+      "link": true
+    },
+    "node_modules/tsx": {
+      "version": "4.20.3",
+      "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz",
+      "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "~0.25.0",
+        "get-tsconfig": "^4.7.5"
+      },
+      "bin": {
+        "tsx": "dist/cli.mjs"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "peer": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/typescript-formatter": {
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz",
+      "integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "commandpost": "^1.0.0",
+        "editorconfig": "^0.15.0"
+      },
+      "bin": {
+        "tsfmt": "bin/tsfmt"
+      },
+      "engines": {
+        "node": ">= 4.2.0"
+      },
+      "peerDependencies": {
+        "typescript": "^2.1.6 || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "6.21.0",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
+      "dev": true,
+      "license": "ISC"
+    }
+  }
+}

+ 13 - 0
spine-flutter/codegen/package.json

@@ -0,0 +1,13 @@
+{
+  "name": "spine-flutter-codegen",
+  "type": "module",
+  "dependencies": {
+    "spine-c-codegen": "file:../../spine-c/codegen"
+  },
+  "devDependencies": {
+    "@types/node": "^20.0.0",
+    "tsx": "^4.0.0",
+    "typescript-formatter": "^7.2.2",
+    "@biomejs/biome": "^2.1.1"
+  }
+}

+ 998 - 0
spine-flutter/codegen/src/dart-writer.ts

@@ -0,0 +1,998 @@
+import * as fs from 'node:fs';
+import * as path from 'node:path';
+import type { CClassOrStruct, CEnum, CMethod, CParameter } from '../../../spine-c/codegen/src/c-types.js';
+import { toSnakeCase } from '../../../spine-c/codegen/src/types.js';
+
+const LICENSE_HEADER = `// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/`;
+
+/** Generates Dart wrapper files from C intermediate representation */
+export class DartWriter {
+    private enumNames = new Set<string>();
+
+    constructor(private outputDir: string) {
+        this.cleanOutputDirectory();
+    }
+
+    private cleanOutputDirectory(): void {
+        if (fs.existsSync(this.outputDir)) {
+            console.log(`Cleaning ${this.outputDir}...`);
+            fs.rmSync(this.outputDir, { recursive: true, force: true });
+        }
+        fs.mkdirSync(this.outputDir, { recursive: true });
+    }
+
+    async writeAll(cTypes: CClassOrStruct[], cEnums: CEnum[], cArrayTypes: CClassOrStruct[]): Promise<void> {
+        // Collect enum names first
+        for (const cEnum of cEnums) {
+            this.enumNames.add(cEnum.name);
+        }
+
+        // Write enums
+        for (const cEnum of cEnums) {
+            await this.writeEnum(cEnum);
+        }
+
+        // Write wrapper classes
+        for (const cType of cTypes) {
+            await this.writeClass(cType);
+        }
+
+        // Write all array specializations in a single file
+        await this.writeArrays(cArrayTypes);
+
+        // Write main export file
+        await this.writeExportFile(cTypes, cEnums, cArrayTypes);
+    }
+
+
+    private async writeEnum(cEnum: CEnum): Promise<void> {
+        const lines: string[] = [];
+        const dartName = this.toDartTypeName(cEnum.name);
+
+        lines.push(LICENSE_HEADER);
+        lines.push('');
+        lines.push('// AUTO GENERATED FILE, DO NOT EDIT.');
+        lines.push('');
+        lines.push(`/// ${dartName} enum`);
+        lines.push(`enum ${dartName} {`);
+
+        // Write enum values
+        for (let i = 0; i < cEnum.values.length; i++) {
+            const value = cEnum.values[i];
+            const dartValueName = this.toDartEnumValueName(value.name, cEnum.name);
+            const comma = i < cEnum.values.length - 1 ? ',' : ';';
+
+            if (value.value !== undefined) {
+                lines.push(`  ${dartValueName}(${value.value})${comma}`);
+            } else {
+                lines.push(`  ${dartValueName}(${i})${comma}`);
+            }
+        }
+
+        lines.push('');
+        lines.push(`  const ${dartName}(this.value);`);
+        lines.push('  final int value;');
+        lines.push('');
+        lines.push(`  static ${dartName} fromValue(int value) {`);
+        lines.push('    return values.firstWhere(');
+        lines.push('      (e) => e.value == value,');
+        lines.push(`      orElse: () => throw ArgumentError('Invalid ${dartName} value: \$value'),`);
+        lines.push('    );');
+        lines.push('  }');
+        lines.push('}');
+
+        const fileName = `${toSnakeCase(dartName)}.dart`;
+        const filePath = path.join(this.outputDir, fileName);
+        fs.writeFileSync(filePath, lines.join('\n'));
+    }
+
+    private async writeClass(cType: CClassOrStruct): Promise<void> {
+        const lines: string[] = [];
+        const dartClassName = this.toDartTypeName(cType.name);
+
+        lines.push(LICENSE_HEADER);
+        lines.push('');
+        lines.push('// AUTO GENERATED FILE, DO NOT EDIT.');
+        lines.push('');
+        lines.push("import 'dart:ffi';");
+        
+        // Check if we need package:ffi for string conversions
+        const needsPackageFfi = this.needsStringConversions(cType);
+        if (needsPackageFfi) {
+            lines.push("import 'package:ffi/ffi.dart';");
+        }
+        
+        lines.push("import 'spine_flutter_bindings_generated.dart';");
+
+        // Check if this class has an rtti method
+        const hasRttiMethod = cType.methods.some(m => m.name === `${cType.name}_rtti` && m.parameters.length === 0);
+        if (hasRttiMethod) {
+            lines.push("import 'rtti.dart';");
+        }
+
+        // Collect all imports needed (arrays, enums, and other types)
+        const allImports = this.collectAllImports(cType);
+        for (const importFile of allImports) {
+            // Skip rtti.dart if we already added it above
+            if (importFile === 'rtti.dart' && hasRttiMethod) {
+                continue;
+            }
+            lines.push(`import '${importFile}';`);
+        }
+
+        lines.push('');
+        lines.push(`/// ${dartClassName} wrapper`);
+        lines.push(`class ${dartClassName} implements Finalizable {`);
+        lines.push('  static late SpineFlutterBindings _bindings;');
+        lines.push(`  final Pointer<${cType.name}_wrapper> _ptr;`);
+        lines.push('');
+        lines.push('  /// Initialize the bindings for all spine-flutter classes');
+        lines.push('  static void init(SpineFlutterBindings bindings) {');
+        lines.push('    _bindings = bindings;');
+        lines.push('  }');
+        lines.push('');
+
+        // Constructor from pointer
+        lines.push(`  ${dartClassName}.fromPointer(this._ptr);`);
+        lines.push('');
+        lines.push('  /// Get the native pointer for FFI calls');
+        lines.push('  Pointer get nativePtr => _ptr;');
+        lines.push('');
+
+        // Write constructors
+        for (const constr of cType.constructors) {
+            lines.push(this.writeConstructor(dartClassName, constr, cType));
+            lines.push('');
+        }
+
+        // Filter out methods with raw pointer parameters
+        const validMethods = cType.methods.filter(method => {
+            if (this.hasRawPointerParameters(method)) {
+                console.log(`  Skipping method ${cType.name}::${method.name}: has raw pointer parameters`);
+                return false;
+            }
+            return true;
+        });
+
+        // Renumber methods that need it
+        const renumberedMethods = this.renumberMethods(validMethods, cType.name);
+
+        // Write methods
+        for (const methodInfo of renumberedMethods) {
+            const { method, renamedMethod } = methodInfo;
+            
+            // Special case: SlotPose hasDarkColor should be a getter
+            if (cType.name === 'spine_slot_pose' && method.name === 'spine_slot_pose_has_dark_color') {
+                lines.push(this.writeGetter(cType, method, 'hasDarkColor'));
+            } else if (this.isGetter(method)) {
+                lines.push(this.writeGetter(cType, method, renamedMethod));
+            } else if (this.isSetter(method)) {
+                lines.push(this.writeSetter(cType, method, renamedMethod));
+            } else {
+                lines.push(this.writeMethod(cType, method, renamedMethod));
+            }
+            lines.push('');
+        }
+
+        // Write dispose method if destructor exists
+        if (cType.destructor) {
+            lines.push('  void dispose() {');
+            lines.push(`    _bindings.${cType.destructor.name}(_ptr);`);
+            lines.push('  }');
+        }
+
+        lines.push('}');
+
+        const fileName = `${toSnakeCase(dartClassName)}.dart`;
+        const filePath = path.join(this.outputDir, fileName);
+        fs.writeFileSync(filePath, lines.join('\n'));
+    }
+
+    private async writeArrays(cArrayTypes: CClassOrStruct[]): Promise<void> {
+        const lines: string[] = [];
+        
+        lines.push(LICENSE_HEADER);
+        lines.push('');
+        lines.push('// AUTO GENERATED FILE, DO NOT EDIT.');
+        lines.push('');
+        lines.push("import 'dart:ffi';");
+        lines.push("import 'spine_flutter_bindings_generated.dart';");
+        lines.push("import '../native_array.dart';");
+        
+        // Collect all imports needed for all array types
+        const imports = new Set<string>();
+        for (const arrayType of cArrayTypes) {
+            const elementType = this.extractArrayElementType(arrayType.name);
+            if (!this.isPrimitive(elementType) && !['int', 'float', 'bool', 'unsigned_short', 'property_id'].includes(elementType.toLowerCase())) {
+                imports.add(`import '${toSnakeCase(elementType)}.dart';`);
+            }
+        }
+        
+        // Add sorted imports
+        for (const imp of Array.from(imports).sort()) {
+            lines.push(imp);
+        }
+        
+        // Generate each array class
+        for (const arrayType of cArrayTypes) {
+            lines.push('');
+            lines.push(...this.generateArrayClass(arrayType));
+        }
+        
+        const filePath = path.join(this.outputDir, 'arrays.dart');
+        fs.writeFileSync(filePath, lines.join('\n'));
+    }
+    
+    private generateArrayClass(arrayType: CClassOrStruct): string[] {
+        const lines: string[] = [];
+        const dartClassName = this.toDartTypeName(arrayType.name);
+        const elementType = this.extractArrayElementType(arrayType.name);
+        
+
+        lines.push(`/// Array of ${elementType} elements`);
+        lines.push(`class ${dartClassName} extends NativeArray<${this.toDartElementType(elementType)}> {`);
+        lines.push('  static late SpineFlutterBindings _bindings;');
+        lines.push('');
+        lines.push('  /// Initialize the bindings for all spine-flutter classes');
+        lines.push('  static void init(SpineFlutterBindings bindings) {');
+        lines.push('    _bindings = bindings;');
+        lines.push('  }');
+        lines.push('');
+        // Generate typed constructor - arrays use the array wrapper type
+        const arrayWrapperType = `${arrayType.name}_wrapper`;
+        lines.push(`  ${dartClassName}.fromPointer(Pointer<${arrayWrapperType}> super.ptr);`);
+        lines.push('');
+
+        // Find size and buffer methods
+        const sizeMethod = arrayType.methods.find(m => m.name.endsWith('_size') && !m.name.endsWith('_set_size'));
+        const bufferMethod = arrayType.methods.find(m => m.name.endsWith('_buffer'));
+        const setMethod = arrayType.methods.find(m => m.name.endsWith('_set') && m.parameters.length === 3); // self, index, value
+
+        if (sizeMethod) {
+            lines.push('  @override');
+            lines.push('  int get length {');
+            lines.push(`    return _bindings.${sizeMethod.name}(nativePtr.cast());`);
+            lines.push('  }');
+            lines.push('');
+        }
+
+        if (bufferMethod) {
+            lines.push('  @override');
+            lines.push(`  ${this.toDartElementType(elementType)} operator [](int index) {`);
+            lines.push('    if (index < 0 || index >= length) {');
+            lines.push('      throw RangeError.index(index, this, \'index\');');
+            lines.push('    }');
+            
+            lines.push(`    final buffer = _bindings.${bufferMethod.name}(nativePtr.cast());`);
+
+            // Handle different element types
+            if (elementType === 'int') {
+                lines.push('    return buffer.cast<Int32>()[index];');
+            } else if (elementType === 'float') {
+                lines.push('    return buffer.cast<Float>()[index];');
+            } else if (elementType === 'bool') {
+                lines.push('    return buffer.cast<Int32>()[index] != 0;');
+            } else if (elementType === 'unsigned_short') {
+                lines.push('    return buffer.cast<Uint16>()[index];');
+            } else if (elementType === 'property_id') {
+                // PropertyId buffer returns int instead of Pointer<Int64> due to C codegen bug
+                // This will cause a compile error, but it's a known issue with the C API
+                lines.push('    // NOTE: This will not compile due to C API bug - buffer() returns int instead of Pointer');
+                lines.push('    return buffer.cast<Int64>()[index];');
+            } else {
+                // For object types, the buffer contains pointers
+                const dartElementType = this.toDartTypeName(`spine_${toSnakeCase(elementType)}`);
+                lines.push(`    return ${dartElementType}.fromPointer(buffer[index]);`);
+            }
+
+            lines.push('  }');
+            lines.push('');
+        }
+
+        // Override []= if there's a set method
+        if (setMethod) {
+            lines.push('  @override');
+            lines.push(`  void operator []=(int index, ${this.toDartElementType(elementType)} value) {`);
+            lines.push('    if (index < 0 || index >= length) {');
+            lines.push('      throw RangeError.index(index, this, \'index\');');
+            lines.push('    }');
+            
+            // Convert value to C type
+            const param = setMethod.parameters[2]; // The value parameter
+            const convertedValue = this.convertDartToC('value', param);
+            lines.push(`    _bindings.${setMethod.name}(nativePtr.cast(), index, ${convertedValue});`);
+            lines.push('  }');
+        }
+
+        lines.push('}');
+        
+        return lines;
+    }
+
+    private async writeExportFile(cTypes: CClassOrStruct[], cEnums: CEnum[], cArrayTypes: CClassOrStruct[]): Promise<void> {
+        const lines: string[] = [];
+
+        lines.push(LICENSE_HEADER);
+        lines.push('');
+        lines.push('// AUTO GENERATED FILE, DO NOT EDIT.');
+        lines.push('');
+        lines.push('// Export all generated types');
+        lines.push('');
+
+
+        // Export enums
+        if (cEnums.length > 0) {
+            lines.push('// Enums');
+            for (const cEnum of cEnums) {
+                const dartName = this.toDartTypeName(cEnum.name);
+                lines.push(`export 'generated/${toSnakeCase(dartName)}.dart';`);
+            }
+            lines.push('');
+        }
+
+        // Export classes
+        if (cTypes.length > 0) {
+            lines.push('// Classes');
+            for (const cType of cTypes) {
+                const dartName = this.toDartTypeName(cType.name);
+                lines.push(`export 'generated/${toSnakeCase(dartName)}.dart';`);
+            }
+            lines.push('');
+        }
+        
+        // Export arrays
+        if (cArrayTypes.length > 0) {
+            lines.push('// Arrays');
+            lines.push(`export 'generated/arrays.dart';`);
+        }
+
+        const filePath = path.join(path.dirname(path.dirname(this.outputDir)), 'spine_flutter.dart');
+        fs.writeFileSync(filePath, lines.join('\n'));
+    }
+
+    // Helper methods
+
+    private writeConstructor(dartClassName: string, constr: CMethod, cType: CClassOrStruct): string {
+        const lines: string[] = [];
+
+        const params = constr.parameters.map(p => {
+            const dartType = this.toDartParameterType(p);
+            return `${dartType} ${p.name}`;
+        }).join(', ');
+
+        const args = constr.parameters.map(p => {
+            return this.convertDartToC(p.name, p);
+        }).join(', ');
+
+        // Determine constructor name suffix
+        const cTypeName = `spine_${toSnakeCase(dartClassName)}`;
+        let constructorName = constr.name.replace(`${cTypeName}_create`, '');
+
+        // Handle numeric suffixes and special cases
+        if (constructorName) {
+            // If it's just a number, handle it generically
+            if (/^\d+$/.test(constructorName)) {
+                // Special case for Color::create2 specifically
+                if (cType.name === 'spine_color' && constr.name === 'spine_color_create2') {
+                    constructorName = 'fromRGBA';
+                }
+                // For other numbered constructors, look at parameters to generate a name
+                else if (constr.parameters.length > 0) {
+                    // If first param is the same type as what we're constructing, it's likely a copy/from constructor
+                    const firstParamType = constr.parameters[0].cType.replace('*', '').trim();
+                    if (firstParamType === cType.name) {
+                        constructorName = 'from';
+                    } else {
+                        // Otherwise use a generic variant name
+                        constructorName = `variant${constructorName}`;
+                    }
+                } else {
+                    constructorName = `variant${constructorName}`;
+                }
+            } else if (constructorName.startsWith('_')) {
+                // Handle underscored names (e.g., create_with_data -> withData)
+                constructorName = this.toCamelCase(constructorName.slice(1));
+            }
+        }
+
+        const factoryName = constructorName ? `.${constructorName}` : '';
+
+        lines.push(`  factory ${dartClassName}${factoryName}(${params}) {`);
+        lines.push(`    final ptr = _bindings.${constr.name}(${args});`);
+        lines.push(`    return ${dartClassName}.fromPointer(ptr);`);
+        lines.push('  }');
+
+        return lines.join('\n');
+    }
+
+    private writeMethod(cType: CClassOrStruct, method: CMethod, renamedMethod?: string): string {
+        const lines: string[] = [];
+        const dartReturnType = this.toDartReturnType(method.returnType);
+        let methodName = renamedMethod || this.toDartMethodName(method.name, cType.name);
+
+        // Skip if this is handled as getter/setter
+        if (this.isGetter(method) || this.isSetter(method)) {
+            return '';
+        }
+
+        // Check if this is a static method (no self parameter)
+        const isStatic = method.parameters.length === 0 ||
+                        (method.parameters[0].name !== 'self' &&
+                         !method.parameters[0].cType.startsWith(cType.name));
+
+        // Rename static rtti method to avoid conflict with getter
+        if (isStatic && methodName === 'rtti') {
+            methodName = 'rttiStatic';
+        }
+
+        // Parameters (skip 'self' parameter for instance methods)
+        const paramStartIndex = isStatic ? 0 : 1;
+        const params = method.parameters.slice(paramStartIndex).map(p => {
+            const dartType = this.toDartParameterType(p);
+            return `${dartType} ${p.name}`;
+        }).join(', ');
+
+        // Arguments
+        const args = method.parameters.map((p, i) => {
+            if (!isStatic && i === 0) return '_ptr'; // self parameter
+            return this.convertDartToC(p.name, p);
+        }).join(', ');
+
+        // Generate method signature with appropriate modifier
+        const methodSignature = isStatic ? `  static ${dartReturnType} ${methodName}` : `  ${dartReturnType} ${methodName}`;
+
+        lines.push(`${methodSignature}(${params}) {`);
+
+        // Always use the static _bindings
+        const bindingsRef = '_bindings';
+
+        if (method.returnType === 'void') {
+            lines.push(`    ${bindingsRef}.${method.name}(${args});`);
+        } else {
+            lines.push(`    final result = ${bindingsRef}.${method.name}(${args});`);
+            lines.push(`    ${this.generateReturnConversion(method.returnType, 'result', bindingsRef)}`);
+        }
+
+        lines.push('  }');
+
+        return lines.join('\n');
+    }
+
+    private writeGetter(cType: CClassOrStruct, method: CMethod, renamedMethod?: string): string {
+        const lines: string[] = [];
+        const propertyName = renamedMethod || this.extractPropertyName(method.name, cType.name);
+        const dartReturnType = this.toDartReturnType(method.returnType);
+
+        lines.push(`  ${dartReturnType} get ${propertyName} {`);
+        lines.push(`    final result = _bindings.${method.name}(_ptr);`);
+        lines.push(`    ${this.generateReturnConversion(method.returnType, 'result', '_bindings')}`);
+        lines.push('  }');
+
+        return lines.join('\n');
+    }
+
+    private writeSetter(cType: CClassOrStruct, method: CMethod, renamedMethod?: string): string {
+        const lines: string[] = [];
+        let propertyName = renamedMethod || this.extractPropertyName(method.name, cType.name);
+        const param = method.parameters[1]; // First param is self
+        const dartType = this.toDartParameterType(param);
+
+        // Handle numeric suffixes in setter names
+        const match = propertyName.match(/^(\w+)_(\d+)$/);
+        if (match) {
+            // Convert property_2 to property2
+            propertyName = `${match[1]}${match[2]}`;
+        } else if (/^\d+$/.test(propertyName)) {
+            // If property name is just a number, prefix with 'set'
+            propertyName = `set${propertyName}`;
+        }
+
+        lines.push(`  set ${propertyName}(${dartType} value) {`);
+        lines.push(`    _bindings.${method.name}(_ptr, ${this.convertDartToC('value', param)});`);
+        lines.push('  }');
+
+        return lines.join('\n');
+    }
+
+    private isGetter(method: CMethod): boolean {
+        // Traditional getter with _get_ in name
+        if (method.name.includes('_get_') && method.parameters.length === 1) {
+            return true;
+        }
+        
+        // Boolean methods that start with 'has_' or 'is_' and take only self parameter
+        if (method.returnType === 'bool' && method.parameters.length === 1) {
+            if (method.name.includes('_has_') || method.name.includes('_is_')) {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+
+    private isSetter(method: CMethod): boolean {
+        // Must return void and have 2 parameters (self + value)
+        if (method.returnType !== 'void' || method.parameters.length !== 2) {
+            return false;
+        }
+        
+        // Traditional setter with _set_ in name
+        if (method.name.includes('_set_')) {
+            return true;
+        }
+        
+        return false;
+    }
+
+    private extractPropertyName(methodName: string, typeName: string): string {
+        // Remove type prefix and get/set
+        const prefix = `${typeName}_`;
+        let name = methodName.startsWith(prefix) ? methodName.slice(prefix.length) : methodName;
+
+        if (name.startsWith('get_')) {
+            name = name.slice(4);
+        } else if (name.startsWith('set_')) {
+            name = name.slice(4);
+        }
+
+        // Special case: if the property name is "update_cache", rename to "updateCacheList"
+        // to avoid collision with the updateCache() method
+        if (name === 'update_cache') {
+            return 'updateCacheList';
+        }
+
+        // Special case: if property name is a type name, suffix with 'Value'
+        const typeNames = ['int', 'float', 'double', 'bool', 'string'];
+        if (typeNames.includes(name.toLowerCase())) {
+            return `${this.toCamelCase(name)}Value`;
+        }
+
+        return this.toCamelCase(name);
+    }
+
+    private toDartTypeName(cTypeName: string): string {
+        // spine_animation -> Animation
+        if (cTypeName.startsWith('spine_')) {
+            const name = cTypeName.slice(6);
+            return this.toPascalCase(name);
+        }
+        return this.toPascalCase(cTypeName);
+    }
+
+    private toDartMethodName(cMethodName: string, cTypeName: string): string {
+        // spine_animation_apply -> apply
+        const prefix = `${cTypeName}_`;
+        if (cMethodName.startsWith(prefix)) {
+            return this.toCamelCase(cMethodName.slice(prefix.length));
+        }
+        return this.toCamelCase(cMethodName);
+    }
+
+    private toDartEnumValueName(cValueName: string, cEnumName: string): string {
+        // SPINE_BLEND_MODE_NORMAL -> normal
+        const enumNameUpper = cEnumName.toUpperCase();
+
+        // Try different prefix patterns
+        const prefixes = [
+            `SPINE_${enumNameUpper}_`,
+            `${enumNameUpper}_`,
+            'SPINE_'
+        ];
+
+        let name = cValueName;
+        for (const prefix of prefixes) {
+            if (name.startsWith(prefix)) {
+                name = name.slice(prefix.length);
+                break;
+            }
+        }
+
+        const enumValue = this.toCamelCase(name.toLowerCase());
+        
+        // Special case for MixDirection enum - prefix with 'direction'
+        if (cEnumName === 'spine_mix_direction' && ['in', 'out'].includes(enumValue)) {
+            return `direction${this.toPascalCase(enumValue)}`;
+        }
+        
+        return enumValue;
+    }
+
+    private toDartReturnType(cType: string): string {
+        if (cType === 'void') return 'void';
+        // Handle char* with or without spaces
+        if (cType === 'char*' || cType === 'char *' || cType === 'const char*' || cType === 'const char *') return 'String';
+        if (cType === 'float' || cType === 'double') return 'double';
+        if (cType === 'int' || cType === 'size_t' || cType === 'int32_t' || cType === 'uint32_t') return 'int';
+        if (cType === 'bool') return 'bool';
+
+        // Handle enum types
+        if (this.enumNames.has(cType)) {
+            return this.toDartTypeName(cType);
+        }
+
+        // Handle array types
+        if (cType.startsWith('spine_array_')) {
+            return this.toDartTypeName(cType);
+        }
+
+        // Handle other spine types
+        if (cType.startsWith('spine_')) {
+            return this.toDartTypeName(cType);
+        }
+
+        return 'dynamic';
+    }
+
+    private toDartParameterType(param: CParameter): string {
+        // Handle output parameters (non-const references that become pointers)
+        if (param.isOutput) {
+            const baseType = param.cType.replace('*', '').trim();
+            return `Pointer<${this.getPrimitiveFFIType(baseType + '*')}>`;
+        }
+
+        // String parameters should stay as String, not dynamic (handle with or without spaces)
+        if (param.cType === 'char*' || param.cType === 'char *' || param.cType === 'const char*' || param.cType === 'const char *') {
+            return 'String';
+        }
+
+        return this.toDartReturnType(param.cType);
+    }
+
+    private toDartElementType(elementType: string): string {
+        // Handle pointer types
+        if (elementType.endsWith('*')) {
+            const baseType = elementType.slice(0, -1).trim();
+            return this.toDartTypeName(`spine_${toSnakeCase(baseType)}`);
+        }
+
+        // For primitive types, return the Dart type directly
+        if (elementType === 'int' || elementType === 'int32_t' || elementType === 'uint32_t' || elementType === 'size_t') {
+            return 'int';
+        }
+        if (elementType === 'unsigned_short') {
+            return 'int';  // Dart doesn't have unsigned short, use int
+        }
+        if (elementType === 'property_id' || elementType === 'int64_t') {
+            return 'int';  // PropertyId is int64_t which maps to int in Dart
+        }
+        if (elementType === 'float' || elementType === 'double') {
+            return 'double';
+        }
+        if (elementType === 'bool') {
+            return 'bool';
+        }
+
+        // For object types that are already in PascalCase (from extractArrayElementType)
+        // just return them as-is
+        return elementType;
+    }
+
+    private getPrimitiveFFIType(cType: string): string {
+        switch (cType) {
+            case 'float*': return 'Float';
+            case 'double*': return 'Double';
+            case 'int*': return 'Int';
+            case 'bool*': return 'Bool';
+            default: return 'Void';
+        }
+    }
+
+    private convertDartToC(dartValue: string, param: CParameter): string {
+        // Handle char* with or without spaces
+        if (param.cType === 'char*' || param.cType === 'char *' || param.cType === 'const char*' || param.cType === 'const char *') {
+            return `${dartValue}.toNativeUtf8().cast<Char>()`;
+        }
+
+        // Check if it's an enum type
+        if (this.enumNames.has(param.cType)) {
+            return `${dartValue}.value`;
+        }
+
+        // Check if it's an array type - arrays use _nativeArray
+        if (param.cType.startsWith('spine_array_')) {
+            return `${dartValue}.nativePtr.cast()`;
+        }
+
+        // Regular spine types have nativePtr
+        if (param.cType.startsWith('spine_')) {
+            return `${dartValue}.nativePtr.cast()`;
+        }
+
+        return dartValue;
+    }
+
+    private generateReturnConversion(cReturnType: string, resultVar: string, bindingsRef: string = '_bindings'): string {
+        // Handle char* with or without spaces
+        if (cReturnType === 'char*' || cReturnType === 'char *' || cReturnType === 'const char*' || cReturnType === 'const char *') {
+            return `return ${resultVar}.cast<Utf8>().toDartString();`;
+        }
+
+        // Handle enum types
+        if (this.enumNames.has(cReturnType)) {
+            const dartType = this.toDartTypeName(cReturnType);
+            return `return ${dartType}.fromValue(${resultVar});`;
+        }
+
+        if (cReturnType.startsWith('spine_array_')) {
+            const dartType = this.toDartTypeName(cReturnType);
+            return `return ${dartType}.fromPointer(${resultVar});`;
+        }
+
+        if (cReturnType.startsWith('spine_')) {
+            const dartType = this.toDartTypeName(cReturnType);
+            return `return ${dartType}.fromPointer(${resultVar});`;
+        }
+
+        return `return ${resultVar};`;
+    }
+
+    private collectAllImports(cType: CClassOrStruct): Set<string> {
+        const imports = new Set<string>();
+        const currentTypeName = this.toDartTypeName(cType.name);
+        const currentFileName = `${toSnakeCase(currentTypeName)}.dart`;
+
+        // Collect from methods (return types and parameters)
+        // Only consider methods that will actually be generated (skip raw pointer methods)
+        let hasArrays = false;
+        for (const method of cType.methods) {
+            // Skip methods with raw pointer parameters - they won't be generated
+            if (this.hasRawPointerParameters(method)) {
+                continue;
+            }
+            // Return type
+            if (method.returnType.startsWith('spine_array_')) {
+                hasArrays = true;
+            }
+            // Check for spine types in return types (including pointer types)
+            else if (method.returnType.startsWith('spine_')) {
+                const cleanType = method.returnType.replace('*', '').trim();
+                if (!this.isPrimitive(cleanType)) {
+                    const typeName = this.toDartTypeName(cleanType);
+                    const fileName = `${toSnakeCase(typeName)}.dart`;
+                    // Skip self-imports
+                    if (fileName !== currentFileName) {
+                        imports.add(fileName);
+                    }
+                }
+            }
+
+            // Parameters
+            for (const param of method.parameters) {
+                // Skip self parameter
+                if (param.name === 'self') continue;
+
+                // Arrays
+                if (param.cType.startsWith('spine_array_')) {
+                    hasArrays = true;
+                }
+                // Enums
+                else if (this.enumNames.has(param.cType)) {
+                    const enumType = this.toDartTypeName(param.cType);
+                    imports.add(`${toSnakeCase(enumType)}.dart`);
+                }
+                // Other spine types (handle both pointer and non-pointer types)
+                else if (param.cType.startsWith('spine_')) {
+                    const cleanType = param.cType.replace('*', '').trim();
+                    if (!this.isPrimitive(cleanType)) {
+                        const typeName = this.toDartTypeName(cleanType);
+                        const fileName = `${toSnakeCase(typeName)}.dart`;
+                        // Skip self-imports
+                        if (fileName !== currentFileName) {
+                            imports.add(fileName);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Collect from constructors
+        for (const constr of cType.constructors) {
+            for (const param of constr.parameters) {
+                // Arrays
+                if (param.cType.startsWith('spine_array_')) {
+                    hasArrays = true;
+                }
+                // Enums
+                else if (this.enumNames.has(param.cType)) {
+                    const enumType = this.toDartTypeName(param.cType);
+                    imports.add(`${toSnakeCase(enumType)}.dart`);
+                }
+                // Other spine types (but not primitives)
+                else if (param.cType.startsWith('spine_') && !param.cType.includes('*')) {
+                    const typeName = this.toDartTypeName(param.cType);
+                    const fileName = `${toSnakeCase(typeName)}.dart`;
+                    // Skip self-imports
+                    if (fileName !== currentFileName) {
+                        imports.add(fileName);
+                    }
+                }
+            }
+        }
+        
+        // Add arrays.dart import if any arrays are used
+        if (hasArrays) {
+            imports.add('arrays.dart');
+        }
+
+        return imports;
+    }
+
+    private extractArrayElementType(arrayTypeName: string): string {
+        // spine_array_animation -> Animation
+        // spine_array_int -> int
+        const match = arrayTypeName.match(/spine_array_(.+)/);
+        if (match) {
+            const rawType = match[1];
+            // For primitive types, return the raw type
+            if (['int', 'float', 'bool', 'unsigned_short', 'property_id'].includes(rawType)) {
+                return rawType;
+            }
+            // For object types, convert to PascalCase
+            return this.toPascalCase(rawType);
+        }
+        return 'dynamic';
+    }
+
+    private isPrimitive(type: string): boolean {
+        return ['float', 'double', 'int', 'bool', 'size_t', 'int32_t', 'uint32_t'].includes(type);
+    }
+
+    private hasRawPointerParameters(method: CMethod): boolean {
+        // Check return type
+        if (this.isRawPointer(method.returnType)) {
+            return true;
+        }
+
+        // Check parameters
+        for (const param of method.parameters) {
+            if (this.isRawPointer(param.cType)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private isRawPointer(cType: string): boolean {
+        // String types are allowed
+        if (cType === 'char*' || cType === 'char *' || cType === 'const char*' || cType === 'const char *') {
+            return false;
+        }
+
+        // Check if it's a pointer type (ends with * or contains *)
+        if (cType.includes('*')) {
+            // If it's not a spine type pointer, it's a raw pointer
+            const cleanType = cType.replace('*', '').trim();
+            if (!cleanType.startsWith('spine_')) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private renumberMethods(methods: CMethod[], typeName: string): Array<{method: CMethod, renamedMethod?: string}> {
+        const result: Array<{method: CMethod, renamedMethod?: string}> = [];
+        
+        // Group methods by their base name (without numeric suffix)
+        const methodGroups = new Map<string, CMethod[]>();
+        
+        for (const method of methods) {
+            // Extract base name without numeric suffix
+            const match = method.name.match(/^(.+?)_(\d+)$/);
+            if (match) {
+                const baseName = match[1];
+                if (!methodGroups.has(baseName)) {
+                    methodGroups.set(baseName, []);
+                }
+                methodGroups.get(baseName)!.push(method);
+            } else {
+                // Method without numeric suffix
+                result.push({ method });
+            }
+        }
+        
+        // Process grouped methods
+        for (const [baseName, groupedMethods] of methodGroups) {
+            if (groupedMethods.length === 1) {
+                // Only one method left in the group - remove the numeric suffix
+                const method = groupedMethods[0];
+                const dartMethodName = this.toDartMethodName(baseName, typeName);
+                result.push({ method, renamedMethod: dartMethodName });
+            } else {
+                // Multiple methods - renumber them starting from 1 (or keep special names)
+                groupedMethods.sort((a, b) => {
+                    const aNum = parseInt(a.name.match(/_(\d+)$/)![1]);
+                    const bNum = parseInt(b.name.match(/_(\d+)$/)![1]);
+                    return aNum - bNum;
+                });
+                
+                for (let i = 0; i < groupedMethods.length; i++) {
+                    const method = groupedMethods[i];
+                    const newNumber = i + 1;
+                    const currentNumber = parseInt(method.name.match(/_(\d+)$/)![1]);
+                    
+                    if (newNumber !== currentNumber) {
+                        // Need to renumber
+                        const baseDartName = this.toDartMethodName(baseName, typeName);
+                        result.push({ method, renamedMethod: `${baseDartName}${newNumber}` });
+                    } else {
+                        // Number is correct
+                        result.push({ method });
+                    }
+                }
+            }
+        }
+        
+        return result;
+    }
+
+    private toPascalCase(str: string): string {
+        return str.split('_')
+            .map(word => word.charAt(0).toUpperCase() + word.slice(1))
+            .join('');
+    }
+
+    private toCamelCase(str: string): string {
+        const pascal = this.toPascalCase(str);
+        return pascal.charAt(0).toLowerCase() + pascal.slice(1);
+    }
+
+    private needsStringConversions(cType: CClassOrStruct): boolean {
+        // Check if any method has string parameters or return types
+        for (const method of cType.methods) {
+            // Check return type
+            if (method.returnType === 'char*' || method.returnType === 'char *' || 
+                method.returnType === 'const char*' || method.returnType === 'const char *') {
+                return true;
+            }
+            
+            // Check parameters
+            for (const param of method.parameters) {
+                if (param.cType === 'char*' || param.cType === 'char *' || 
+                    param.cType === 'const char*' || param.cType === 'const char *') {
+                    return true;
+                }
+            }
+        }
+
+        // Check constructors
+        for (const constr of cType.constructors) {
+            for (const param of constr.parameters) {
+                if (param.cType === 'char*' || param.cType === 'char *' || 
+                    param.cType === 'const char*' || param.cType === 'const char *') {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+}

+ 132 - 0
spine-flutter/codegen/src/index.ts

@@ -0,0 +1,132 @@
+#!/usr/bin/env node
+import { execSync } from 'node:child_process';
+import * as fs from 'node:fs';
+import * as path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { generate } from '../../../spine-c/codegen/src/index.js';
+import { DartWriter } from './dart-writer.js';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+async function generateFFIBindings(spineCDir: string): Promise<void> {
+    console.log('Finding all header files...');
+    const generatedDir = path.join(spineCDir, 'src/generated');
+    const headerFiles = fs.readdirSync(generatedDir)
+        .filter(f => f.endsWith('.h'))
+        .map(f => path.join('src/spine-c/src/generated', f))
+        .sort();
+
+    console.log(`Found ${headerFiles.length} header files`);
+
+    // Generate ffigen.yaml configuration
+    console.log('Generating ffigen.yaml configuration...');
+    const ffigenConfig = `# Run with \`dart run ffigen --config ffigen.yaml\`.
+name: SpineFlutterBindings
+description: |
+  Bindings for Spine C headers.
+
+  Regenerate bindings with \`dart run ffigen --config ffigen.yaml\`.
+output: 'lib/generated/spine_flutter_bindings_generated.dart'
+llvm-path:
+    - '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/'
+headers:
+  entry-points:
+    - 'src/spine-c/include/spine-c.h'
+    - 'src/spine-c/src/base.h'
+    - 'src/spine-c/src/extensions.h'
+${headerFiles.map(h => `    - '${h}'`).join('\n')}
+  include-directives:
+    - 'src/spine-c/include/spine-c.h'
+    - 'src/spine-c/src/base.h'
+    - 'src/spine-c/src/extensions.h'
+${headerFiles.map(h => `    - '${h}'`).join('\n')}
+compiler-opts:
+  - '-Isrc/spine-c/include'
+  - '-Isrc/spine-c/src'
+  - '-Isrc/spine-c/src/generated'
+  - '-xc'
+  - '-std=c99'
+functions:
+  include:
+    - 'spine_.*'
+structs:
+  include:
+    - 'spine_.*'
+enums:
+  include:
+    - 'spine_.*'
+typedefs:
+  include:
+    - 'spine_.*'
+preamble: |
+  // ignore_for_file: always_specify_types, constant_identifier_names
+  // ignore_for_file: camel_case_types
+  // ignore_for_file: non_constant_identifier_names
+comments:
+  style: any
+  length: full
+`;
+
+    const ffigenPath = path.join(__dirname, '../../ffigen.yaml');
+    fs.writeFileSync(ffigenPath, ffigenConfig);
+
+    // Run ffigen to generate bindings
+    console.log('Running ffigen...');
+    try {
+        execSync('dart run ffigen --config ffigen.yaml', {
+            cwd: path.join(__dirname, '../..'),
+            stdio: 'inherit'
+        });
+    } catch (error) {
+        console.error('Failed to run ffigen:', error);
+        throw error;
+    }
+
+    // Check if bindings were generated successfully
+    const bindingsPath = path.join(__dirname, '../../lib/generated/spine_flutter_bindings_generated.dart');
+    if (!fs.existsSync(bindingsPath)) {
+        throw new Error('Failed to generate bindings');
+    }
+
+    // Replace dart:ffi import with ffi_proxy.dart
+    console.log('Replacing dart:ffi import with ffi_proxy.dart...');
+    let content = fs.readFileSync(bindingsPath, 'utf8');
+    content = content.replace("import 'dart:ffi' as ffi;", "import '../../ffi_proxy.dart' as ffi;");
+    fs.writeFileSync(bindingsPath, content);
+
+    // Clean up ffigen.yaml
+    console.log('Cleaning up ffigen.yaml...');
+    fs.unlinkSync(ffigenPath);
+
+    console.log('✅ FFI bindings generated successfully!');
+}
+
+async function main() {
+    console.log('Generating Spine Flutter bindings and wrappers...\n');
+
+    try {
+        // Step 1: Generate C intermediate representation using spine-c codegen
+        console.log('Step 1: Generating C intermediate representation...');
+        const { cTypes, cEnums, cArrayTypes } = await generate();
+        console.log(`Generated ${cTypes.length} C types, ${cEnums.length} enums, and ${cArrayTypes.length} array types\n`);
+
+        // Step 2: Write Dart wrapper classes
+        console.log('Step 2: Writing Dart wrapper classes...');
+        const outputDir = path.join(__dirname, '../../lib/generated');
+        const dartWriter = new DartWriter(outputDir);
+        await dartWriter.writeAll(cTypes, cEnums, cArrayTypes);
+        console.log();
+
+        // Step 3: Generate FFI bindings using ffigen
+        console.log('Step 3: Generating FFI bindings...');
+        const spineCDir = path.join(__dirname, '../../src/spine-c');
+        await generateFFIBindings(spineCDir);
+
+        console.log('\n✅ All code generation completed successfully!');
+    } catch (error) {
+        console.error('\n❌ Error:', error);
+        process.exit(1);
+    }
+}
+
+main();

+ 17 - 0
spine-flutter/codegen/tsconfig.json

@@ -0,0 +1,17 @@
+{
+  "compilerOptions": {
+    "target": "ES2022",
+    "module": "ESNext",
+    "moduleResolution": "node",
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "strict": true,
+    "skipLibCheck": true,
+    "forceConsistentCasingInFileNames": true,
+    "resolveJsonModule": true,
+    "types": ["node"]
+  },
+  "include": [
+    "src/**/*.ts"
+  ]
+}

+ 24 - 0
spine-flutter/codegen/tsfmt.json

@@ -0,0 +1,24 @@
+{
+	"baseIndentSize": 0,
+	"indentSize": 4,
+	"tabSize": 4,
+	"indentStyle": 2,
+	"newLineCharacter": "\n",
+	"convertTabsToSpaces": false,
+	"insertSpaceAfterCommaDelimiter": true,
+	"insertSpaceAfterSemicolonInForStatements": true,
+	"insertSpaceBeforeAndAfterBinaryOperators": true,
+	"insertSpaceAfterConstructor": true,
+	"insertSpaceAfterKeywordsInControlFlowStatements": true,
+	"insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
+	"insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
+	"insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
+	"insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true,
+	"insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false,
+	"insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false,
+	"insertSpaceAfterTypeAssertion": false,
+	"insertSpaceBeforeFunctionParenthesis": true,
+	"insertSpaceBeforeTypeAnnotation": false,
+	"placeOpenBraceOnNewLineForFunctions": false,
+	"placeOpenBraceOnNewLineForControlBlocks": false
+}

+ 0 - 21
spine-flutter/ffigen.yaml

@@ -1,21 +0,0 @@
-# Run with `dart run ffigen --config ffigen.yaml`.
-name: SpineFlutterBindings
-description: |
-  Bindings for `src/spine_flutter.h`.
-
-  Regenerate bindings with `dart run ffigen --config ffigen.yaml`.
-output: 'lib/spine_flutter_bindings_generated.dart'
-llvm-path:
-    - '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/'
-headers:
-  entry-points:
-    - 'src/spine-cpp-lite/spine-cpp-lite.h'
-  include-directives:
-    - 'src/spine-cpp-lite/spine-cpp-lite.h'
-preamble: |
-  // ignore_for_file: always_specify_types, constant_identifier_names
-  // ignore_for_file: camel_case_types
-  // ignore_for_file: non_constant_identifier_names
-comments:
-  style: any
-  length: full

+ 20 - 0
spine-flutter/generate-bindings.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+
+set -e
+
+# Get to the script's directory
+pushd "$(dirname "$0")" > /dev/null
+
+#./setup.sh
+
+# Install dependencies if needed
+if [ ! -d "codegen/node_modules" ]; then
+    pushd codegen > /dev/null
+    npm install
+    popd > /dev/null
+fi
+
+# Run the codegen
+npx tsx codegen/src/index.ts
+
+popd > /dev/null

+ 911 - 0
spine-flutter/generator.md

@@ -0,0 +1,911 @@
+# Dart FFI Wrapper Generator
+
+## Overview
+
+A TypeScript-based code generator that extends the existing `spine-c/codegen` system to automatically generate clean, type-safe Dart wrapper classes over the raw FFI bindings. This eliminates the need for manual wrapper implementation while providing a native Dart API experience.
+
+## Architecture
+
+```
+spine-cpp (C++ source)
+    ↓ (existing type-extractor.ts)
+spine-cpp-types.json (type definitions)
+    ↓ (existing ir-generator.ts + c-writer.ts)
+spine-c (C bindings: .h/.c files)
+    ↓ (ffigen via generate_bindings.sh)
+spine_flutter_bindings_generated.dart (raw FFI)
+    ↓ (NEW: dart-generator.ts)
+spine_flutter.dart (clean Dart API)
+```
+
+## Key Insights
+
+### 1. Derivation vs Parsing
+Instead of parsing the generated FFI bindings, we **derive** what ffigen produces using the same C type information that generates the headers. This works because ffigen follows predictable transformation rules:
+
+### 2. Predictable Disposal Pattern
+All C types follow a consistent disposal pattern (`spine_type_name` → `spine_type_name_dispose`), so we can derive disposal function names automatically instead of storing them.
+
+### 3. Array Properties vs Regular Getters
+C functions that return `spine_array_*` types become special **Array<T> properties** in Dart, requiring different generation logic than primitive getters.
+
+### FFigen Transformation Rules
+
+| C Code | Generated Dart FFI |
+|--------|-------------------|
+| `SPINE_C_API float spine_animation_get_duration(spine_animation self);` | `double spine_animation_get_duration(Pointer<spine_animation_wrapper> self)` |
+| `SPINE_C_API void spine_animation_dispose(spine_animation self);` | `void spine_animation_dispose(Pointer<spine_animation_wrapper> self)` |
+| `typedef enum { BLEND_NORMAL, BLEND_ADDITIVE } spine_blend_mode;` | `enum spine_blend_mode { BLEND_NORMAL(0), BLEND_ADDITIVE(1) }` |
+| `SPINE_OPAQUE_TYPE(spine_animation)` | `typedef struct spine_animation_wrapper { char _dummy; } spine_animation_wrapper; typedef spine_animation_wrapper *spine_animation;` |
+| `spine_array_timeline spine_animation_get_timelines(spine_animation self);` | `Pointer<spine_array_timeline_wrapper> spine_animation_get_timelines(Pointer<spine_animation_wrapper> self)` → **Array<Timeline> property** |
+
+## Generator Components
+
+### 1. Type Mapping System (`dart-types.ts`)
+
+Defines the structure for Dart wrapper types:
+
+```typescript
+interface DartClass {
+  name: string;                    // "Animation"
+  cName: string;                   // "spine_animation" 
+  nativeType: string;              // "Pointer<spine_animation_wrapper>"
+  constructors: DartConstructor[];
+  methods: DartMethod[];
+  getters: DartGetter[];
+  setters: DartSetter[];
+  arrays: DartArrayGetter[];       // Properties that return Array<T> (e.g., animation.timelines)
+}
+
+interface DartMethod {
+  name: string;                    // "apply"
+  cFunctionName: string;           // "spine_animation_apply"
+  returnType: DartType;
+  parameters: DartParameter[];
+  isStatic?: boolean;
+}
+
+interface DartGetter {
+  name: string;                    // "duration"
+  cFunctionName: string;           // "spine_animation_get_duration"
+  returnType: DartType;
+}
+
+interface DartSetter {
+  name: string;                    // "duration"
+  cFunctionName: string;           // "spine_animation_set_duration"
+  parameterType: DartType;
+}
+
+interface DartArrayGetter {
+  name: string;                    // "timelines" (Dart property name)
+  elementType: string;             // "Timeline" (element type inside Array<T>)
+  cArrayType: string;              // "spine_array_timeline" (C array type returned)
+  cGetterName: string;             // "spine_animation_get_timelines" (C function to call)
+}
+
+interface DartConstructor {
+  cFunctionName: string;           // "spine_animation_create"
+  parameters: DartParameter[];
+}
+
+interface DartParameter {
+  name: string;
+  type: DartType;
+  cType: string;                   // Original C type for conversion
+}
+
+interface DartType {
+  dart: string;                    // "double", "String", "Animation"
+  isNullable?: boolean;
+  isNative?: boolean;              // true for primitives, false for wrapper classes
+}
+
+interface DartEnum {
+  name: string;                    // "BlendMode"
+  cName: string;                   // "spine_blend_mode"
+  values: DartEnumValue[];
+}
+
+interface DartEnumValue {
+  name: string;                    // "normal"
+  cName: string;                   // "SPINE_BLEND_MODE_NORMAL"  
+  value: number;
+}
+```
+
+### 2. Type Mapping Rules (`dart-type-mapper.ts`)
+
+Converts C types to Dart types:
+
+```typescript
+class DartTypeMapper {
+  // Maps C types to Dart types
+  private static readonly TYPE_MAP: Record<string, DartType> = {
+    'float': { dart: 'double', isNative: true },
+    'double': { dart: 'double', isNative: true },
+    'int': { dart: 'int', isNative: true },
+    'bool': { dart: 'bool', isNative: true },
+    'char*': { dart: 'String', isNative: true },
+    'const char*': { dart: 'String', isNative: true },
+    'void': { dart: 'void', isNative: true },
+    'spine_skeleton': { dart: 'Skeleton', isNative: false },
+    'spine_animation': { dart: 'Animation', isNative: false },
+    // ... more mappings
+  };
+
+  static mapCTypeToDart(cType: string): DartType {
+    // Handle pointers
+    if (cType.endsWith('*')) {
+      const baseType = cType.slice(0, -1).trim();
+      const mapped = this.TYPE_MAP[baseType];
+      return mapped ? { ...mapped, isNullable: true } : this.mapSpineType(baseType);
+    }
+    
+    // Handle direct mappings
+    return this.TYPE_MAP[cType] || this.mapSpineType(cType);
+  }
+
+  private static mapSpineType(cType: string): DartType {
+    if (cType.startsWith('spine_')) {
+      // spine_animation -> Animation
+      const dartName = toPascalCase(cType.replace('spine_', ''));
+      return { dart: dartName, isNative: false };
+    }
+    
+    // Default to dynamic for unknown types
+    return { dart: 'dynamic', isNative: false };
+  }
+}
+```
+
+### 3. Naming Convention Utilities (`dart-naming.ts`)
+
+Handles C to Dart naming conversions:
+
+```typescript
+export function toPascalCase(snakeCase: string): string {
+  return snakeCase
+    .split('_')
+    .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
+    .join('');
+}
+
+export function toCamelCase(snakeCase: string): string {
+  const pascal = toPascalCase(snakeCase);
+  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
+}
+
+export function extractMethodName(cFunctionName: string, className: string): string {
+  // spine_animation_get_duration -> getDuration
+  // spine_animation_set_duration -> setDuration
+  // spine_animation_apply -> apply
+  
+  const prefix = `spine_${toSnakeCase(className)}_`;
+  if (!cFunctionName.startsWith(prefix)) {
+    throw new Error(`Function ${cFunctionName} doesn't match expected prefix ${prefix}`);
+  }
+  
+  const methodPart = cFunctionName.slice(prefix.length);
+  return toCamelCase(methodPart);
+}
+
+export function isGetter(methodName: string): boolean {
+  return methodName.startsWith('get_');
+}
+
+export function isSetter(methodName: string): boolean {
+  return methodName.startsWith('set_');
+}
+
+export function extractPropertyName(methodName: string): string {
+  // get_duration -> duration
+  // set_duration -> duration
+  if (methodName.startsWith('get_') || methodName.startsWith('set_')) {
+    return methodName.slice(4);
+  }
+  return methodName;
+}
+```
+
+### 4. Dart Code Generator (`dart-writer.ts`)
+
+Generates the actual Dart wrapper files:
+
+```typescript
+export class DartWriter {
+  constructor(private outputDir: string, private bindingsImport: string) {}
+
+  async writeClass(dartClass: DartClass): Promise<void> {
+    const lines: string[] = [];
+    
+    // File header
+    lines.push("// AUTO GENERATED FILE, DO NOT EDIT.");
+    lines.push("// Generated by spine-c dart-wrapper generator");
+    lines.push("");
+    lines.push(`import '${this.bindingsImport}';`);
+    lines.push("import 'dart:ffi';");
+    lines.push("import 'array.dart';");
+    lines.push("");
+    
+    // Class declaration
+    lines.push(`class ${dartClass.name} {`);
+    lines.push(`  final ${dartClass.nativeType} _ptr;`);
+    lines.push(`  final SpineFlutterBindings _bindings;`);
+    lines.push("");
+    
+    // Private constructor
+    lines.push(`  ${dartClass.name}._(this._ptr, this._bindings);`);
+    lines.push("");
+    
+    // Public constructors
+    for (const constructor of dartClass.constructors) {
+      lines.push(this.writeConstructor(dartClass, constructor));
+      lines.push("");
+    }
+    
+    // Getters
+    for (const getter of dartClass.getters) {
+      lines.push(this.writeGetter(getter));
+    }
+    
+    // Setters  
+    for (const setter of dartClass.setters) {
+      lines.push(this.writeSetter(setter));
+    }
+    
+    // Array getters
+    for (const arrayGetter of dartClass.arrays) {
+      lines.push(this.writeArrayGetter(arrayGetter));
+    }
+    
+    // Methods
+    for (const method of dartClass.methods) {
+      lines.push(this.writeMethod(method));
+      lines.push("");
+    }
+    
+    // Disposal method (derived from class name)
+    lines.push(`  void dispose() => _bindings.${dartClass.cName}_dispose(_ptr);`);
+    
+    lines.push("}");
+    
+    // Write to file
+    const fileName = `${toSnakeCase(dartClass.name)}.dart`;
+    const filePath = path.join(this.outputDir, fileName);
+    await fs.writeFile(filePath, lines.join('\n'));
+  }
+
+  private writeConstructor(dartClass: DartClass, constructor: DartConstructor): string {
+    const params = constructor.parameters.map(p => 
+      `${p.type.dart} ${p.name}`
+    ).join(', ');
+    
+    const args = constructor.parameters.map(p => 
+      this.convertDartToC(p.name, p.type, p.cType)
+    ).join(', ');
+    
+    return [
+      `  factory ${dartClass.name}.create(SpineFlutterBindings bindings${params ? ', ' + params : ''}) {`,
+      `    final ptr = bindings.${constructor.cFunctionName}(${args});`,
+      `    return ${dartClass.name}._(ptr, bindings);`,
+      `  }`
+    ].join('\n');
+  }
+
+  private writeGetter(getter: DartGetter): string {
+    if (getter.returnType.isNative) {
+      return `  ${getter.returnType.dart} get ${getter.name} => _bindings.${getter.cFunctionName}(_ptr);`;
+    } else {
+      return [
+        `  ${getter.returnType.dart} get ${getter.name} {`,
+        `    final ptr = _bindings.${getter.cFunctionName}(_ptr);`,
+        `    return ${getter.returnType.dart}._(ptr, _bindings);`,
+        `  }`
+      ].join('\n');
+    }
+  }
+
+  private writeSetter(setter: DartSetter): string {
+    const conversion = this.convertDartToC('value', setter.parameterType, '');
+    return `  set ${setter.name}(${setter.parameterType.dart} value) => _bindings.${setter.cFunctionName}(_ptr, ${conversion});`;
+  }
+
+  private writeArrayGetter(arrayGetter: DartArrayGetter): string {
+    return [
+      `  Array<${arrayGetter.elementType}> get ${arrayGetter.name} {`,
+      `    final array = _bindings.${arrayGetter.cGetterName}(_ptr);`,
+      `    return Array.create<${arrayGetter.elementType}>(array, _bindings, ${arrayGetter.elementType}._);`,
+      `  }`
+    ].join('\n');
+  }
+
+  private writeMethod(method: DartMethod): string {
+    const params = method.parameters.map(p => 
+      `${p.type.dart} ${p.name}`
+    ).join(', ');
+    
+    const args = ['_ptr', ...method.parameters.map(p => 
+      this.convertDartToC(p.name, p.type, p.cType)
+    )].join(', ');
+    
+    if (method.returnType.dart === 'void') {
+      return [
+        `  void ${method.name}(${params}) {`,
+        `    _bindings.${method.cFunctionName}(${args});`,
+        `  }`
+      ].join('\n');
+    } else if (method.returnType.isNative) {
+      return [
+        `  ${method.returnType.dart} ${method.name}(${params}) {`,
+        `    return _bindings.${method.cFunctionName}(${args});`,
+        `  }`
+      ].join('\n');
+    } else {
+      return [
+        `  ${method.returnType.dart} ${method.name}(${params}) {`,
+        `    final ptr = _bindings.${method.cFunctionName}(${args});`,
+        `    return ${method.returnType.dart}._(ptr, _bindings);`,
+        `  }`
+      ].join('\n');
+    }
+  }
+
+  private convertDartToC(dartValue: string, dartType: DartType, cType: string): string {
+    if (dartType.isNative) {
+      // Handle string conversion
+      if (dartType.dart === 'String') {
+        return `${dartValue}.toNativeUtf8().cast<Char>()`;
+      }
+      return dartValue;
+    } else {
+      // Wrapper class - extract the pointer
+      return `${dartValue}._ptr`;
+    }
+  }
+}
+```
+
+### 5. Generic Array Implementation (`dart-array-writer.ts`)
+
+Generates a single reusable Array class:
+
+```typescript
+export class DartArrayWriter {
+  async writeArrayClass(outputDir: string): Promise<void> {
+    const content = `
+// AUTO GENERATED FILE, DO NOT EDIT.
+// Generated by spine-c dart-wrapper generator
+
+import 'dart:collection';
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+
+class Array<T> extends ListBase<T> {
+  final Pointer _nativeArray;
+  final SpineFlutterBindings _bindings;
+  final T Function(Pointer) _elementFactory;
+  final String _arrayTypeName;
+
+  Array._(
+    this._nativeArray,
+    this._bindings,
+    this._elementFactory,
+    this._arrayTypeName,
+  );
+
+  static Array<T> create<T>(
+    Pointer nativeArray,
+    SpineFlutterBindings bindings,
+    T Function(Pointer) elementFactory,
+  ) {
+    final typeName = T.toString().toLowerCase();
+    return Array._(nativeArray, bindings, elementFactory, 'spine_array_\$typeName');
+  }
+
+  @override
+  int get length {
+    // Use dynamic function lookup based on type
+    switch (_arrayTypeName) {
+      case 'spine_array_timeline':
+        return _bindings.spine_array_timeline_get_size(_nativeArray.cast());
+      case 'spine_array_bone_data':
+        return _bindings.spine_array_bone_data_get_size(_nativeArray.cast());
+      case 'spine_array_slot_data':
+        return _bindings.spine_array_slot_data_get_size(_nativeArray.cast());
+      // Add more cases as needed
+      default:
+        throw UnsupportedError('Unknown array type: \$_arrayTypeName');
+    }
+  }
+
+  @override
+  T operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this);
+    }
+
+    Pointer elementPtr;
+    switch (_arrayTypeName) {
+      case 'spine_array_timeline':
+        elementPtr = _bindings.spine_array_timeline_get(_nativeArray.cast(), index);
+        break;
+      case 'spine_array_bone_data':
+        elementPtr = _bindings.spine_array_bone_data_get(_nativeArray.cast(), index);
+        break;
+      case 'spine_array_slot_data':
+        elementPtr = _bindings.spine_array_slot_data_get(_nativeArray.cast(), index);
+        break;
+      // Add more cases as needed
+      default:
+        throw UnsupportedError('Unknown array type: \$_arrayTypeName');
+    }
+
+    return _elementFactory(elementPtr);
+  }
+
+  @override
+  void operator []=(int index, T value) {
+    throw UnsupportedError('Array is read-only');
+  }
+
+  @override
+  set length(int newLength) {
+    throw UnsupportedError('Array is read-only');
+  }
+}
+`;
+
+    const filePath = path.join(outputDir, 'array.dart');
+    await fs.writeFile(filePath, content.trim());
+  }
+}
+```
+
+### 6. Enum Generator (`dart-enum-writer.ts`)
+
+Generates Dart enum wrappers:
+
+```typescript
+export class DartEnumWriter {
+  async writeEnum(dartEnum: DartEnum, outputDir: string): Promise<void> {
+    const lines: string[] = [];
+    
+    // File header
+    lines.push("// AUTO GENERATED FILE, DO NOT EDIT.");
+    lines.push("// Generated by spine-c dart-wrapper generator");
+    lines.push("");
+    
+    // Enum declaration
+    lines.push(`enum ${dartEnum.name} {`);
+    
+    // Enum values
+    for (let i = 0; i < dartEnum.values.length; i++) {
+      const value = dartEnum.values[i];
+      const comma = i < dartEnum.values.length - 1 ? ',' : '';
+      lines.push(`  ${value.name}(${value.value})${comma}`);
+    }
+    
+    lines.push("");
+    lines.push("  const ${dartEnum.name}(this.value);");
+    lines.push("  final int value;");
+    lines.push("");
+    
+    // From native conversion
+    lines.push(`  static ${dartEnum.name} fromNative(int value) {`);
+    lines.push("    switch (value) {");
+    for (const value of dartEnum.values) {
+      lines.push(`      case ${value.value}: return ${dartEnum.name}.${value.name};`);
+    }
+    lines.push(`      default: throw ArgumentError('Unknown ${dartEnum.name} value: \$value');`);
+    lines.push("    }");
+    lines.push("  }");
+    lines.push("}");
+    
+    // Write to file
+    const fileName = `${toSnakeCase(dartEnum.name)}.dart`;
+    const filePath = path.join(outputDir, fileName);
+    await fs.writeFile(filePath, lines.join('\n'));
+  }
+}
+```
+
+### 7. Main Generator Orchestrator (`dart-generator.ts`)
+
+Coordinates the entire generation process:
+
+```typescript
+import { CClassOrStruct, CEnum, CArrayType } from './c-types';
+import { DartClass, DartEnum } from './dart-types';
+import { DartTypeMapper } from './dart-type-mapper';
+import { DartWriter } from './dart-writer';
+import { DartEnumWriter } from './dart-enum-writer';
+import { DartArrayWriter } from './dart-array-writer';
+import { extractMethodName, isGetter, isSetter, extractPropertyName } from './dart-naming';
+
+export class DartGenerator {
+  private typeMapper = new DartTypeMapper();
+  private writer: DartWriter;
+  private enumWriter = new DartEnumWriter();
+  private arrayWriter = new DartArrayWriter();
+
+  constructor(
+    private cTypes: CClassOrStruct[],
+    private cEnums: CEnum[],
+    private cArrayTypes: CArrayType[],
+    private outputDir: string,
+    private bindingsImport: string = 'spine_flutter_bindings_generated.dart'
+  ) {
+    this.writer = new DartWriter(outputDir, bindingsImport);
+  }
+
+  async generateAll(): Promise<void> {
+    // Ensure output directory exists
+    await fs.mkdir(this.outputDir, { recursive: true });
+
+    console.log(`Generating ${this.cTypes.length} Dart wrapper classes...`);
+    
+    // Generate wrapper classes
+    for (const cType of this.cTypes) {
+      const dartClass = this.convertCTypeToDartClass(cType);
+      await this.writer.writeClass(dartClass);
+      console.log(`Generated: ${dartClass.name}`);
+    }
+
+    console.log(`Generating ${this.cEnums.length} Dart enums...`);
+    
+    // Generate enums
+    for (const cEnum of this.cEnums) {
+      const dartEnum = this.convertCEnumToDartEnum(cEnum);
+      await this.enumWriter.writeEnum(dartEnum, this.outputDir);
+      console.log(`Generated enum: ${dartEnum.name}`);
+    }
+
+    // Generate generic Array class
+    await this.arrayWriter.writeArrayClass(this.outputDir);
+    console.log('Generated: Array<T>');
+
+    console.log('Dart wrapper generation complete!');
+  }
+
+  private convertCTypeToDartClass(cType: CClassOrStruct): DartClass {
+    const className = toPascalCase(cType.name.replace('spine_', ''));
+    
+    // Separate getters, setters, and regular methods
+    const getters: DartGetter[] = [];
+    const setters: DartSetter[] = [];
+    const methods: DartMethod[] = [];
+    const constructors: DartConstructor[] = [];
+    const arrays: DartArrayGetter[] = [];
+
+    for (const method of cType.methods) {
+      const methodName = extractMethodName(method.name, cType.name);
+      
+      if (method.name.includes('_create')) {
+        // Constructor
+        constructors.push({
+          cFunctionName: method.name,
+          parameters: method.parameters.slice(0, -1).map(p => ({
+            name: p.name,
+            type: this.typeMapper.mapCTypeToDart(p.type),
+            cType: p.type
+          }))
+        });
+      } else if (isGetter(methodName)) {
+        // Getter
+        const propertyName = extractPropertyName(methodName);
+        const returnType = this.typeMapper.mapCTypeToDart(method.returnType);
+        
+        // Check if this is an array getter
+        if (method.returnType.startsWith('spine_array_')) {
+          const elementType = this.extractArrayElementType(method.returnType);
+          arrays.push({
+            name: propertyName,
+            elementType,
+            cArrayType: method.returnType,
+            cGetterName: method.name
+          });
+        } else {
+          getters.push({
+            name: propertyName,
+            cFunctionName: method.name,
+            returnType
+          });
+        }
+      } else if (isSetter(methodName)) {
+        // Setter
+        const propertyName = extractPropertyName(methodName);
+        const paramType = this.typeMapper.mapCTypeToDart(method.parameters[1].type);
+        setters.push({
+          name: propertyName,
+          cFunctionName: method.name,
+          parameterType: paramType
+        });
+      } else {
+        // Regular method
+        methods.push({
+          name: methodName,
+          cFunctionName: method.name,
+          returnType: this.typeMapper.mapCTypeToDart(method.returnType),
+          parameters: method.parameters.slice(1).map(p => ({
+            name: p.name,
+            type: this.typeMapper.mapCTypeToDart(p.type),
+            cType: p.type
+          }))
+        });
+      }
+    }
+
+    return {
+      name: className,
+      cName: cType.name,
+      nativeType: `Pointer<${cType.name}_wrapper>`,
+      constructors,
+      methods,
+      getters,
+      setters,
+      arrays
+    };
+  }
+
+  private convertCEnumToDartEnum(cEnum: CEnum): DartEnum {
+    return {
+      name: toPascalCase(cEnum.name.replace('spine_', '')),
+      cName: cEnum.name,
+      values: cEnum.values.map(value => ({
+        name: toCamelCase(value.name.replace(/^SPINE_.*?_/, '')),
+        cName: value.name,
+        value: value.value
+      }))
+    };
+  }
+
+  private extractArrayElementType(arrayType: string): string {
+    // spine_array_timeline -> Timeline
+    // spine_array_bone_data -> BoneData
+    const match = arrayType.match(/spine_array_(.+)/);
+    if (!match) throw new Error(`Invalid array type: ${arrayType}`);
+    
+    return toPascalCase(match[1]);
+  }
+}
+```
+
+### 8. Integration with Existing Codegen (`index.ts` modifications)
+
+Extend the existing main function:
+
+```typescript
+// Add to existing imports
+import { DartGenerator } from './dart-generator';
+
+// Add to existing main() function after C generation
+async function main() {
+    // ... existing C generation code ...
+
+    // Write all C files to disk
+    const cWriter = new CWriter(path.join(__dirname, '../../src/generated'));
+    await cWriter.writeAll(cTypes, cEnums, cArrayTypes);
+
+    console.log('C code generation complete!');
+
+    // NEW: Generate Dart wrappers
+    const dartOutputDir = path.join(__dirname, '../../../lib/src/generated');
+    const dartGenerator = new DartGenerator(
+        cTypes,
+        cEnums, 
+        cArrayTypes,
+        dartOutputDir
+    );
+    
+    await dartGenerator.generateAll();
+
+    console.log('All code generation complete!');
+}
+```
+
+## Generated Output Structure
+
+After running the generator, the output structure will be:
+
+```
+lib/
+├── spine_flutter.dart                    # Main export file
+├── spine_flutter_bindings_generated.dart # Raw FFI bindings (from ffigen)
+└── src/
+    └── generated/
+        ├── array.dart                    # Generic Array<T> implementation
+        ├── animation.dart                # Animation wrapper class
+        ├── skeleton.dart                 # Skeleton wrapper class
+        ├── bone_data.dart               # BoneData wrapper class
+        ├── blend_mode.dart              # BlendMode enum
+        └── ...                          # More generated classes and enums
+```
+
+## Usage Examples
+
+### Before (Manual FFI Usage)
+```dart
+// Raw FFI - error-prone and verbose
+final skeletonDataPtr = bindings.spine_skeleton_data_create_from_file('skeleton.json'.toNativeUtf8().cast());
+final bonesArrayPtr = bindings.spine_skeleton_data_get_bones(skeletonDataPtr);
+final numBones = bindings.spine_skeleton_data_get_num_bones(skeletonDataPtr);
+
+for (int i = 0; i < numBones; i++) {
+  final bonePtr = bindings.spine_array_bone_data_get(bonesArrayPtr, i);
+  final namePtr = bindings.spine_bone_data_get_name(bonePtr);
+  final name = namePtr.cast<Utf8>().toDartString();
+  print('Bone: $name');
+}
+
+bindings.spine_skeleton_data_dispose(skeletonDataPtr);
+```
+
+### After (Generated Wrapper Usage)
+```dart
+// Clean, type-safe API
+final skeletonData = SkeletonData.fromFile(bindings, 'skeleton.json');
+final bones = skeletonData.bones;  // Array<BoneData>
+
+for (final bone in bones) {  // Natural Dart iteration
+  print('Bone: ${bone.name}');  // Direct property access
+}
+
+skeletonData.dispose();  // Clean disposal
+```
+
+### Advanced Usage
+```dart
+// Complex operations made simple
+final skeleton = Skeleton.create(bindings, skeletonData);
+final animState = AnimationState.create(bindings, animStateData);
+
+// Arrays work like native Dart Lists
+final animations = skeleton.data.animations;
+final firstAnim = animations[0];
+final animCount = animations.length;
+
+// Functional programming support
+final animNames = animations.map((a) => a.name).toList();
+final longAnims = animations.where((a) => a.duration > 5.0).toList();
+
+// Enum usage
+skeleton.setSkin('goblin');
+animState.setAnimation(0, firstAnim, true);
+animState.setMixByName('idle', 'walk', 0.2);
+
+// Chaining operations
+skeleton.data.bones
+  .where((bone) => bone.parent != null)
+  .forEach((bone) => print('Child bone: ${bone.name}'));
+```
+
+## Build Integration
+
+### 1. Update `generate_bindings.sh`
+
+Add Dart wrapper generation to the existing script:
+
+```bash
+#!/bin/bash
+
+# ... existing FFI generation code ...
+
+# Generate Dart wrappers
+echo "Generating Dart wrapper classes..."
+cd src/spine-c/codegen
+npm run generate-dart
+
+echo "✅ All code generation completed!"
+```
+
+### 2. Add npm script to `spine-c/codegen/package.json`
+
+```json
+{
+  "scripts": {
+    "build": "tsc",
+    "generate": "npm run build && node dist/index.js",
+    "generate-dart": "npm run build && node dist/index.js --dart-only",
+    "test": "echo \"Error: no test specified\" && exit 1"
+  }
+}
+```
+
+### 3. Update `pubspec.yaml` dependencies
+
+The generated code will require:
+
+```yaml
+dependencies:
+  flutter:
+    sdk: flutter
+  ffi: ^2.1.0
+  # ... existing dependencies
+```
+
+## Benefits
+
+### 1. **Developer Experience**
+- **Type Safety**: Compile-time checking prevents FFI pointer errors
+- **IDE Support**: Full autocomplete, documentation, and refactoring
+- **Familiar API**: Uses standard Dart patterns (getters, setters, Lists)
+- **Memory Safety**: Automatic lifetime management with dispose patterns
+
+### 2. **Performance**
+- **Zero Copy**: Arrays provide lazy access to native data
+- **Minimal Overhead**: Thin wrappers over FFI calls
+- **Batch Operations**: Array operations can be optimized in native code
+
+### 3. **Maintainability**
+- **Automatic Updates**: Changes to C++ API automatically flow through
+- **Consistent Patterns**: All classes follow the same conventions
+- **Documentation**: Generated code includes comprehensive docs
+- **Testing**: Type-safe API makes unit testing straightforward
+
+### 4. **Reliability**
+- **No Manual Coding**: Eliminates human error in wrapper implementation
+- **Validated Generation**: Uses proven C type information
+- **Comprehensive Coverage**: Every C function gets a Dart wrapper
+
+## Implementation Timeline
+
+### Phase 1: Core Infrastructure (1-2 weeks)
+- [ ] Set up TypeScript generator project structure
+- [ ] Implement basic type mapping system
+- [ ] Create simple class generator for basic types
+- [ ] Test with a few example classes (Animation, Skeleton)
+
+### Phase 2: Array Support (1 week)
+- [ ] Implement generic Array<T> class
+- [ ] Add array detection and generation logic
+- [ ] Test array functionality with timeline/bone arrays
+
+### Phase 3: Enum Support (3-5 days)
+- [ ] Add enum detection and generation
+- [ ] Implement enum value mapping
+- [ ] Test with BlendMode and other enums
+
+### Phase 4: Advanced Features (1 week)
+- [ ] Add constructor detection and generation
+- [ ] Implement property getter/setter pairing
+- [ ] Add disposal pattern detection
+- [ ] Memory management best practices
+
+### Phase 5: Integration & Polish (3-5 days)
+- [ ] Integrate with existing build pipeline
+- [ ] Add comprehensive documentation
+- [ ] Create migration guide from manual FFI
+- [ ] Performance testing and optimization
+
+### Phase 6: Testing & Validation (1 week)
+- [ ] Unit tests for all generated wrappers
+- [ ] Integration tests with actual Spine files
+- [ ] Performance benchmarks vs raw FFI
+- [ ] Documentation and examples
+
+**Total Estimated Time: 4-6 weeks**
+
+## Future Enhancements
+
+### 1. **Advanced Memory Management**
+- Automatic disposal when objects go out of scope
+- Reference counting for shared objects
+- Memory leak detection in debug mode
+
+### 2. **Performance Optimizations**
+- Cached property access
+- Batch array operations
+- Native collection implementations
+
+### 3. **Developer Tools**
+- Debug visualizations for Spine objects
+- Memory usage monitoring
+- Performance profiling integration
+
+### 4. **API Enhancements**
+- Async/Future support for long operations
+- Stream-based event handling
+- Reactive programming patterns
+
+This comprehensive generator will transform the Spine Flutter experience from low-level FFI manipulation to a clean, type-safe, and performant Dart API that feels native to the Flutter ecosystem.

+ 4288 - 0
spine-flutter/lib/extensions.dart

@@ -0,0 +1,4288 @@
+///
+/// Spine Runtimes License Agreement
+/// Last updated April 5, 2025. Replaces all prior versions.
+///
+/// Copyright (c) 2013-2025, Esoteric Software LLC
+///
+/// Integration of the Spine Runtimes into software or otherwise creating
+/// derivative works of the Spine Runtimes is permitted under the terms and
+/// conditions of Section 2 of the Spine Editor License Agreement:
+/// http://esotericsoftware.com/spine-editor-license
+///
+/// Otherwise, it is permitted to integrate the Spine Runtimes into software
+/// or otherwise create derivative works of the Spine Runtimes (collectively,
+/// "Products"), provided that each user of the Products must obtain their own
+/// Spine Editor license and redistribution of the Products in any form must
+/// include this license and copyright notice.
+///
+/// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+/// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+/// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+/// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+/// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+/// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+/// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+/// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+/// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+/// THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+///
+
+import 'dart:convert' as convert;
+import 'dart:io';
+import 'dart:typed_data';
+import 'dart:ui';
+
+import 'package:flutter/foundation.dart' show kIsWeb;
+import 'package:flutter/material.dart' as material;
+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 'ffi_proxy.dart';
+import 'init.dart' if (dart.library.html) 'init_web.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'raw_image_provider.dart';
+
+export 'spine_widget.dart';
+
+late SpineFlutterBindings _bindings;
+late Allocator _allocator;
+
+Future<void> initSpineFlutter({bool useStaticLinkage = false, bool enableMemoryDebugging = false}) async {
+  final ffi = await initSpineFlutterFFI(useStaticLinkage);
+  _bindings = SpineFlutterBindings(ffi.dylib);
+  _allocator = ffi.allocator;
+  if (enableMemoryDebugging) _bindings.spine_enable_debug_extension(true);
+  return;
+}
+
+int majorVersion() => _bindings.spine_major_version();
+
+int minorVersion() => _bindings.spine_minor_version();
+
+void reportLeaks() => _bindings.spine_report_leaks();
+
+/// A color made of red, green, blue, and alpha components,
+/// ranging from 0-1.
+class Color {
+  double r;
+  double g;
+  double b;
+  double a;
+
+  Color(this.r, this.g, this.b, this.a);
+}
+
+/// Bounds denoted by the top left corner coordinates [x] and [y]
+/// and the [width] and [height].
+class Bounds {
+  double x;
+  double y;
+  double width;
+  double height;
+
+  Bounds(this.x, this.y, this.width, this.height);
+}
+
+/// A two-dimensional vector with [x] and [y] components.
+class Vec2 {
+  double x;
+  double y;
+
+  Vec2(this.x, this.y);
+}
+
+/// Atlas data loaded from a `.atlas` file and its corresponding `.png` files. For each atlas image,
+/// a corresponding [Image] and [Paint] is constructed, which are used when rendering a skeleton
+/// that uses this atlas.
+///
+/// Use the static methods [fromAsset], [fromFile], and [fromHttp] to load an atlas. Call [dispose]
+/// when the atlas is no longer in use to release its resources.
+class Atlas {
+  static FilterQuality filterQuality = FilterQuality.none;
+  final spine_atlas _atlas;
+  final List<Image> atlasPages;
+  final List<Map<BlendMode, Paint>> atlasPagePaints;
+  bool _disposed;
+
+  Atlas._(this._atlas, this.atlasPages, this.atlasPagePaints) : _disposed = false;
+
+  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(allocator: _allocator);
+    final atlas = _bindings.spine_atlas_load(atlasDataNative.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");
+    }
+
+    final atlasDir = path.dirname(atlasFileName);
+    List<Image> atlasPages = [];
+    List<Map<BlendMode, Paint>> atlasPagePaints = [];
+    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 = "$atlasDir/${atlasPageFile.toDartString()}";
+      var imageData = await loadFile(imagePath);
+      final Codec codec = await instantiateImageCodec(imageData);
+      final FrameInfo frameInfo = await codec.getNextFrame();
+      final Image image = frameInfo.image;
+      atlasPages.add(image);
+      Map<BlendMode, Paint> paints = {};
+      for (final blendMode in BlendMode.values) {
+        paints[blendMode] = Paint()
+          ..shader = ImageShader(
+            image,
+            TileMode.clamp,
+            TileMode.clamp,
+            Matrix4.identity().storage,
+            filterQuality: Atlas.filterQuality,
+          )
+          ..isAntiAlias = true
+          ..blendMode = blendMode.canvasBlendMode;
+      }
+      atlasPagePaints.add(paints);
+    }
+
+    return Atlas._(atlas, atlasPages, atlasPagePaints);
+  }
+
+  /// Loads an [Atlas] from the file [atlasFileName] in the root bundle or the optionally provided [bundle].
+  ///
+  /// Throws an [Exception] in case the atlas could not be loaded.
+  static Future<Atlas> fromAsset(String atlasFileName, {AssetBundle? bundle}) async {
+    bundle ??= rootBundle;
+    return _load(atlasFileName, (file) async => (await bundle!.load(file)).buffer.asUint8List());
+  }
+
+  /// Loads an [Atlas] from the file [atlasFileName].
+  ///
+  /// Throws an [Exception] in case the atlas could not be loaded.
+  static Future<Atlas> fromFile(String atlasFileName) async {
+    return _load(atlasFileName, (file) => File(file).readAsBytes());
+  }
+
+  /// Loads an [Atlas] from the URL [atlasURL].
+  ///
+  /// Throws an [Exception] in case the atlas could not be loaded.
+  static Future<Atlas> fromHttp(String atlasURL) async {
+    return _load(atlasURL, (file) async {
+      return (await http.get(Uri.parse(file))).bodyBytes;
+    });
+  }
+
+  /// Disposes the (native) resources of this atlas. The atlas can no longer be
+  /// used after calling this function. Only the first call to this method will
+  /// have an effect. Subsequent calls are ignored.
+  void dispose() {
+    if (_disposed) return;
+    _disposed = true;
+    _bindings.spine_atlas_dispose(_atlas);
+    for (final image in atlasPages) {
+      image.dispose();
+    }
+    atlasPagePaints.clear();
+  }
+}
+
+/// Skeleton data loaded from a skeleton `.json` or `.skel` file. Contains bones, slots, constraints,
+/// skins, animations, and so on making up a skeleton. Also contains meta data such as the skeletons
+/// setup pose bounding box, the Spine editor version it was exported from, and so on.
+///
+/// Skeleton data is stateless. Stateful [Skeleton] instances can be constructed from a [SkeletonData] instance.
+/// A single [SkeletonData] instance can be shared by multiple [Skeleton] instances.
+///
+/// Use the static methods [fromJson], [fromBinary], [fromAsset], [fromFile], and [fromURL] to load
+/// skeleton data. Call [dispose] when the skeleton data is no longer in use to free its resources.
+///
+/// See [Data objects](http://esotericsoftware.com/spine-runtime-architecture#Data-objects) in the Spine
+/// Runtimes Guide.
+class SkeletonData {
+  final spine_skeleton_data _data;
+  bool _disposed;
+
+  SkeletonData._(this._data) : _disposed = false;
+
+  /// Loads a [SkeletonData] from the [json] string, using the provided [atlas] to resolve attachment
+  /// images.
+  ///
+  /// Throws an [Exception] in case the atlas could not be loaded.
+  static SkeletonData fromJson(Atlas atlas, String json) {
+    final jsonNative = json.toNativeUtf8(allocator: _allocator);
+    final path = "".toNativeUtf8(allocator: _allocator);
+    final result = _bindings.spine_skeleton_data_load_json(atlas._atlas, jsonNative.cast(), path.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();
+      _bindings.spine_skeleton_data_result_dispose(result);
+      throw Exception("Couldn't load skeleton data: $message");
+    }
+    var data = SkeletonData._(_bindings.spine_skeleton_data_result_get_data(result));
+    _bindings.spine_skeleton_data_result_dispose(result);
+    return data;
+  }
+
+  /// Loads a [SkeletonData] from the [binary] skeleton data, using the provided [atlas] to resolve attachment
+  /// images.
+  ///
+  /// Throws an [Exception] in case the skeleton data could not be loaded.
+  static SkeletonData fromBinary(Atlas atlas, Uint8List binary) {
+    final Pointer<Uint8> binaryNative = _allocator.allocate(binary.lengthInBytes);
+    binaryNative.asTypedList(binary.lengthInBytes).setAll(0, binary);
+    final path = "".toNativeUtf8(allocator: _allocator);
+    final result = _bindings.spine_skeleton_data_load_binary(atlas._atlas, binaryNative.cast(), binary.lengthInBytes, path.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();
+      _bindings.spine_skeleton_data_result_dispose(result);
+      throw Exception("Couldn't load skeleton data: $message");
+    }
+    var data = SkeletonData._(_bindings.spine_skeleton_data_result_get_data(result));
+    _bindings.spine_skeleton_data_result_dispose(result);
+    return data;
+  }
+
+  /// Loads a [SkeletonData] from the file [skeletonFile] in the root bundle or the optionally provided [bundle].
+  /// Uses the provided [atlas] to resolve attachment images.
+  ///
+  /// Throws an [Exception] in case the skeleton data could not be loaded.
+  static Future<SkeletonData> fromAsset(Atlas atlas, String skeletonFile, {AssetBundle? bundle}) async {
+    bundle ??= rootBundle;
+    if (skeletonFile.endsWith(".json")) {
+      return fromJson(atlas, await bundle.loadString(skeletonFile));
+    } else {
+      return fromBinary(atlas, (await bundle.load(skeletonFile)).buffer.asUint8List());
+    }
+  }
+
+  /// Loads a [SkeletonData] from the file [skeletonFile]. Uses the provided [atlas] to resolve attachment images.
+  ///
+  /// Throws an [Exception] in case the skeleton data could not be loaded.
+  static Future<SkeletonData> fromFile(Atlas atlas, String skeletonFile) async {
+    if (skeletonFile.endsWith(".json")) {
+      return fromJson(atlas, convert.utf8.decode(await File(skeletonFile).readAsBytes()));
+    } else {
+      return fromBinary(atlas, await File(skeletonFile).readAsBytes());
+    }
+  }
+
+  /// Loads a [SkeletonData] from the URL [skeletonURL]. Uses the provided [atlas] to resolve attachment images.
+  ///
+  /// Throws an [Exception] in case the skeleton data could not be loaded.
+  static Future<SkeletonData> fromHttp(Atlas atlas, String skeletonURL) async {
+    if (skeletonURL.endsWith(".json")) {
+      return fromJson(atlas, convert.utf8.decode((await http.get(Uri.parse(skeletonURL))).bodyBytes));
+    } else {
+      return fromBinary(atlas, (await http.get(Uri.parse(skeletonURL))).bodyBytes);
+    }
+  }
+
+  /// The skeleton's bones, sorted parent first. The root bone is always the first bone.
+  List<BoneData> getBones() {
+    final bones = _bindings.spine_skeleton_data_get_bones(_data);
+
+    final List<BoneData> bones = [];
+    final numBones = _bindings.spine_skeleton_data_get_num_bones(_data);
+    final nativeBones = _bindings.spine_skeleton_data_get_bones(_data);
+    for (int i = 0; i < numBones; i++) {
+      bones.add(BoneData._(nativeBones[i]));
+    }
+    return bones;
+  }
+
+  /// 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(allocator: _allocator);
+    final bone = _bindings.spine_skeleton_data_find_bone(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (bone.address == nullptr.address) return null;
+    return BoneData._(bone);
+  }
+
+  /// The skeleton's slots.
+  List<SlotData> getSlots() {
+    final List<SlotData> slots = [];
+    final numSlots = _bindings.spine_skeleton_data_get_num_slots(_data);
+    final nativeSlots = _bindings.spine_skeleton_data_get_slots(_data);
+    for (int i = 0; i < numSlots; i++) {
+      slots.add(SlotData._(nativeSlots[i]));
+    }
+    return slots;
+  }
+
+  /// 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(allocator: _allocator);
+    final slot = _bindings.spine_skeleton_data_find_slot(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (slot.address == nullptr.address) return null;
+    return SlotData._(slot);
+  }
+
+  /// All skins, including the default skin.
+  List<Skin> getSkins() {
+    final List<Skin> skins = [];
+    final numSkins = _bindings.spine_skeleton_data_get_num_skins(_data);
+    final nativeSkins = _bindings.spine_skeleton_data_get_skins(_data);
+    for (int i = 0; i < numSkins; i++) {
+      skins.add(Skin._(nativeSkins[i]));
+    }
+    return skins;
+  }
+
+  /// The skeleton's default skin. By default this skin contains all attachments that were not in a skin in Spine.
+  Skin? getDefaultSkin() {
+    final skin = _bindings.spine_skeleton_data_get_default_skin(_data);
+    if (skin.address == nullptr.address) return null;
+    return Skin._(skin);
+  }
+
+  void setDefaultSkin(Skin? skin) {
+    if (skin == null) {
+      _bindings.spine_skeleton_data_set_default_skin(_data, nullptr);
+    } else {
+      _bindings.spine_skeleton_data_set_default_skin(_data, skin._skin);
+    }
+  }
+
+  /// 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(allocator: _allocator);
+    final skin = _bindings.spine_skeleton_data_find_skin(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (skin.address == nullptr.address) return null;
+    return Skin._(skin);
+  }
+
+  /// The skeleton's events.
+  List<EventData> getEvents() {
+    final List<EventData> events = [];
+    final numEvents = _bindings.spine_skeleton_data_get_num_events(_data);
+    final nativeEvents = _bindings.spine_skeleton_data_get_events(_data);
+    for (int i = 0; i < numEvents; i++) {
+      events.add(EventData._(nativeEvents[i]));
+    }
+    return events;
+  }
+
+  /// 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(allocator: _allocator);
+    final event = _bindings.spine_skeleton_data_find_event(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (event.address == nullptr.address) return null;
+    return EventData._(event);
+  }
+
+  /// The skeleton's animations.
+  List<Animation> getAnimations() {
+    final List<Animation> events = [];
+    final numAnimation = _bindings.spine_skeleton_data_get_num_animations(_data);
+    final nativeAnimations = _bindings.spine_skeleton_data_get_animations(_data);
+    for (int i = 0; i < numAnimation; i++) {
+      events.add(Animation._(nativeAnimations[i]));
+    }
+    return events;
+  }
+
+  /// 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(allocator: _allocator);
+    final animation = _bindings.spine_skeleton_data_find_animation(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (animation.address == nullptr.address) return null;
+    return Animation._(animation);
+  }
+
+  /// The skeleton's IK constraints.
+  List<IkConstraintData> getIkConstraints() {
+    final List<IkConstraintData> constraints = [];
+    final numConstraints = _bindings.spine_skeleton_data_get_num_ik_constraints(_data);
+    final nativeConstraints = _bindings.spine_skeleton_data_get_ik_constraints(_data);
+    for (int i = 0; i < numConstraints; i++) {
+      constraints.add(IkConstraintData._(nativeConstraints[i]));
+    }
+    return constraints;
+  }
+
+  /// 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(allocator: _allocator);
+    final constraint = _bindings.spine_skeleton_data_find_ik_constraint(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (constraint.address == nullptr.address) return null;
+    return IkConstraintData._(constraint);
+  }
+
+  /// The skeleton's transform constraints.
+  List<TransformConstraint> getTransformConstraints() {
+    final List<TransformConstraint> constraints = [];
+    final numConstraints = _bindings.spine_skeleton_data_get_num_transform_constraints(_data);
+    final nativeConstraints = _bindings.spine_skeleton_data_get_transform_constraints(_data);
+    for (int i = 0; i < numConstraints; i++) {
+      constraints.add(TransformConstraint._(nativeConstraints[i].cast()));
+    }
+    return constraints;
+  }
+
+  /// 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(allocator: _allocator);
+    final constraint = _bindings.spine_skeleton_data_find_transform_constraint(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (constraint.address == nullptr.address) return null;
+    return TransformConstraintData._(constraint);
+  }
+
+  /// The skeleton's path constraints.
+  List<PathConstraintData> getPathConstraints() {
+    final List<PathConstraintData> constraints = [];
+    final numConstraints = _bindings.spine_skeleton_data_get_num_path_constraints(_data);
+    final nativeConstraints = _bindings.spine_skeleton_data_get_path_constraints(_data);
+    for (int i = 0; i < numConstraints; i++) {
+      constraints.add(PathConstraintData._(nativeConstraints[i]));
+    }
+    return constraints;
+  }
+
+  /// 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(allocator: _allocator);
+    final constraint = _bindings.spine_skeleton_data_find_path_constraint(_data, nativeName.cast());
+    _allocator.free(nativeName);
+    if (constraint.address == nullptr.address) return null;
+    return PathConstraintData._(constraint);
+  }
+
+  /// The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been
+  /// set.
+  String? getName() {
+    Pointer<Utf8> name = _bindings.spine_skeleton_data_get_name(_data).cast();
+    if (name.address == nullptr.address) return null;
+    return name.toDartString();
+  }
+
+  /// The X coordinate of the skeleton's axis aligned bounding box in the setup pose.
+  double getX() {
+    return _bindings.spine_skeleton_data_get_x(_data);
+  }
+
+  void setX(double x) {
+    _bindings.spine_skeleton_data_set_x(_data, x);
+  }
+
+  /// The Y coordinate of the skeleton's axis aligned bounding box in the setup pose.
+  double getY() {
+    return _bindings.spine_skeleton_data_get_y(_data);
+  }
+
+  void setY(double y) {
+    _bindings.spine_skeleton_data_set_x(_data, y);
+  }
+
+  /// The width of the skeleton's axis aligned bounding box in the setup pose.
+  double getWidth() {
+    return _bindings.spine_skeleton_data_get_width(_data);
+  }
+
+  void setWidth(double width) {
+    _bindings.spine_skeleton_data_set_width(_data, width);
+  }
+
+  /// The height of the skeleton's axis aligned bounding box in the setup pose.
+  double getHeight() {
+    return _bindings.spine_skeleton_data_get_height(_data);
+  }
+
+  void setHeight(double height) {
+    _bindings.spine_skeleton_data_set_height(_data, height);
+  }
+
+  /// The Spine version used to export the skeleton data.
+  String? getVersion() {
+    Pointer<Utf8> name = _bindings.spine_skeleton_data_get_version(_data).cast();
+    if (name.address == nullptr.address) return null;
+    return name.toDartString();
+  }
+
+  /// The skeleton data hash. This value will change if any of the skeleton data has changed.
+  String? getHash() {
+    Pointer<Utf8> name = _bindings.spine_skeleton_data_get_hash(_data).cast();
+    if (name.address == nullptr.address) return null;
+    return name.toDartString();
+  }
+
+  /// The path to the images directory as defined in Spine, or null if nonessential data was not exported.
+  String? getImagesPath() {
+    Pointer<Utf8> name = _bindings.spine_skeleton_data_get_images_path(_data).cast();
+    if (name.address == nullptr.address) return null;
+    return name.toDartString();
+  }
+
+  /// The path to the audio directory as defined in Spine, or null if nonessential data was not exported.
+  String? getAudioPath() {
+    Pointer<Utf8> name = _bindings.spine_skeleton_data_get_audio_path(_data).cast();
+    if (name.address == nullptr.address) return null;
+    return name.toDartString();
+  }
+
+  /// The dopesheet FPS in Spine, or zero if nonessential data was not exported.
+  double getFps() {
+    return _bindings.spine_skeleton_data_get_fps(_data);
+  }
+
+  /// Disposes the (native) resources of this skeleton data. The skeleton data can no longer be
+  /// used after calling this function. Only the first call to this method will
+  /// have an effect. Subsequent calls are ignored.
+  void dispose() {
+    if (_disposed) return;
+    _disposed = true;
+    _bindings.spine_skeleton_data_dispose(_data);
+  }
+}
+
+/// Determines how images are blended with existing pixels when drawn. See [Blending](http://esotericsoftware.com/spine-slots#Blending) in
+/// the Spine User Guide.
+enum BlendMode {
+  normal(0, rendering.BlendMode.srcOver),
+  additive(1, rendering.BlendMode.plus),
+  multiply(2, rendering.BlendMode.multiply),
+  screen(3, rendering.BlendMode.screen);
+
+  final int value;
+  final rendering.BlendMode canvasBlendMode;
+
+  const BlendMode(this.value, this.canvasBlendMode);
+}
+
+/// Determines how a bone inherits world transforms from parent bones. See [Transform inheritance](esotericsoftware.com/spine-bones#Transform-inheritance)
+/// in the Spine User Guide.
+enum Inherit {
+  normal(0),
+  onlyTranslation(1),
+  noRotationOrReflection(2),
+  noScale(3),
+  noScaleOrReflection(4);
+
+  final int value;
+
+  const Inherit(this.value);
+}
+
+/// Determines how physics and other non-deterministic updates are applied.
+enum Physics {
+  none(0),
+  reset(1),
+  update(2),
+  pose(3);
+
+  final int value;
+
+  const Physics(this.value);
+}
+
+/// Controls how the first bone is positioned along the path.
+///
+/// See [Position mode](http://esotericsoftware.com/spine-path-constraints#Position-mode) in the Spine User Guide.
+enum PositionMode {
+  fixed(0),
+  percent(1);
+
+  final int value;
+
+  const PositionMode(this.value);
+}
+
+/// Controls how bones after the first bone are positioned along the path.
+///
+/// See [Spacing mode](http://esotericsoftware.com/spine-path-constraints#Spacing-mode) in the Spine User Guide.
+enum SpacingMode {
+  length(0),
+  fixed(1),
+  percent(2),
+  proportional(3);
+
+  final int value;
+
+  const SpacingMode(this.value);
+}
+
+/// Controls how bones are rotated, translated, and scaled to match the path.
+///
+/// See [Rotate mode](https://esotericsoftware.com/spine-path-constraints#Rotate-Mix) in the Spine User Guide.
+enum RotateMode {
+  tangent(0),
+  chain(1),
+  chainScale(2);
+
+  final int value;
+
+  const RotateMode(this.value);
+}
+
+/// Stores the setup pose for a [Bone].
+class BoneData {
+  final spine_bone_data _data;
+
+  BoneData._(this._data);
+
+  /// The index of the bone in [Skeleton.getBones].
+  int getIndex() {
+    return _bindings.spine_bone_data_get_index(_data);
+  }
+
+  /// The name of the bone, which is unique across all bones in the skeleton.
+  String getName() {
+    Pointer<Utf8> name = _bindings.spine_bone_data_get_name(_data).cast();
+    return name.toDartString();
+  }
+
+  /// The parent bone or `null` if this is the root bone.
+  BoneData? getParent() {
+    final parent = _bindings.spine_bone_data_get_parent(_data);
+    if (parent.address == nullptr.address) return null;
+    return BoneData._(parent);
+  }
+
+  /// The bone's length.
+  double getLength() {
+    return _bindings.spine_bone_data_get_length(_data);
+  }
+
+  void setLength(double length) {
+    _bindings.spine_bone_data_set_length(_data, length);
+  }
+
+  /// The local x translation.
+  double getX() {
+    return _bindings.spine_bone_data_get_x(_data);
+  }
+
+  void setX(double x) {
+    _bindings.spine_bone_data_set_x(_data, x);
+  }
+
+  /// The local y translation.
+  double getY() {
+    return _bindings.spine_bone_data_get_y(_data);
+  }
+
+  void setY(double y) {
+    _bindings.spine_bone_data_set_y(_data, y);
+  }
+
+  /// The local rotation in degrees.
+  double getRotation() {
+    return _bindings.spine_bone_data_get_rotation(_data);
+  }
+
+  void setRotation(double rotation) {
+    _bindings.spine_bone_data_set_rotation(_data, rotation);
+  }
+
+  /// The local scaleX.
+  double getScaleX() {
+    return _bindings.spine_bone_data_get_scale_x(_data);
+  }
+
+  void setScaleX(double scaleX) {
+    _bindings.spine_bone_data_set_scale_x(_data, scaleX);
+  }
+
+  /// The local scaleY.
+  double getScaleY() {
+    return _bindings.spine_bone_data_get_scale_y(_data);
+  }
+
+  void setScaleY(double scaleY) {
+    _bindings.spine_bone_data_set_scale_y(_data, scaleY);
+  }
+
+  /// The local shearX.
+  double getShearX() {
+    return _bindings.spine_bone_data_get_shear_x(_data);
+  }
+
+  void setShearX(double shearX) {
+    _bindings.spine_bone_data_set_shear_x(_data, shearX);
+  }
+
+  /// The local shearY.
+  double getShearY() {
+    return _bindings.spine_bone_data_get_shear_y(_data);
+  }
+
+  void setShearY(double shearY) {
+    _bindings.spine_bone_data_set_shear_y(_data, shearY);
+  }
+
+  /// The [Inherit] for how parent world transforms affect this bone.
+  Inherit getInherit() {
+    final nativeMode = _bindings.spine_bone_data_get_inherit(_data);
+    return Inherit.values[nativeMode];
+  }
+
+  void setInherit(Inherit inherit) {
+    _bindings.spine_bone_data_set_inherit(_data, inherit.value);
+  }
+
+  /// When true, [Skeleton.updateWorldTransform] only updates this bone if the [Skeleton.getSkin] contains this bone.
+  ///
+  /// See [Skin.getBones].
+  bool isSkinRequired() {
+    return _bindings.spine_bone_data_is_skin_required(_data) == -1;
+  }
+
+  void setIsSkinRequired(bool isSkinRequired) {
+    _bindings.spine_bone_data_set_is_skin_required(_data, isSkinRequired ? -1 : 0);
+  }
+
+  /// The [Color] of the bone as it was in Spine, or a default color if nonessential data was not exported. Bones are not usually
+  /// rendered at runtime.
+  Color getColor() {
+    final color = _bindings.spine_bone_data_get_color(_data);
+    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) {
+    _bindings.spine_bone_data_set_color(_data, r, g, b, a);
+  }
+
+  @override
+  String toString() {
+    return getName();
+  }
+}
+
+/// Stores a bone's current pose.
+///
+///  A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a
+///  local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a
+///  constraint or application code modifies the world transform after it was computed from the local transform.
+class Bone {
+  final spine_bone _bone;
+
+  Bone._(this._bone);
+
+  /// Assume y-axis pointing down for all calculations.
+  static void setIsYDown(bool isYDown) {
+    _bindings.spine_bone_set_is_y_down(isYDown ? -1 : 0);
+  }
+
+  static bool getIsYDown() {
+    return _bindings.spine_bone_get_is_y_down() == 1;
+  }
+
+  /// Computes the world transform using the parent bone and this bone's local applied transform.
+  void update() {
+    _bindings.spine_bone_update(_bone);
+  }
+
+  /// Computes the world transform using the parent bone and this bone's local transform.
+  ///
+  /// See [updateWorldTransformWith].
+  void updateWorldTransform() {
+    _bindings.spine_bone_update_world_transform(_bone);
+  }
+
+  /// Computes the world transform using the parent bone and the specified local transform. The applied transform is set to the
+  /// specified local transform. Child bones are not updated.
+  ///
+  /// See [World transform](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
+  /// Runtimes Guide.
+  void updateWorldTransformWith(
+    double x,
+    double y,
+    double rotation,
+    double scaleX,
+    double scaleY,
+    double shearX,
+    double shearY,
+  ) {
+    _bindings.spine_bone_update_world_transform_with(_bone, x, y, rotation, scaleX, scaleY, shearX, shearY);
+  }
+
+  /// Computes the applied transform values from the world transform.
+  ///
+  /// If the world transform is modified (by a constraint, [rotateWorld], etc) then this method should be called so
+  /// the applied transform matches the world transform. The applied transform may be needed by other code (eg to apply another
+  /// constraint).
+  ///
+  /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The applied transform after
+  /// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical.
+  void updateAppliedTransform() {
+    _bindings.spine_bone_update_applied_transform(_bone);
+  }
+
+  /// Sets this bone's local transform to the setup pose.
+  void setToSetupPose() {
+    _bindings.spine_bone_set_to_setup_pose(_bone);
+  }
+
+  /// Transforms a point from world coordinates to the bone's local coordinates.
+  Vec2 worldToLocal(double worldX, double worldY) {
+    final local = _bindings.spine_bone_world_to_local(_bone, worldX, worldY);
+    final result = Vec2(_bindings.spine_vector_get_x(local), _bindings.spine_vector_get_y(local));
+    return result;
+  }
+
+  /// Transforms a point from the bone's local coordinates to world coordinates.
+  Vec2 localToWorld(double localX, double localY) {
+    final world = _bindings.spine_bone_local_to_world(_bone, localX, localY);
+    final result = Vec2(_bindings.spine_vector_get_x(world), _bindings.spine_vector_get_y(world));
+    return result;
+  }
+
+  /// Transforms a world rotation to a local rotation.
+  double worldToLocalRotation(double worldRotation) {
+    return _bindings.spine_bone_world_to_local_rotation(_bone, worldRotation);
+  }
+
+  /// Transforms a local rotation to a world rotation.
+  double localToWorldRotation(double localRotation) {
+    return _bindings.spine_bone_local_to_world_rotation(_bone, localRotation);
+  }
+
+  /// Rotates the world transform the specified amount.
+  ///
+  /// After changes are made to the world transform, [updateAppliedTransform] should be called and [update] will
+  /// need to be called on any child bones, recursively.
+  void rotateWorld(double degrees) {
+    _bindings.spine_bone_rotate_world(_bone, degrees);
+  }
+
+  double getWorldToLocalRotationX() {
+    return _bindings.spine_bone_get_world_rotation_x(_bone);
+  }
+
+  double getWorldToLocalRotationY() {
+    return _bindings.spine_bone_get_world_to_local_rotation_y(_bone);
+  }
+
+  /// The bone's setup pose data.
+  BoneData getData() {
+    return BoneData._(_bindings.spine_bone_get_data(_bone));
+  }
+
+  /// The skeleton this bone belongs to.
+  Skeleton getSkeleton() {
+    return Skeleton._(_bindings.spine_bone_get_skeleton(_bone));
+  }
+
+  /// The parent bone, or null if this is the root bone.
+  Bone? getParent() {
+    final parent = _bindings.spine_bone_get_parent(_bone);
+    if (parent.address == nullptr.address) return null;
+    return Bone._(parent);
+  }
+
+  /// The immediate children of this bone.
+  List<Bone> getChildren() {
+    List<Bone> children = [];
+    final numChildren = _bindings.spine_bone_get_num_children(_bone);
+    final nativeChildren = _bindings.spine_bone_get_children(_bone);
+    for (int i = 0; i < numChildren; i++) {
+      children.add(Bone._(nativeChildren[i]));
+    }
+    return children;
+  }
+
+  /// The local x translation.
+  double getX() {
+    return _bindings.spine_bone_get_x(_bone);
+  }
+
+  void setX(double x) {
+    _bindings.spine_bone_set_x(_bone, x);
+  }
+
+  /// The local y translation.
+  double getY() {
+    return _bindings.spine_bone_get_y(_bone);
+  }
+
+  void setY(double y) {
+    _bindings.spine_bone_set_y(_bone, y);
+  }
+
+  /// The local rotation in degrees, counter clockwise.
+  double getRotation() {
+    return _bindings.spine_bone_get_rotation(_bone);
+  }
+
+  void setRotation(double rotation) {
+    _bindings.spine_bone_set_rotation(_bone, rotation);
+  }
+
+  /// The local scaleX.
+  double getScaleX() {
+    return _bindings.spine_bone_get_scale_x(_bone);
+  }
+
+  void setScaleX(double scaleX) {
+    _bindings.spine_bone_set_scale_x(_bone, scaleX);
+  }
+
+  /// The local scaleY.
+  double getScaleY() {
+    return _bindings.spine_bone_get_scale_y(_bone);
+  }
+
+  void setScaleY(double scaleY) {
+    _bindings.spine_bone_set_scale_y(_bone, scaleY);
+  }
+
+  /// The local shearX.
+  double getShearX() {
+    return _bindings.spine_bone_get_shear_x(_bone);
+  }
+
+  void setShearX(double shearX) {
+    _bindings.spine_bone_set_shear_x(_bone, shearX);
+  }
+
+  /// The local shearY.
+  double getShearY() {
+    return _bindings.spine_bone_get_shear_y(_bone);
+  }
+
+  void setShearY(double shearY) {
+    _bindings.spine_bone_set_shear_y(_bone, shearY);
+  }
+
+  /// The applied local x translation.
+  double getAX() {
+    return _bindings.spine_bone_get_a_x(_bone);
+  }
+
+  void setAX(double x) {
+    _bindings.spine_bone_set_a_x(_bone, x);
+  }
+
+  /// The applied local y translation.
+  double getAY() {
+    return _bindings.spine_bone_get_a_y(_bone);
+  }
+
+  void setAY(double y) {
+    _bindings.spine_bone_set_a_y(_bone, y);
+  }
+
+  /// The applied local rotation in degrees, counter clockwise.
+  double getAppliedRotation() {
+    return _bindings.spine_bone_get_applied_rotation(_bone);
+  }
+
+  void setAppliedRotation(double rotation) {
+    _bindings.spine_bone_set_applied_rotation(_bone, rotation);
+  }
+
+  /// The applied local scaleX.
+  double getAScaleX() {
+    return _bindings.spine_bone_get_a_scale_x(_bone);
+  }
+
+  void setAScaleX(double scaleX) {
+    _bindings.spine_bone_set_a_scale_x(_bone, scaleX);
+  }
+
+  /// The applied local scaleY.
+  double getAScaleY() {
+    return _bindings.spine_bone_get_a_scale_y(_bone);
+  }
+
+  void setAScaleY(double scaleY) {
+    _bindings.spine_bone_set_a_scale_y(_bone, scaleY);
+  }
+
+  /// The applied local shearX.
+  double getAShearX() {
+    return _bindings.spine_bone_get_a_shear_x(_bone);
+  }
+
+  void setAShearX(double shearX) {
+    _bindings.spine_bone_set_a_shear_x(_bone, shearX);
+  }
+
+  /// The applied local shearY.
+  double getAShearY() {
+    return _bindings.spine_bone_get_a_shear_y(_bone);
+  }
+
+  void setAShearY(double shearY) {
+    _bindings.spine_bone_set_a_shear_y(_bone, shearY);
+  }
+
+  /// Part of the world transform matrix for the X axis. If changed, [updateAppliedTransform] should be called.
+  double getA() {
+    return _bindings.spine_bone_get_a(_bone);
+  }
+
+  void setA(double a) {
+    _bindings.spine_bone_set_a(_bone, a);
+  }
+
+  /// Part of the world transform matrix for the Y axis. If changed, [updateAppliedTransform] should be called.
+  double getB() {
+    return _bindings.spine_bone_get_b(_bone);
+  }
+
+  void setB(double b) {
+    _bindings.spine_bone_set_b(_bone, b);
+  }
+
+  /// Part of the world transform matrix for the X axis. If changed, [updateAppliedTransform] should be called.
+  double getC() {
+    return _bindings.spine_bone_get_c(_bone);
+  }
+
+  void setC(double c) {
+    _bindings.spine_bone_set_c(_bone, c);
+  }
+
+  /// Part of the world transform matrix for the Y axis. If changed, [updateAppliedTransform] should be called.
+  double getD() {
+    return _bindings.spine_bone_get_d(_bone);
+  }
+
+  void setD(double d) {
+    _bindings.spine_bone_set_a(_bone, d);
+  }
+
+  /// The world X position. If changed, [updateAppliedTransform] should be called.
+  double getWorldX() {
+    return _bindings.spine_bone_get_world_x(_bone);
+  }
+
+  void setWorldX(double worldX) {
+    _bindings.spine_bone_set_world_x(_bone, worldX);
+  }
+
+  /// The world Y position. If changed, [updateAppliedTransform] should be called.
+  double getWorldY() {
+    return _bindings.spine_bone_get_world_y(_bone);
+  }
+
+  void setWorldY(double worldY) {
+    _bindings.spine_bone_set_world_y(_bone, worldY);
+  }
+
+  /// The world rotation for the X axis, calculated using [getA] and [getC].
+  double getWorldRotationX() {
+    return _bindings.spine_bone_get_world_rotation_x(_bone);
+  }
+
+  /// The world rotation for the Y axis, calculated using [getB] and [getD].
+  double getWorldRotationY() {
+    return _bindings.spine_bone_get_world_rotation_y(_bone);
+  }
+
+  /// The magnitude (always positive) of the world scale X, calculated using [getA] and [getC].
+  double getWorldScaleX() {
+    return _bindings.spine_bone_get_world_scale_x(_bone);
+  }
+
+  /// The magnitude (always positive) of the world scale Y, calculated using [getB] and [getD].
+  double getWorldScaleY() {
+    return _bindings.spine_bone_get_world_scale_y(_bone);
+  }
+
+  /// Returns false when the bone has not been computed because [BoneData.getSkinRequired] is true and the
+  /// active skin (see [Skeleton.getSkin]) does not contain this bone (see [Skin.getBones]).
+  bool isActive() {
+    return _bindings.spine_bone_get_is_active(_bone) == -1;
+  }
+
+  void setIsActive(bool isActive) {
+    _bindings.spine_bone_set_is_active(_bone, isActive ? -1 : 0);
+  }
+}
+
+/// Stores the setup pose for a [Slot].
+class SlotData {
+  final spine_slot_data _data;
+
+  SlotData._(this._data);
+
+  /// The index of the slot in [Skeleton.getSlots].
+  int getIndex() {
+    return _bindings.spine_slot_data_get_index(_data);
+  }
+
+  /// The name of the slot, which is unique across all slots in the skeleton.
+  String getName() {
+    final Pointer<Utf8> value = _bindings.spine_slot_data_get_name(_data).cast();
+    return value.toDartString();
+  }
+
+  /// The bone this slot belongs to.
+  BoneData getBoneData() {
+    return BoneData._(_bindings.spine_slot_data_get_bone_data(_data));
+  }
+
+  /// The [Color] used to tint the slot's attachment. If [hasDarkColor] is true, this is used as the light color for two
+  /// color tinting.
+  Color getColor() {
+    final color = _bindings.spine_slot_data_get_color(_data);
+    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) {
+    _bindings.spine_slot_data_set_color(_data, r, g, b, a);
+  }
+
+  /// The dark color used to tint the slot's attachment for two color tinting, if [hasDarkColor] is true. The dark
+  /// color's alpha is not used.
+  Color getDarkColor() {
+    final color = _bindings.spine_slot_data_get_dark_color(_data);
+    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) {
+    _bindings.spine_slot_data_set_dark_color(_data, r, g, b, a);
+  }
+
+  /// Returns whether this slot has a dark color set for two color tinting.
+  bool hasDarkColor() {
+    return _bindings.spine_slot_data_has_dark_color(_data) == -1;
+  }
+
+  void setHasDarkColor(bool hasDarkColor) {
+    _bindings.spine_slot_data_set_has_dark_color(_data, hasDarkColor ? -1 : 0);
+  }
+
+  /// The name of the attachment that is visible for this slot in the setup pose, or null if no attachment is visible.
+  String getAttachmentName() {
+    final Pointer<Utf8> value = _bindings.spine_slot_data_get_attachment_name(_data).cast();
+    return value.toDartString();
+  }
+
+  void setAttachmentName(String attachmentName) {
+    final nativeName = attachmentName.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_slot_data_set_attachment_name(_data, nativeName.cast());
+    _allocator.free(nativeName);
+  }
+
+  /// The [BlendMode] for drawing the slot's attachment.
+  BlendMode getBlendMode() {
+    return BlendMode.values[_bindings.spine_slot_data_get_blend_mode(_data)];
+  }
+
+  void setBlendMode(BlendMode mode) {
+    _bindings.spine_slot_data_set_blend_mode(_data, mode.value);
+  }
+
+  @override
+  String toString() {
+    return getName();
+  }
+}
+
+/// Stores a slot's current pose. Slots organize attachments for [Skeleton.getDrawOrder] purposes and provide a place to store
+/// state for an attachment. State cannot be stored in an attachment itself because attachments are stateless and may be shared
+/// across multiple skeletons.
+class Slot {
+  final spine_slot _slot;
+
+  Slot._(this._slot);
+
+  /// Sets this slot to the setup pose.
+  void setToSetupPose() {
+    _bindings.spine_slot_set_to_setup_pose(_slot);
+  }
+
+  /// The slot's setup pose data.
+  SlotData getData() {
+    return SlotData._(_bindings.spine_slot_get_data(_slot));
+  }
+
+  /// The bone this slot belongs to.
+  Bone getBone() {
+    return Bone._(_bindings.spine_slot_get_bone(_slot));
+  }
+
+  /// The skeleton this slot belongs to.
+  Skeleton getSkeleton() {
+    return Skeleton._(_bindings.spine_slot_get_skeleton(_slot));
+  }
+
+  /// The color used to tint the slot's attachment. If [hasDarkColor] is true, this is used as the light color for two
+  /// color tinting.
+  Color getColor() {
+    final color = _bindings.spine_slot_get_color(_slot);
+    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) {
+    _bindings.spine_slot_set_color(_slot, color.r, color.g, color.b, color.a);
+  }
+
+  /// The dark color used to tint the slot's attachment for two color tinting, if [hasDarkColor] is true. The dark
+  /// color's alpha is not used.
+  Color getDarkColor() {
+    final color = _bindings.spine_slot_get_dark_color(_slot);
+    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) {
+    _bindings.spine_slot_set_dark_color(_slot, color.r, color.g, color.b, color.a);
+  }
+
+  /// Returns whether this slot has a dark color set for two color tinting.
+  bool hasDarkColor() {
+    return _bindings.spine_slot_has_dark_color(_slot) == -1;
+  }
+
+  /// The current attachment for the slot, or null if the slot has no attachment.
+  Attachment? getAttachment() {
+    final attachment = _bindings.spine_slot_get_attachment(_slot);
+    if (attachment.address == nullptr.address) return null;
+    return Attachment._toSubclass(attachment);
+  }
+
+  void setAttachment(Attachment? attachment) {
+    _bindings.spine_slot_set_attachment(_slot, attachment != null ? attachment._attachment.cast() : nullptr);
+  }
+
+  @override
+  String toString() {
+    return getData().getName();
+  }
+
+  /// The index of the texture region to display when the slot's attachment has a [Sequence]. -1 represents the
+  /// [Sequence.getSetupIndex].
+  int getSequenceIndex() {
+    return _bindings.spine_slot_get_sequence_index(_slot);
+  }
+
+  void setSequenceIndex(int sequenceIndex) {
+    _bindings.spine_slot_set_sequence_index(_slot, sequenceIndex);
+  }
+}
+
+/// A region within a texture, given in normalized texture coordinates of the top left ([getU], [getV]) and
+/// bottom left ([getU2], [getV2]) corner of the region within the texture.
+class TextureRegion {
+  final spine_texture_region _region;
+
+  TextureRegion._(this._region);
+
+  Pointer<Void> getTexture() {
+    return _bindings.spine_texture_region_get_texture(_region);
+  }
+
+  void setTexture(Pointer<Void> texture) {
+    _bindings.spine_texture_region_set_texture(_region, texture);
+  }
+
+  double getU() {
+    return _bindings.spine_texture_region_get_u(_region);
+  }
+
+  void setU(double u) {
+    _bindings.spine_texture_region_set_u(_region, u);
+  }
+
+  double getV() {
+    return _bindings.spine_texture_region_get_v(_region);
+  }
+
+  void setV(double v) {
+    _bindings.spine_texture_region_set_v(_region, v);
+  }
+
+  double getU2() {
+    return _bindings.spine_texture_region_get_u2(_region);
+  }
+
+  void setU2(double u2) {
+    _bindings.spine_texture_region_set_u2(_region, u2);
+  }
+
+  double getV2() {
+    return _bindings.spine_texture_region_get_v2(_region);
+  }
+
+  void setV2(double v2) {
+    _bindings.spine_texture_region_set_v2(_region, v2);
+  }
+
+  int getDegrees() {
+    return _bindings.spine_texture_region_get_degrees(_region);
+  }
+
+  void setDegrees(int degrees) {
+    _bindings.spine_texture_region_set_degrees(_region, degrees);
+  }
+
+  double getOffsetX() {
+    return _bindings.spine_texture_region_get_offset_x(_region);
+  }
+
+  void setOffsetX(double offsetX) {
+    _bindings.spine_texture_region_set_offset_x(_region, offsetX);
+  }
+
+  double getOffsetY() {
+    return _bindings.spine_texture_region_get_offset_x(_region);
+  }
+
+  void setOffsetY(double offsetX) {
+    _bindings.spine_texture_region_set_offset_x(_region, offsetX);
+  }
+
+  int getWidth() {
+    return _bindings.spine_texture_region_get_width(_region);
+  }
+
+  void setWidth(int width) {
+    _bindings.spine_texture_region_set_width(_region, width);
+  }
+
+  int getHeight() {
+    return _bindings.spine_texture_region_get_height(_region);
+  }
+
+  void setHeight(int height) {
+    _bindings.spine_texture_region_set_height(_region, height);
+  }
+
+  int getOriginalWidth() {
+    return _bindings.spine_texture_region_get_original_width(_region);
+  }
+
+  void setOriginalWidth(int originalWidth) {
+    _bindings.spine_texture_region_set_original_width(_region, originalWidth);
+  }
+
+  int getOriginalHeight() {
+    return _bindings.spine_texture_region_get_original_height(_region);
+  }
+
+  void setOriginalHeight(int originalHeight) {
+    _bindings.spine_texture_region_set_original_height(_region, originalHeight);
+  }
+}
+
+/// Stores a sequence of [TextureRegion] instances that will switched through when set on an attachment.
+class Sequence {
+  final spine_sequence _sequence;
+
+  Sequence._(this._sequence);
+
+  void apply(Slot slot, Attachment attachment) {
+    _bindings.spine_sequence_apply(_sequence, slot._slot, attachment._attachment.cast());
+  }
+
+  String getPath(String basePath, int index) {
+    final nativeBasePath = basePath.toNativeUtf8(allocator: _allocator);
+    final Pointer<Utf8> path = _bindings.spine_sequence_get_path(_sequence, nativeBasePath.cast(), index).cast();
+    final result = path.toDartString();
+    _allocator.free(nativeBasePath);
+    _allocator.free(path);
+    return result;
+  }
+
+  int getId() {
+    return _bindings.spine_sequence_get_id(_sequence);
+  }
+
+  void setId(int id) {
+    _bindings.spine_sequence_set_id(_sequence, id);
+  }
+
+  int getStart() {
+    return _bindings.spine_sequence_get_start(_sequence);
+  }
+
+  void setStart(int start) {
+    _bindings.spine_sequence_set_start(_sequence, start);
+  }
+
+  int getDigits() {
+    return _bindings.spine_sequence_get_digits(_sequence);
+  }
+
+  void setDigits(int digits) {
+    _bindings.spine_sequence_set_digits(_sequence, digits);
+  }
+
+  int getSetupIndex() {
+    return _bindings.spine_sequence_get_setup_index(_sequence);
+  }
+
+  void setSetupIndex(int setupIndex) {
+    _bindings.spine_sequence_set_setup_index(_sequence, setupIndex);
+  }
+
+  List<TextureRegion> getRegions() {
+    List<TextureRegion> result = [];
+    final num = _bindings.spine_sequence_get_num_regions(_sequence);
+    final nativeRegions = _bindings.spine_sequence_get_regions(_sequence);
+    for (int i = 0; i < num; i++) {
+      result.add(TextureRegion._(nativeRegions[i]));
+    }
+    return result;
+  }
+}
+
+/// Attachment types.
+enum AttachmentType {
+  region(0),
+  mesh(1),
+  clipping(2),
+  boundingBox(3),
+  path(4),
+  point(5);
+
+  final int value;
+
+  const AttachmentType(this.value);
+}
+
+/// The base class for all attachments.
+abstract class Attachment<T extends Pointer> {
+  final T _attachment;
+
+  Attachment._(this._attachment);
+
+  /// The attachment's name.
+  String getName() {
+    Pointer<Utf8> name = _bindings.spine_attachment_get_name(_attachment.cast()).cast();
+    return name.toString();
+  }
+
+  /// The attachment's type.
+  AttachmentType getType() {
+    final type = _bindings.spine_attachment_get_type(_attachment.cast());
+    return AttachmentType.values[type];
+  }
+
+  static Attachment _toSubclass(spine_attachment attachment) {
+    final type = AttachmentType.values[_bindings.spine_attachment_get_type(attachment)];
+    switch (type) {
+      case AttachmentType.region:
+        return RegionAttachment._(attachment.cast());
+      case AttachmentType.mesh:
+        return MeshAttachment._(attachment.cast());
+      case AttachmentType.clipping:
+        return ClippingAttachment._(attachment.cast());
+      case AttachmentType.boundingBox:
+        return BoundingBoxAttachment._(attachment.cast());
+      case AttachmentType.path:
+        return PathAttachment._(attachment.cast());
+      case AttachmentType.point:
+        return PointAttachment._(attachment.cast());
+    }
+  }
+
+  /// Returns a copy of the attachment. Copied attachments need to be disposed manually
+  /// when no longer in use via the [dispose] method.
+  Attachment copy() {
+    return _toSubclass(_bindings.spine_attachment_copy(_attachment.cast()));
+  }
+
+  void dispose() {
+    _bindings.spine_attachment_dispose(_attachment.cast());
+  }
+}
+
+/// An attachment that displays a textured quadrilateral.
+///
+/// See [Region attachments](http://esotericsoftware.com/spine-regions) in the Spine User Guide.
+class RegionAttachment extends Attachment<spine_region_attachment> {
+  RegionAttachment._(super.attachment) : super._();
+
+  /// Transforms and returns the attachment's four vertices to world coordinates. If the attachment has a [Sequence], the region may
+  /// be changed.
+  ///
+  /// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
+  /// Runtimes Guide.
+  List<double> computeWorldVertices(Slot slot) {
+    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();
+    _allocator.free(vertices);
+    return result;
+  }
+
+  /// The local x translation.
+  double getX() {
+    return _bindings.spine_region_attachment_get_x(_attachment);
+  }
+
+  void setX(double x) {
+    _bindings.spine_region_attachment_set_x(_attachment, x);
+  }
+
+  /// The local y translation.
+  double getY() {
+    return _bindings.spine_region_attachment_get_y(_attachment);
+  }
+
+  void setY(double y) {
+    _bindings.spine_region_attachment_set_y(_attachment, y);
+  }
+
+  /// The local rotation.
+  double getRotation() {
+    return _bindings.spine_region_attachment_get_rotation(_attachment);
+  }
+
+  void setRotation(double rotation) {
+    _bindings.spine_region_attachment_set_rotation(_attachment, rotation);
+  }
+
+  /// The local scaleX.
+  double getScaleX() {
+    return _bindings.spine_region_attachment_get_scale_x(_attachment);
+  }
+
+  void setScaleX(double scaleX) {
+    _bindings.spine_region_attachment_set_scale_x(_attachment, scaleX);
+  }
+
+  /// The local scaleY.
+  double getScaleY() {
+    return _bindings.spine_region_attachment_get_scale_y(_attachment);
+  }
+
+  void setScaleY(double scaleY) {
+    _bindings.spine_region_attachment_set_scale_x(_attachment, scaleY);
+  }
+
+  /// The width of the region attachment in Spine.
+  double getWidth() {
+    return _bindings.spine_region_attachment_get_width(_attachment);
+  }
+
+  void setWidth(double width) {
+    _bindings.spine_region_attachment_set_width(_attachment, width);
+  }
+
+  /// The height of the region attachment in Spine.
+  double getHeight() {
+    return _bindings.spine_region_attachment_get_height(_attachment);
+  }
+
+  void setHeight(double height) {
+    _bindings.spine_region_attachment_set_height(_attachment, height);
+  }
+
+  Color getColor() {
+    final color = _bindings.spine_region_attachment_get_color(_attachment);
+    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) {
+    _bindings.spine_region_attachment_set_color(_attachment, r, g, b, a);
+  }
+
+  String getPath() {
+    Pointer<Utf8> path = _bindings.spine_region_attachment_get_path(_attachment).cast();
+    return path.toDartString();
+  }
+
+  TextureRegion? getRegion() {
+    final region = _bindings.spine_region_attachment_get_region(_attachment);
+    if (region.address == nullptr.address) return null;
+    return TextureRegion._(region);
+  }
+
+  Sequence? getSequence() {
+    final sequence = _bindings.spine_region_attachment_get_sequence(_attachment);
+    if (sequence.address == nullptr.address) return null;
+    return Sequence._(sequence);
+  }
+
+  /// For each of the 4 vertices, a pair of `x,y` values that is the local position of the vertex.
+  ///
+  /// See [updateRegion].
+  Float32List getOffset() {
+    final num = _bindings.spine_region_attachment_get_num_offset(_attachment);
+    final offset = _bindings.spine_region_attachment_get_offset(_attachment);
+    return offset.asTypedList(num);
+  }
+
+  Float32List getUVs() {
+    final num = _bindings.spine_region_attachment_get_num_uvs(_attachment);
+    final uvs = _bindings.spine_region_attachment_get_uvs(_attachment);
+    return uvs.asTypedList(num);
+  }
+}
+
+/// Base class for an attachment with vertices that are transformed by one or more bones and can be deformed by a slot's
+/// [Slot.getDeform].
+class VertexAttachment<T extends Pointer> extends Attachment<T> {
+  VertexAttachment._(super.attachment) : super._();
+
+  /// Transforms and returns the attachment's local [getVertices] to world coordinates. If the slot's [Slot.getDeform] is
+  /// not empty, it is used to deform the vertices.
+
+  /// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
+  /// Runtimes Guide.
+  List<double> computeWorldVertices(Slot slot) {
+    final worldVerticesLength = _bindings.spine_vertex_attachment_get_world_vertices_length(_attachment.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();
+    _allocator.free(vertices);
+    return result;
+  }
+
+  /// The bones which affect the [getVertices]. The array entries are, for each vertex, the number of bones affecting
+  /// the vertex followed by that many bone indices, which is the index of the bone in [Skeleton.getBones]. Will be null
+  /// if this attachment has no weights.
+  Int32List getBones() {
+    final num = _bindings.spine_vertex_attachment_get_num_bones(_attachment.cast());
+    final bones = _bindings.spine_vertex_attachment_get_bones(_attachment.cast());
+    return bones.asTypedList(num);
+  }
+
+  /// The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are `x,y`
+  /// entries for each vertex. For a weighted attachment, the values are `x,y,weight` entries for each bone affecting
+  /// each vertex.
+  Float32List getVertices() {
+    final num = _bindings.spine_vertex_attachment_get_num_vertices(_attachment.cast());
+    final vertices = _bindings.spine_vertex_attachment_get_vertices(_attachment.cast());
+    return vertices.asTypedList(num);
+  }
+
+  /// Timelines for the timeline attachment are also applied to this attachment. May return `null` if not
+  /// attachment-specific timelines should be applied.
+  Attachment? getTimelineAttachment() {
+    final attachment = _bindings.spine_vertex_attachment_get_timeline_attachment(_attachment.cast());
+    if (_attachment.address == nullptr.address) return null;
+    return Attachment._toSubclass(attachment);
+  }
+
+  void setTimelineAttachment(Attachment? attachment) {
+    _bindings.spine_vertex_attachment_set_timeline_attachment(
+      _attachment.cast(),
+      attachment == null ? nullptr : attachment._attachment.cast(),
+    );
+  }
+}
+
+/// An attachment that displays a textured mesh. A mesh has hull vertices and internal vertices within the hull. Holes are not
+/// supported. Each vertex has UVs (texture coordinates) and triangles are used to map an image on to the mesh.
+///
+/// See [Mesh attachments](http://esotericsoftware.com/spine-meshes) in the Spine User Guide.
+class MeshAttachment extends VertexAttachment<spine_mesh_attachment> {
+  MeshAttachment._(spine_mesh_attachment attachment) : super._(attachment.cast());
+
+  /// Calculates texture coordinates returned by [getUVs] using the coordinates returned by [getRegionUVs] and region. Must be called if
+  /// the region, the region's properties, or the [getRegionUVs] are changed.
+  void updateRegion() {
+    _bindings.spine_mesh_attachment_update_region(_attachment);
+  }
+
+  /// The number of entries at the beginning of {@link #vertices} that make up the mesh hull.
+  int getHullLength() {
+    return _bindings.spine_mesh_attachment_get_hull_length(_attachment);
+  }
+
+  void setHullLength(int hullLength) {
+    _bindings.spine_mesh_attachment_set_hull_length(_attachment, hullLength);
+  }
+
+  /// The UV pair for each vertex, normalized within the texture region.
+  Float32List getRegionUVs() {
+    final num = _bindings.spine_mesh_attachment_get_num_region_uvs(_attachment);
+    final uvs = _bindings.spine_mesh_attachment_get_region_uvs(_attachment);
+    return uvs.asTypedList(num);
+  }
+
+  /// The UV pair for each vertex, normalized within the entire texture.
+  ///
+  /// See [updateRegion].
+  Float32List getUVs() {
+    final num = _bindings.spine_mesh_attachment_get_num_uvs(_attachment);
+    final uvs = _bindings.spine_mesh_attachment_get_uvs(_attachment);
+    return uvs.asTypedList(num);
+  }
+
+  /// Triplets of vertex indices which describe the mesh's triangulation.
+  Uint16List getTriangles() {
+    final num = _bindings.spine_mesh_attachment_get_num_triangles(_attachment);
+    final triangles = _bindings.spine_mesh_attachment_get_triangles(_attachment);
+    return triangles.asTypedList(num);
+  }
+
+  Color getColor() {
+    final color = _bindings.spine_mesh_attachment_get_color(_attachment);
+    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) {
+    _bindings.spine_mesh_attachment_set_color(_attachment, r, g, b, a);
+  }
+
+  String getPath() {
+    Pointer<Utf8> path = _bindings.spine_mesh_attachment_get_path(_attachment).cast();
+    return path.toDartString();
+  }
+
+  TextureRegion? getRegion() {
+    final region = _bindings.spine_mesh_attachment_get_region(_attachment);
+    if (region.address == nullptr.address) return null;
+    return TextureRegion._(region);
+  }
+
+  Sequence? getSequence() {
+    final sequence = _bindings.spine_mesh_attachment_get_sequence(_attachment);
+    if (sequence.address == nullptr.address) return null;
+    return Sequence._(sequence);
+  }
+
+  /// The parent mesh if this is a linked mesh, else null. A linked mesh shares the bones, vertices,
+  /// region UVs, triangles, hull length, edges, width, and height with the
+  /// parent mesh, but may have a different name or path (and therefore a different texture).
+  MeshAttachment? getParentMesh() {
+    final parent = _bindings.spine_mesh_attachment_get_parent_mesh(_attachment);
+    if (parent.address == nullptr.address) return null;
+    return MeshAttachment._(parent);
+  }
+
+  void setParentMesh(MeshAttachment? parentMesh) {
+    _bindings.spine_mesh_attachment_set_parent_mesh(_attachment, parentMesh == null ? nullptr : parentMesh._attachment);
+  }
+
+  /// Vertex index pairs describing edges for controlling triangulation, or be null if nonessential data was not exported. Mesh
+  /// triangles will never cross edges. Triangulation is not performed at runtime.
+  Uint16List getEdges() {
+    final num = _bindings.spine_mesh_attachment_get_num_edges(_attachment);
+    final edges = _bindings.spine_mesh_attachment_get_edges(_attachment);
+    return edges.asTypedList(num);
+  }
+
+  /// The width of the mesh's image, or zero if nonessential data was not exported.
+  double getWidth() {
+    return _bindings.spine_mesh_attachment_get_width(_attachment);
+  }
+
+  void setWidth(double width) {
+    _bindings.spine_mesh_attachment_set_width(_attachment, width);
+  }
+
+  /// The height of the mesh's image, or zero if nonessential data was not exported.
+  double getHeight() {
+    return _bindings.spine_mesh_attachment_get_height(_attachment);
+  }
+
+  void setHeight(double height) {
+    _bindings.spine_mesh_attachment_set_height(_attachment, height);
+  }
+}
+
+/// An attachment with vertices that make up a polygon used for clipping the rendering of other attachments.
+class ClippingAttachment extends VertexAttachment<spine_clipping_attachment> {
+  ClippingAttachment._(spine_clipping_attachment attachment) : super._(attachment.cast());
+
+  /// Clipping is performed between the clipping attachment's slot and the end slot. If null clipping is done until the end of
+  /// the skeleton's rendering.
+  SlotData? getEndSlot() {
+    final endSlot = _bindings.spine_clipping_attachment_get_end_slot(_attachment);
+    if (endSlot.address == nullptr.address) return null;
+    return SlotData._(endSlot);
+  }
+
+  void setEndSlot(SlotData? endSlot) {
+    _bindings.spine_clipping_attachment_set_end_slot(_attachment, endSlot == null ? nullptr : endSlot._data);
+  }
+
+  /// The color of the clipping attachment as it was in Spine, or a default color if nonessential data was not exported. Clipping
+  /// attachments are not usually rendered at runtime.
+  Color getColor() {
+    final color = _bindings.spine_clipping_attachment_get_color(_attachment);
+    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) {
+    _bindings.spine_clipping_attachment_set_color(_attachment, r, g, b, a);
+  }
+}
+
+/// An attachment with vertices that make up a polygon. Can be used for hit detection, creating physics bodies, spawning particle
+/// effects, and more.
+///
+/// See [SkeletonBounds] and [Bounding boxes](http://esotericsoftware.com/spine-bounding-boxes) in the Spine User
+/// Guide.
+class BoundingBoxAttachment extends VertexAttachment<spine_bounding_box_attachment> {
+  BoundingBoxAttachment._(super.attachment) : super._();
+
+  /// The color of the bounding box as it was in Spine, or a default color if nonessential data was not exported. Bounding boxes
+  /// are not usually rendered at runtime.
+  Color getColor() {
+    final color = _bindings.spine_bounding_box_attachment_get_color(_attachment);
+    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) {
+    _bindings.spine_bounding_box_attachment_set_color(_attachment, r, g, b, a);
+  }
+}
+
+/// An attachment whose vertices make up a composite Bezier curve.
+///
+/// See [PathConstraint] and [Paths](http://esotericsoftware.com/spine-paths) in the Spine User Guide.
+class PathAttachment extends VertexAttachment<spine_path_attachment> {
+  PathAttachment._(super.attachment) : super._();
+
+  /// The lengths along the path in the setup pose from the start of the path to the end of each Bezier curve.
+  Float32List getLengths() {
+    final num = _bindings.spine_path_attachment_get_num_lengths(_attachment);
+    final lengths = _bindings.spine_path_attachment_get_lengths(_attachment);
+    return lengths.asTypedList(num);
+  }
+
+  /// If true, the start and end knots are connected.
+  bool isClosed() {
+    return _bindings.spine_path_attachment_get_is_closed(_attachment) == -1;
+  }
+
+  void setIsClosed(bool isClosed) {
+    _bindings.spine_path_attachment_set_is_closed(_attachment, isClosed ? -1 : 0);
+  }
+
+  /// If true, additional calculations are performed to make computing positions along the path more accurate and movement along
+  /// the path have a constant speed.
+  bool isConstantSpeed() {
+    return _bindings.spine_path_attachment_get_is_constant_speed(_attachment) == -1;
+  }
+
+  void setIsConstantSpeed(bool isClosed) {
+    _bindings.spine_path_attachment_set_is_constant_speed(_attachment, isClosed ? -1 : 0);
+  }
+
+  /// The color of the path as it was in Spine, or a default color if nonessential data was not exported. Paths are not usually
+  /// rendered at runtime.
+  Color getColor() {
+    final color = _bindings.spine_path_attachment_get_color(_attachment);
+    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) {
+    _bindings.spine_path_attachment_set_color(_attachment, r, g, b, a);
+  }
+}
+
+/// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be
+/// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a
+/// skin.
+///
+/// See [Point Attachments](https://esotericsoftware.com/spine-points) in the Spine User Guide.
+class PointAttachment extends Attachment<spine_point_attachment> {
+  PointAttachment._(super.attachment) : super._();
+
+  Vec2 computeWorldPosition(Bone bone) {
+    final position = _bindings.spine_point_attachment_compute_world_position(_attachment, bone._bone);
+    final result = Vec2(_bindings.spine_vector_get_x(position), _bindings.spine_vector_get_y(position));
+    return result;
+  }
+
+  double computeWorldRotation(Bone bone) {
+    return _bindings.spine_point_attachment_compute_world_rotation(_attachment, bone._bone);
+  }
+
+  double getX() {
+    return _bindings.spine_point_attachment_get_x(_attachment);
+  }
+
+  void setX(double x) {
+    _bindings.spine_point_attachment_set_x(_attachment, x);
+  }
+
+  double getY() {
+    return _bindings.spine_point_attachment_get_y(_attachment);
+  }
+
+  void setY(double y) {
+    _bindings.spine_point_attachment_set_y(_attachment, y);
+  }
+
+  double getRotation() {
+    return _bindings.spine_point_attachment_get_rotation(_attachment);
+  }
+
+  void setRotation(double rotation) {
+    _bindings.spine_point_attachment_set_x(_attachment, rotation);
+  }
+
+  /// The color of the point attachment as it was in Spine, or a default clor if nonessential data was not exported. Point
+  /// attachments are not usually rendered at runtime.
+  Color getColor() {
+    final color = _bindings.spine_point_attachment_get_color(_attachment);
+    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) {
+    _bindings.spine_point_attachment_set_color(_attachment, r, g, b, a);
+  }
+}
+
+/// An entry storing the attachment to be used for a specific slot within [Skin].
+class SkinEntry {
+  final int slotIndex;
+  final String name;
+  final Attachment? attachment;
+
+  SkinEntry(this.slotIndex, this.name, this.attachment);
+}
+
+/// Stores attachments by slot index and attachment name.
+///
+/// Skins constructed manually via the `Skin(String name)` constructor must be manually disposed via the [dipose] method if they
+/// are no longer used.
+///
+/// See [SkeletonData.defaultSkin], [Skeleton.getSkin}, and [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the
+/// Spine Runtimes Guide.
+class Skin {
+  late final bool _isCustomSkin;
+  late final spine_skin _skin;
+
+  Skin._(this._skin) : _isCustomSkin = false;
+
+  /// Constructs a new empty skin using the given [name]. Skins constructed this way must be manually disposed via the [dispose] method
+  /// if they are no longer used.
+  Skin(String name) {
+    final nativeName = name.toNativeUtf8(allocator: _allocator);
+    _skin = _bindings.spine_skin_create(nativeName.cast());
+    _allocator.free(nativeName);
+    _isCustomSkin = true;
+  }
+
+  /// Diposes this skin.
+  void dispose() {
+    if (!_isCustomSkin) return;
+    _bindings.spine_skin_dispose(_skin);
+  }
+
+  /// Adds an attachment to the skin for the specified slot index and name.
+  void setAttachment(int slotIndex, String name, Attachment? attachment) {
+    final nativeName = name.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_skin_set_attachment(
+      _skin,
+      slotIndex,
+      nativeName.cast(),
+      attachment == null ? nullptr : attachment._attachment.cast(),
+    );
+    _allocator.free(nativeName);
+  }
+
+  /// Returns the attachment for the specified slot index and name, or null.
+  Attachment? getAttachment(int slotIndex, String name) {
+    final nativeName = name.toNativeUtf8(allocator: _allocator);
+    final attachment = _bindings.spine_skin_get_attachment(_skin, slotIndex, nativeName.cast());
+    _allocator.free(nativeName);
+    if (attachment.address == nullptr.address) return null;
+    return Attachment._toSubclass(attachment);
+  }
+
+  /// Removes the attachment in the skin for the specified slot index and name, if any.
+  void removeAttachment(int slotIndex, String name) {
+    final nativeName = name.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_skin_remove_attachment(_skin, slotIndex, nativeName.cast());
+    _allocator.free(nativeName);
+  }
+
+  /// The skin's name, which is unique across all skins in the skeleton.
+  String getName() {
+    Pointer<Utf8> name = _bindings.spine_skin_get_name(_skin).cast();
+    return name.toDartString();
+  }
+
+  /// Adds all attachments, bones, and constraints from the specified skin to this skin.
+  void addSkin(Skin other) {
+    _bindings.spine_skin_add_skin(_skin, other._skin);
+  }
+
+  /// Returns all entries in this skin.
+  List<SkinEntry> getEntries() {
+    List<SkinEntry> result = [];
+    final entries = _bindings.spine_skin_get_entries(_skin);
+    int numEntries = _bindings.spine_skin_entries_get_num_entries(entries);
+    for (int i = 0; i < numEntries; i++) {
+      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;
+  }
+
+  List<BoneData> getBones() {
+    List<BoneData> bones = [];
+    final numBones = _bindings.spine_skin_get_num_bones(_skin);
+    final nativeBones = _bindings.spine_skin_get_bones(_skin);
+    for (int i = 0; i < numBones; i++) {
+      bones.add(BoneData._(nativeBones[i]));
+    }
+    return bones;
+  }
+
+  List<ConstraintData> getConstraints() {
+    List<ConstraintData> constraints = [];
+    final numConstraints = _bindings.spine_skin_get_num_constraints(_skin);
+    final nativeConstraints = _bindings.spine_skin_get_constraints(_skin);
+    for (int i = 0; i < numConstraints; i++) {
+      final nativeConstraint = nativeConstraints[i];
+      final type = _bindings.spine_constraint_data_get_type(nativeConstraint);
+      switch (type) {
+        case spine_constraint_type.SPINE_CONSTRAINT_IK:
+          constraints.add(IkConstraintData._(nativeConstraint.cast()));
+          break;
+        case spine_constraint_type.SPINE_CONSTRAINT_TRANSFORM:
+          constraints.add(TransformConstraintData._(nativeConstraint.cast()));
+          break;
+        case spine_constraint_type.SPINE_CONSTRAINT_PATH:
+          constraints.add(PathConstraintData._(nativeConstraint.cast()));
+          break;
+      }
+    }
+    return constraints;
+  }
+
+  /// Adds all bones and constraints and copies of all attachments from the specified skin to this skin. Mesh attachments are not
+  /// copied, instead a new linked mesh is created. The attachment copies can be modified without affecting the originals.
+  void copy(Skin other) {
+    _bindings.spine_skin_copy_skin(_skin, other._skin);
+  }
+}
+
+/// The base class for all constraint datas.
+class ConstraintData<T extends Pointer> {
+  final T _data;
+
+  ConstraintData._(this._data);
+
+  /// The constraint's name, which is unique across all constraints in the skeleton of the same type.
+  String getName() {
+    final Pointer<Utf8> name = _bindings.spine_constraint_data_get_name(_data.cast()).cast();
+    return name.toDartString();
+  }
+
+  /// The ordinal of this constraint for the order a skeleton's constraints will be applied by
+  /// [Skeleton.updateWorldTransform].
+  int getOrder() {
+    return _bindings.spine_constraint_data_get_order(_data.cast());
+  }
+
+  void setOrder(int order) {
+    _bindings.spine_constraint_data_set_order(_data.cast(), order);
+  }
+
+  /// When true, [Skeleton.updateWorldTransform] only updates this constraint if the skin returned by [Skeleton.getSkin] contains
+  /// this constraint.
+  ///
+  /// See [Skin.getConstraints].
+  bool isSkinRequired() {
+    return _bindings.spine_constraint_data_get_is_skin_required(_data.cast()) == 1;
+  }
+
+  void setIsSkinRequired(bool isSkinRequired) {
+    _bindings.spine_constraint_data_set_is_skin_required(_data.cast(), isSkinRequired ? -1 : 0);
+  }
+}
+
+/// Stores the setup pose for an [IkConstraint].
+///
+/// See [IK constraints](http://esotericsoftware.com/spine-ik-constraints) in the Spine User Guide.
+class IkConstraintData extends ConstraintData<spine_ik_constraint_data> {
+  IkConstraintData._(super.data) : super._();
+
+  /// The bones that are constrained by this IK constraint.
+  List<BoneData> getBones() {
+    final List<BoneData> result = [];
+    final numBones = _bindings.spine_ik_constraint_data_get_num_bones(_data);
+    final nativeBones = _bindings.spine_ik_constraint_data_get_bones(_data);
+    for (int i = 0; i < numBones; i++) {
+      result.add(BoneData._(nativeBones[i]));
+    }
+    return result;
+  }
+
+  /// The bone that is the IK target.
+  BoneData getTarget() {
+    return BoneData._(_bindings.spine_ik_constraint_data_get_target(_data));
+  }
+
+  void setTarget(BoneData target) {
+    _bindings.spine_ik_constraint_data_set_target(_data, target._data);
+  }
+
+  /// For two bone IK, controls the bend direction of the IK bones, either 1 or -1.
+  int getBendDirection() {
+    return _bindings.spine_ik_constraint_data_get_bend_direction(_data);
+  }
+
+  void setBendDirection(int bendDirection) {
+    _bindings.spine_ik_constraint_data_set_bend_direction(_data, bendDirection);
+  }
+
+  /// For one bone IK, when true and the target is too close, the bone is scaled to reach it.
+  bool getCompress() {
+    return _bindings.spine_ik_constraint_data_get_compress(_data) == -1;
+  }
+
+  void setCompress(bool compress) {
+    _bindings.spine_ik_constraint_data_set_compress(_data, compress ? -1 : 0);
+  }
+
+  /// When true and the target is out of range, the parent bone is scaled to reach it.
+  ///
+  /// For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if [getSoftness] is
+  /// > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied.
+  bool getStretch() {
+    return _bindings.spine_ik_constraint_data_get_stretch(_data) == -1;
+  }
+
+  void setStretch(bool stretch) {
+    _bindings.spine_ik_constraint_data_set_stretch(_data, stretch ? -1 : 0);
+  }
+
+  /// When true and [getCompress] or [getStretch] is used, the bone is scaled on both the X and Y axes.
+  bool getUniform() {
+    return _bindings.spine_ik_constraint_data_get_uniform(_data) == -1;
+  }
+
+  void setUniform(bool uniform) {
+    _bindings.spine_ik_constraint_data_set_uniform(_data, uniform ? -1 : 0);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
+  ///
+  /// For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0.
+  double getMix() {
+    return _bindings.spine_ik_constraint_data_get_mix(_data);
+  }
+
+  void setMix(double mix) {
+    _bindings.spine_ik_constraint_data_set_mix(_data, mix);
+  }
+
+  /// For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
+  /// will not straighten completely until the target is this far out of range.
+  double getSoftness() {
+    return _bindings.spine_ik_constraint_data_get_softness(_data);
+  }
+
+  void setSoftness(double softness) {
+    _bindings.spine_ik_constraint_data_set_softness(_data, softness);
+  }
+}
+
+/// Stores the current pose for an IK constraint. An IK constraint adjusts the rotation of 1 or 2 constrained bones so the tip of
+/// the last bone is as close to the target bone as possible.
+/// <p>
+/// See <a href="http://esotericsoftware.com/spine-ik-constraints">IK constraints</a> in the Spine User Guide.
+class IkConstraint {
+  final spine_ik_constraint _constraint;
+
+  IkConstraint._(this._constraint);
+
+  /// Applies the constraint to the constrained bones.
+  void update() {
+    _bindings.spine_ik_constraint_update(_constraint);
+  }
+
+  int getOrder() {
+    return _bindings.spine_ik_constraint_get_order(_constraint);
+  }
+
+  /// The IK constraint's setup pose data.
+  IkConstraintData getData() {
+    return IkConstraintData._(_bindings.spine_ik_constraint_get_data(_constraint));
+  }
+
+  /// The bones that will be modified by this IK constraint.
+  List<Bone> getBones() {
+    List<Bone> result = [];
+    final num = _bindings.spine_ik_constraint_get_num_bones(_constraint);
+    final nativeBones = _bindings.spine_ik_constraint_get_bones(_constraint);
+    for (int i = 0; i < num; i++) {
+      result.add(Bone._(nativeBones[i]));
+    }
+    return result;
+  }
+
+  /// The bone that is the IK target.
+  Bone getTarget() {
+    return Bone._(_bindings.spine_ik_constraint_get_target(_constraint));
+  }
+
+  void setTarget(Bone target) {
+    _bindings.spine_ik_constraint_set_target(_constraint, target._bone);
+  }
+
+  /// For two bone IK, controls the bend direction of the IK bones, either 1 or -1.
+  int getBendDirection() {
+    return _bindings.spine_ik_constraint_get_bend_direction(_constraint);
+  }
+
+  void setBendDirection(int bendDirection) {
+    _bindings.spine_ik_constraint_set_bend_direction(_constraint, bendDirection);
+  }
+
+  /// For one bone IK, when true and the target is too close, the bone is scaled to reach it.
+  bool getCompress() {
+    return _bindings.spine_ik_constraint_get_compress(_constraint) == -1;
+  }
+
+  void setCompress(bool compress) {
+    _bindings.spine_ik_constraint_set_compress(_constraint, compress ? -1 : 0);
+  }
+
+  /// When true and the target is out of range, the parent bone is scaled to reach it.
+  ///
+  /// For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if [getSoftness] is
+  /// > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied.
+  bool getStretch() {
+    return _bindings.spine_ik_constraint_get_stretch(_constraint) == -1;
+  }
+
+  void setStretch(bool stretch) {
+    _bindings.spine_ik_constraint_set_stretch(_constraint, stretch ? -1 : 0);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
+  ///
+  /// For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0.
+  double getMix() {
+    return _bindings.spine_ik_constraint_get_mix(_constraint);
+  }
+
+  void setMix(double mix) {
+    _bindings.spine_ik_constraint_set_mix(_constraint, mix);
+  }
+
+  /// For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
+  /// will not straighten completely until the target is this far out of range.
+  double getSoftness() {
+    return _bindings.spine_ik_constraint_get_softness(_constraint);
+  }
+
+  void setSoftness(double softness) {
+    _bindings.spine_ik_constraint_set_softness(_constraint, softness);
+  }
+
+  bool isActive() {
+    return _bindings.spine_ik_constraint_get_is_active(_constraint) == -1;
+  }
+
+  void setIsActive(bool isActive) {
+    _bindings.spine_ik_constraint_set_is_active(_constraint, isActive ? -1 : 0);
+  }
+}
+
+/// Stores the setup pose for a {@link TransformConstraint}.
+///
+/// See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide.
+class TransformConstraintData extends ConstraintData<spine_transform_constraint_data> {
+  TransformConstraintData._(super.data) : super._();
+
+  /// The bones that will be modified by this transform constraint.
+  List<BoneData> getBones() {
+    final List<BoneData> result = [];
+    final numBones = _bindings.spine_transform_constraint_data_get_num_bones(_data);
+    final nativeBones = _bindings.spine_transform_constraint_data_get_bones(_data);
+    for (int i = 0; i < numBones; i++) {
+      result.add(BoneData._(nativeBones[i]));
+    }
+    return result;
+  }
+
+  /// The target bone whose world transform will be copied to the constrained bones.
+  BoneData getTarget() {
+    return BoneData._(_bindings.spine_transform_constraint_data_get_target(_data));
+  }
+
+  void setTarget(BoneData target) {
+    _bindings.spine_transform_constraint_data_set_target(_data, target._data);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
+  double getMixRotate() {
+    return _bindings.spine_transform_constraint_data_get_mix_rotate(_data);
+  }
+
+  void setMixRotate(double mixRotate) {
+    _bindings.spine_transform_constraint_data_set_mix_rotate(_data, mixRotate);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
+  double getMixX() {
+    return _bindings.spine_transform_constraint_data_get_mix_x(_data);
+  }
+
+  void setMixX(double mixX) {
+    _bindings.spine_transform_constraint_data_set_mix_x(_data, mixX);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y.
+  double getMixY() {
+    return _bindings.spine_transform_constraint_data_get_mix_y(_data);
+  }
+
+  void setMixY(double mixY) {
+    _bindings.spine_transform_constraint_data_set_mix_y(_data, mixY);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained scale X.
+  double getMixScaleX() {
+    return _bindings.spine_transform_constraint_data_get_mix_scale_x(_data);
+  }
+
+  void setMixScaleX(double mixScaleX) {
+    _bindings.spine_transform_constraint_data_set_mix_scale_x(_data, mixScaleX);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained scale Y.
+  double getMixScaleY() {
+    return _bindings.spine_transform_constraint_data_get_mix_scale_y(_data);
+  }
+
+  void setMixScaleY(double mixScaleY) {
+    _bindings.spine_transform_constraint_data_set_mix_scale_y(_data, mixScaleY);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y.
+  double getMixShearY() {
+    return _bindings.spine_transform_constraint_data_get_mix_shear_y(_data);
+  }
+
+  void setMixShearY(double mixShearY) {
+    _bindings.spine_transform_constraint_data_set_mix_shear_y(_data, mixShearY);
+  }
+
+  /// An offset added to the constrained bone rotation.
+  double getOffsetRotation() {
+    return _bindings.spine_transform_constraint_data_get_offset_rotation(_data);
+  }
+
+  void setOffsetRotation(double offsetRotation) {
+    _bindings.spine_transform_constraint_data_set_offset_rotation(_data, offsetRotation);
+  }
+
+  /// An offset added to the constrained bone X translation.
+  double getOffsetX() {
+    return _bindings.spine_transform_constraint_data_get_offset_x(_data);
+  }
+
+  void setOffsetX(double offsetX) {
+    _bindings.spine_transform_constraint_data_set_offset_x(_data, offsetX);
+  }
+
+  /// An offset added to the constrained bone Y translation.
+  double getOffsetY() {
+    return _bindings.spine_transform_constraint_data_get_offset_y(_data);
+  }
+
+  /// An offset added to the constrained bone scaleX.
+  void setOffsetY(double offsetY) {
+    _bindings.spine_transform_constraint_data_set_offset_y(_data, offsetY);
+  }
+
+  /// An offset added to the constrained bone scaleX.
+  double getOffsetScaleX() {
+    return _bindings.spine_transform_constraint_data_get_offset_scale_x(_data);
+  }
+
+  void setOffsetScaleX(double offsetScaleX) {
+    _bindings.spine_transform_constraint_data_set_offset_x(_data, offsetScaleX);
+  }
+
+  /// An offset added to the constrained bone scaleY.
+  double getOffsetScaleY() {
+    return _bindings.spine_transform_constraint_data_get_offset_scale_y(_data);
+  }
+
+  void setOffsetScaleY(double offsetScaleY) {
+    _bindings.spine_transform_constraint_data_set_offset_scale_y(_data, offsetScaleY);
+  }
+
+  /// An offset added to the constrained bone shearY.
+  double getOffsetShearY() {
+    return _bindings.spine_transform_constraint_data_get_offset_shear_y(_data);
+  }
+
+  void setOffsetShearY(double offsetShearY) {
+    _bindings.spine_transform_constraint_data_set_offset_shear_y(_data, offsetShearY);
+  }
+
+  bool isRelative() {
+    return _bindings.spine_transform_constraint_data_get_is_relative(_data) == -1;
+  }
+
+  void setIsRelative(bool isRelative) {
+    _bindings.spine_transform_constraint_data_set_is_relative(_data, isRelative ? -1 : 0);
+  }
+
+  bool isLocal() {
+    return _bindings.spine_transform_constraint_data_get_is_local(_data) == -1;
+  }
+
+  void setIsLocal(bool isLocal) {
+    _bindings.spine_transform_constraint_data_set_is_local(_data, isLocal ? -1 : 0);
+  }
+}
+
+/// Stores the current pose for a transform constraint. A transform constraint adjusts the world transform of the constrained
+/// bones to match that of the target bone.
+///
+/// See [Transform constraints](http://esotericsoftware.com/spine-transform-constraints) in the Spine User Guide.
+class TransformConstraint {
+  final spine_transform_constraint _constraint;
+
+  TransformConstraint._(this._constraint);
+
+  /// Applies the constraint to the constrained bones.
+  void update() {
+    _bindings.spine_transform_constraint_update(_constraint);
+  }
+
+  int getOrder() {
+    return _bindings.spine_transform_constraint_get_order(_constraint);
+  }
+
+  /// The transform constraint's setup pose data.
+  TransformConstraintData getData() {
+    return TransformConstraintData._(_bindings.spine_transform_constraint_get_data(_constraint));
+  }
+
+  /// The bones that will be modified by this transform constraint.
+  List<Bone> getBones() {
+    List<Bone> result = [];
+    final num = _bindings.spine_transform_constraint_get_num_bones(_constraint);
+    final nativeBones = _bindings.spine_transform_constraint_get_bones(_constraint);
+    for (int i = 0; i < num; i++) {
+      result.add(Bone._(nativeBones[i]));
+    }
+    return result;
+  }
+
+  /// The target bone whose world transform will be copied to the constrained bones.
+  Bone getTarget() {
+    return Bone._(_bindings.spine_transform_constraint_get_target(_constraint));
+  }
+
+  void setTarget(Bone target) {
+    _bindings.spine_transform_constraint_set_target(_constraint, target._bone);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
+  double getMixRotate() {
+    return _bindings.spine_transform_constraint_get_mix_rotate(_constraint);
+  }
+
+  void setMixRotate(double mixRotate) {
+    _bindings.spine_transform_constraint_set_mix_rotate(_constraint, mixRotate);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
+  double getMixX() {
+    return _bindings.spine_transform_constraint_get_mix_x(_constraint);
+  }
+
+  void setMixX(double mixX) {
+    _bindings.spine_transform_constraint_set_mix_x(_constraint, mixX);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y.
+  double getMixY() {
+    return _bindings.spine_transform_constraint_get_mix_y(_constraint);
+  }
+
+  void setMixY(double mixY) {
+    _bindings.spine_transform_constraint_set_mix_y(_constraint, mixY);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained scale X.
+  double getMixScaleX() {
+    return _bindings.spine_transform_constraint_get_mix_scale_x(_constraint);
+  }
+
+  void setMixScaleX(double mixScaleX) {
+    _bindings.spine_transform_constraint_set_mix_scale_x(_constraint, mixScaleX);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained scale X.
+  double getMixScaleY() {
+    return _bindings.spine_transform_constraint_get_mix_scale_y(_constraint);
+  }
+
+  void setMixScaleY(double mixScaleY) {
+    _bindings.spine_transform_constraint_set_mix_scale_y(_constraint, mixScaleY);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained shear Y.
+  double getMixShearY() {
+    return _bindings.spine_transform_constraint_get_mix_shear_y(_constraint);
+  }
+
+  void setMixShearY(double mixShearY) {
+    _bindings.spine_transform_constraint_set_mix_shear_y(_constraint, mixShearY);
+  }
+
+  bool isActive() {
+    return _bindings.spine_transform_constraint_get_is_active(_constraint) == -1;
+  }
+
+  void setIsActive(bool isActive) {
+    _bindings.spine_transform_constraint_set_is_active(_constraint, isActive ? -1 : 0);
+  }
+}
+
+/// Stores the setup pose for a [PathConstraint].
+///
+/// See [Path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide.
+class PathConstraintData extends ConstraintData<spine_path_constraint_data> {
+  PathConstraintData._(super.data) : super._();
+
+  /// The bones that will be modified by this path constraint.
+  List<BoneData> getBones() {
+    final List<BoneData> result = [];
+    final numBones = _bindings.spine_path_constraint_data_get_num_bones(_data);
+    final nativeBones = _bindings.spine_path_constraint_data_get_bones(_data);
+    for (int i = 0; i < numBones; i++) {
+      result.add(BoneData._(nativeBones[i]));
+    }
+    return result;
+  }
+
+  /// The slot whose path attachment will be used to constrained the bones.
+  SlotData getTarget() {
+    return SlotData._(_bindings.spine_path_constraint_data_get_target(_data));
+  }
+
+  void setTarget(SlotData target) {
+    _bindings.spine_path_constraint_data_set_target(_data, target._data);
+  }
+
+  /// The mode for positioning the first bone on the path.
+  PositionMode getPositionMode() {
+    return PositionMode.values[_bindings.spine_path_constraint_data_get_position_mode(_data)];
+  }
+
+  void setPositionMode(PositionMode positionMode) {
+    _bindings.spine_path_constraint_data_set_position_mode(_data, positionMode.value);
+  }
+
+  /// The mode for positioning the bones after the first bone on the path.
+  SpacingMode getSpacingMode() {
+    return SpacingMode.values[_bindings.spine_path_constraint_data_get_spacing_mode(_data)];
+  }
+
+  void setSpacingMode(SpacingMode spacingMode) {
+    _bindings.spine_path_constraint_data_set_spacing_mode(_data, spacingMode.value);
+  }
+
+  /// The mode for adjusting the rotation of the bones.
+  RotateMode getRotateMode() {
+    return RotateMode.values[_bindings.spine_path_constraint_data_get_rotate_mode(_data)];
+  }
+
+  void setRotateMode(RotateMode rotateMode) {
+    _bindings.spine_path_constraint_data_set_rotate_mode(_data, rotateMode.value);
+  }
+
+  /// An offset added to the constrained bone rotation.
+  double getOffsetRotation() {
+    return _bindings.spine_path_constraint_data_get_offset_rotation(_data);
+  }
+
+  void setOffsetRotation(double offsetRotation) {
+    _bindings.spine_path_constraint_data_set_offset_rotation(_data, offsetRotation);
+  }
+
+  /// The position along the path.
+  double getPosition() {
+    return _bindings.spine_path_constraint_data_get_position(_data);
+  }
+
+  void setPosition(double position) {
+    _bindings.spine_path_constraint_data_set_position(_data, position);
+  }
+
+  /// The spacing between bones.
+  double getSpacing() {
+    return _bindings.spine_path_constraint_data_get_spacing(_data);
+  }
+
+  void setSpacing(double spacing) {
+    _bindings.spine_path_constraint_data_set_spacing(_data, spacing);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
+  double getMixRotate() {
+    return _bindings.spine_path_constraint_data_get_mix_rotate(_data);
+  }
+
+  void setMixRotate(double mixRotate) {
+    _bindings.spine_path_constraint_data_set_mix_rotate(_data, mixRotate);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
+  double getMixX() {
+    return _bindings.spine_path_constraint_data_get_mix_x(_data);
+  }
+
+  void setMixX(double mixX) {
+    _bindings.spine_path_constraint_data_set_mix_x(_data, mixX);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y.
+  double getMixY() {
+    return _bindings.spine_path_constraint_data_get_mix_x(_data);
+  }
+
+  void setMixY(double mixY) {
+    _bindings.spine_path_constraint_data_set_mix_y(_data, mixY);
+  }
+}
+
+/// Stores the current pose for a path constraint. A path constraint adjusts the rotation, translation, and scale of the
+/// constrained bones so they follow a [PathAttachment].
+///
+/// See [Path constraints](http://esotericsoftware.com/spine-path-constraints) in the Spine User Guide.
+class PathConstraint {
+  final spine_path_constraint _constraint;
+
+  PathConstraint._(this._constraint);
+
+  /// Applies the constraint to the constrained bones.
+  void update() {
+    _bindings.spine_path_constraint_update(_constraint);
+  }
+
+  int getOrder() {
+    return _bindings.spine_path_constraint_get_order(_constraint);
+  }
+
+  /// The bones that will be modified by this path constraint.
+  List<Bone> getBones() {
+    List<Bone> result = [];
+    final num = _bindings.spine_path_constraint_get_num_bones(_constraint);
+    final nativeBones = _bindings.spine_path_constraint_get_bones(_constraint);
+    for (int i = 0; i < num; i++) {
+      result.add(Bone._(nativeBones[i]));
+    }
+    return result;
+  }
+
+  /// The slot whose path attachment will be used to constrained the bones.
+  Slot getTarget() {
+    return Slot._(_bindings.spine_path_constraint_get_target(_constraint));
+  }
+
+  void setTarget(Slot target) {
+    _bindings.spine_path_constraint_set_target(_constraint, target._slot);
+  }
+
+  /// The position along the path.
+  double getPosition() {
+    return _bindings.spine_path_constraint_get_position(_constraint);
+  }
+
+  void setPosition(double position) {
+    _bindings.spine_path_constraint_set_position(_constraint, position);
+  }
+
+  /// The spacing between bones.
+  double getSpacing() {
+    return _bindings.spine_path_constraint_get_spacing(_constraint);
+  }
+
+  void setSpacing(double spacing) {
+    _bindings.spine_path_constraint_set_spacing(_constraint, spacing);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
+  double getMixRotate() {
+    return _bindings.spine_path_constraint_get_mix_rotate(_constraint);
+  }
+
+  void setMixRotate(double mixRotate) {
+    _bindings.spine_path_constraint_set_mix_rotate(_constraint, mixRotate);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
+  double getMixX() {
+    return _bindings.spine_path_constraint_get_mix_x(_constraint);
+  }
+
+  void setMixX(double mixX) {
+    _bindings.spine_path_constraint_set_mix_x(_constraint, mixX);
+  }
+
+  /// A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y.
+  double getMixY() {
+    return _bindings.spine_path_constraint_get_mix_y(_constraint);
+  }
+
+  void setMixY(double mixY) {
+    _bindings.spine_path_constraint_set_mix_y(_constraint, mixY);
+  }
+
+  bool isActive() {
+    return _bindings.spine_path_constraint_get_is_active(_constraint) == -1;
+  }
+
+  void setIsActive(bool isActive) {
+    _bindings.spine_path_constraint_set_is_active(_constraint, isActive ? -1 : 0);
+  }
+}
+
+/// Stores the current pose for a skeleton.
+///
+/// See [Instance objects](http://esotericsoftware.com/spine-runtime-architecture#Instance-objects) in the Spine
+/// Runtimes Guide.
+class Skeleton {
+  final spine_skeleton _skeleton;
+
+  Skeleton._(this._skeleton);
+
+  /// Caches information about bones and constraints. Must be called if the [getSkin] is modified or if bones,
+  /// constraints, or weighted path attachments are added or removed.
+  void updateCache() {
+    _bindings.spine_skeleton_update_cache(_skeleton);
+  }
+
+  /// Updates the world transform for each bone and applies all constraints.
+  ///
+  /// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
+  /// Runtimes Guide.
+  void updateWorldTransform(Physics physics) {
+    _bindings.spine_skeleton_update_world_transform(_skeleton, physics.value);
+  }
+
+  /// Temporarily sets the root bone as a child of the specified bone, then updates the world transform for each bone and applies
+  /// all constraints.
+  ///
+  /// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
+  /// Runtimes Guide.
+  void updateWorldTransformBone(Physics physics, Bone parent) {
+    _bindings.spine_skeleton_update_world_transform_bone(_skeleton, physics.value, parent._bone);
+  }
+
+  /// Sets the bones, constraints, slots, and draw order to their setup pose values.
+  void setToSetupPose() {
+    _bindings.spine_skeleton_set_to_setup_pose(_skeleton);
+  }
+
+  /// Sets the bones and constraints to their setup pose values.
+  void setBonesToSetupPose() {
+    _bindings.spine_skeleton_set_bones_to_setup_pose(_skeleton);
+  }
+
+  /// Sets the slots and draw order to their setup pose values.
+  void setSlotsToSetupPose() {
+    _bindings.spine_skeleton_set_slots_to_setup_pose(_skeleton);
+  }
+
+  /// Finds a bone by comparing each bone's name. It is more efficient to cache the results of this method than to call it
+  /// repeatedly.
+  Bone? findBone(String boneName) {
+    final nameNative = boneName.toNativeUtf8(allocator: _allocator);
+    final bone = _bindings.spine_skeleton_find_bone(_skeleton, nameNative.cast());
+    _allocator.free(nameNative);
+    if (bone.address == nullptr.address) return null;
+    return Bone._(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
+  /// repeatedly.
+  Slot? findSlot(String slotName) {
+    final nameNative = slotName.toNativeUtf8(allocator: _allocator);
+    final slot = _bindings.spine_skeleton_find_slot(_skeleton, nameNative.cast());
+    _allocator.free(nameNative);
+    if (slot.address == nullptr.address) return null;
+    return Slot._(slot);
+  }
+
+  /// Sets a skin by name.
+  ///
+  /// See [setSkin].
+  void setSkinByName(String skinName) {
+    final nameNative = skinName.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_skeleton_set_skin_by_name(_skeleton, nameNative.cast());
+    _allocator.free(nameNative);
+  }
+
+  /// Sets the skin used to look up attachments before looking in the default skin (see [SkeletonData.getDefaultSkin]). If the
+  /// skin is changed, [updateCache] is called.
+  ///
+  /// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was no
+  /// old skin, each slot's setup mode attachment is attached from the new skin.
+  ///
+  /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
+  /// [setSlotsToSetupPose]. Also, often [AnimationState.apply] is called before the next time the
+  /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new
+  /// skin.
+  void setSkin(Skin skin) {
+    _bindings.spine_skeleton_set_skin(_skeleton, skin._skin);
+  }
+
+  /// Finds an attachment by looking in the currently set skin (see [getSkin]) and default skin (see [SkeletonData.getDefaultSkin]) using
+  /// the slot name and attachment name.
+  ///
+  /// See [getAttachment].
+  Attachment? getAttachmentByName(String slotName, String attachmentName) {
+    final slotNameNative = slotName.toNativeUtf8(allocator: _allocator);
+    final attachmentNameNative = attachmentName.toNativeUtf8(allocator: _allocator);
+    final attachment = _bindings.spine_skeleton_get_attachment_by_name(
+      _skeleton,
+      slotNameNative.cast(),
+      attachmentNameNative.cast(),
+    );
+    _allocator.free(slotNameNative);
+    _allocator.free(attachmentNameNative);
+    if (attachment.address == nullptr.address) return null;
+    return Attachment._toSubclass(attachment);
+  }
+
+  /// Finds an attachment by looking in the currently set skin (see [getSkin]) and default skin (see [SkeletonData.getDefaultSkin]) using the
+  /// slot index and attachment name. First the skin is checked and if the attachment was not found, the default skin is checked.
+  ///
+  /// See [Runtime skins](http://esotericsoftware.com/spine-runtime-skins) in the Spine Runtimes Guide.
+  Attachment? getAttachment(int slotIndex, String attachmentName) {
+    final attachmentNameNative = attachmentName.toNativeUtf8(allocator: _allocator);
+    final attachment = _bindings.spine_skeleton_get_attachment(_skeleton, slotIndex, attachmentNameNative.cast());
+    _allocator.free(attachmentNameNative);
+    if (attachment.address == nullptr.address) return null;
+    return Attachment._toSubclass(attachment);
+  }
+
+  /// A convenience method to set an attachment by finding the slot with [findSlot], finding the attachment with
+  /// [getAttachment], then setting the slot's attachment. The [attachmentName] may be an empty string to clear the slot's attachment.
+  void setAttachment(String slotName, String attachmentName) {
+    final slotNameNative = slotName.toNativeUtf8(allocator: _allocator);
+    final attachmentNameNative = attachmentName.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_skeleton_set_attachment(_skeleton, slotNameNative.cast(), attachmentNameNative.cast());
+    _allocator.free(slotNameNative);
+    _allocator.free(attachmentNameNative);
+  }
+
+  /// 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 repeatedly.
+  IkConstraint? findIkConstraint(String constraintName) {
+    final nameNative = constraintName.toNativeUtf8(allocator: _allocator);
+    final constraint = _bindings.spine_skeleton_find_ik_constraint(_skeleton, nameNative.cast());
+    _allocator.free(nameNative);
+    if (constraint.address == nullptr.address) return null;
+    return IkConstraint._(constraint);
+  }
+
+  /// 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 repeatedly.
+  TransformConstraint? findTransformConstraint(String constraintName) {
+    final nameNative = constraintName.toNativeUtf8(allocator: _allocator);
+    final constraint = _bindings.spine_skeleton_find_transform_constraint(_skeleton, nameNative.cast());
+    _allocator.free(nameNative);
+    if (constraint.address == nullptr.address) return null;
+    return TransformConstraint._(constraint);
+  }
+
+  /// 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 repeatedly.
+  PathConstraint? findPathConstraint(String constraintName) {
+    final nameNative = constraintName.toNativeUtf8(allocator: _allocator);
+    final constraint = _bindings.spine_skeleton_find_path_constraint(_skeleton, nameNative.cast());
+    _allocator.free(nameNative);
+    if (constraint.address == nullptr.address) return null;
+    return PathConstraint._(constraint);
+  }
+
+  /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
+  Bounds getBounds() {
+    final nativeBounds = _bindings.spine_skeleton_get_bounds(_skeleton);
+    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),
+    );
+    return bounds;
+  }
+
+  /// Returns the root bone, or null if the skeleton has no bones.
+  Bone? getRootBone() {
+    final bone = _bindings.spine_skeleton_get_root_bone(_skeleton);
+    if (bone.address == nullptr.address) return null;
+    return Bone._(bone);
+  }
+
+  /// The skeleton's setup pose data.
+  SkeletonData? getData() {
+    final data = _bindings.spine_skeleton_get_data(_skeleton);
+    if (data.address == nullptr.address) return null;
+    return SkeletonData._(data);
+  }
+
+  /// The skeleton's bones, sorted parent first. The root bone is always the first bone.
+  List<Bone> getBones() {
+    final List<Bone> bones = [];
+    final numBones = _bindings.spine_skeleton_get_num_bones(_skeleton);
+    final nativeBones = _bindings.spine_skeleton_get_bones(_skeleton);
+    for (int i = 0; i < numBones; i++) {
+      bones.add(Bone._(nativeBones[i]));
+    }
+    return bones;
+  }
+
+  /// The skeleton's slots.
+  List<Slot> getSlots() {
+    final List<Slot> slots = [];
+    final numSlots = _bindings.spine_skeleton_get_num_slots(_skeleton);
+    final nativeSlots = _bindings.spine_skeleton_get_slots(_skeleton);
+    for (int i = 0; i < numSlots; i++) {
+      slots.add(Slot._(nativeSlots[i]));
+    }
+    return slots;
+  }
+
+  /// The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order.
+  List<Slot> getDrawOrder() {
+    final List<Slot> slots = [];
+    final numSlots = _bindings.spine_skeleton_get_num_draw_order(_skeleton);
+    final nativeDrawOrder = _bindings.spine_skeleton_get_draw_order(_skeleton);
+    for (int i = 0; i < numSlots; i++) {
+      slots.add(Slot._(nativeDrawOrder[i]));
+    }
+    return slots;
+  }
+
+  /// The skeleton's IK constraints.
+  List<IkConstraint> getIkConstraints() {
+    final List<IkConstraint> constraints = [];
+    final numConstraints = _bindings.spine_skeleton_get_num_ik_constraints(_skeleton);
+    final nativeConstraints = _bindings.spine_skeleton_get_ik_constraints(_skeleton);
+    for (int i = 0; i < numConstraints; i++) {
+      constraints.add(IkConstraint._(nativeConstraints[i]));
+    }
+    return constraints;
+  }
+
+  /// The skeleton's path constraints.
+  List<PathConstraint> getPathConstraints() {
+    final List<PathConstraint> constraints = [];
+    final numConstraints = _bindings.spine_skeleton_get_num_path_constraints(_skeleton);
+    final nativeConstraints = _bindings.spine_skeleton_get_path_constraints(_skeleton);
+    for (int i = 0; i < numConstraints; i++) {
+      constraints.add(PathConstraint._(nativeConstraints[i]));
+    }
+    return constraints;
+  }
+
+  /// The skeleton's transform constraints.
+  List<TransformConstraint> getTransformConstraints() {
+    final List<TransformConstraint> constraints = [];
+    final numConstraints = _bindings.spine_skeleton_get_num_transform_constraints(_skeleton);
+    final nativeConstraints = _bindings.spine_skeleton_get_transform_constraints(_skeleton);
+    for (int i = 0; i < numConstraints; i++) {
+      constraints.add(TransformConstraint._(nativeConstraints[i]));
+    }
+    return constraints;
+  }
+
+  /// The skeleton's current skin.
+  Skin? getSkin() {
+    final skin = _bindings.spine_skeleton_get_skin(_skeleton);
+    if (skin.address == nullptr.address) return null;
+    return Skin._(skin);
+  }
+
+  /// The color to tint all the skeleton's attachments.
+  Color getColor() {
+    final color = _bindings.spine_skeleton_get_color(_skeleton);
+    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) {
+    _bindings.spine_skeleton_set_color(_skeleton, color.r, color.g, color.b, color.a);
+  }
+
+  /// Sets the skeleton X and Y position, which is added to the root bone worldX and worldY position.
+  ///
+  /// Bones that do not inherit translation are still affected by this property.
+  void setPosition(double x, double y) {
+    _bindings.spine_skeleton_set_position(_skeleton, x, y);
+  }
+
+  Vec2 getPosition() {
+    final x = _bindings.spine_skeleton_get_x(_skeleton);
+    final y = _bindings.spine_skeleton_get_y(_skeleton);
+    return Vec2(x, y);
+  }
+
+  /// Sets the skeleton X position, which is added to the root bone worldX position.
+  ///
+  /// Bones that do not inherit translation are still affected by this property.
+  double getX() {
+    return _bindings.spine_skeleton_get_x(_skeleton);
+  }
+
+  void setX(double x) {
+    _bindings.spine_skeleton_set_x(_skeleton, x);
+  }
+
+  /// Sets the skeleton Y position, which is added to the root bone worldY position.
+  /// <p>
+  /// Bones that do not inherit translation are still affected by this property.
+  double getY() {
+    return _bindings.spine_skeleton_get_y(_skeleton);
+  }
+
+  void setY(double y) {
+    _bindings.spine_skeleton_set_y(_skeleton, y);
+  }
+
+  /// Scales the entire skeleton on the X axis.
+  ///
+  /// Bones that do not inherit scale are still affected by this property.
+  double getScaleX() {
+    return _bindings.spine_skeleton_get_scale_x(_skeleton);
+  }
+
+  void setScaleX(double scaleX) {
+    _bindings.spine_skeleton_set_scale_x(_skeleton, scaleX);
+  }
+
+  /// Scales the entire skeleton on the Y axis.
+  ///
+  /// Bones that do not inherit scale are still affected by this property.
+  double getScaleY() {
+    return _bindings.spine_skeleton_get_scale_y(_skeleton);
+  }
+
+  void setScaleY(double scaleY) {
+    _bindings.spine_skeleton_set_scale_y(_skeleton, scaleY);
+  }
+
+  double getTime() {
+    return _bindings.spine_skeleton_get_time(_skeleton);
+  }
+
+  void setTime(double time) {
+    return _bindings.spine_skeleton_set_time(_skeleton, time);
+  }
+
+  void update(double delta) {
+    _bindings.spine_skeleton_update(_skeleton, delta);
+  }
+}
+
+/// Stores a list of timelines to animate a skeleton's pose over time.
+class Animation {
+  final spine_animation _animation;
+
+  Animation._(this._animation);
+
+  /// The animation's name, which is unique across all animations in the skeleton.
+  String getName() {
+    final Pointer<Utf8> value = _bindings.spine_animation_get_name(_animation).cast();
+    return value.toDartString();
+  }
+
+  /// The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is
+  /// used to know when it has completed and when it should loop back to the start.
+  double getDuration() {
+    return _bindings.spine_animation_get_duration(_animation);
+  }
+}
+
+/// Controls how timeline values are mixed with setup pose values or current pose values when a timeline is applied with
+/// <code>alpha</code> < 1.
+enum MixBlend {
+  /// Transitions from the setup value to the timeline value (the current value is not used). Before the first frame, the
+  /// setup value is set.
+  setup(0),
+
+  /// Transitions from the current value to the timeline value. Before the first frame, transitions from the current value to
+  /// the setup value. Timelines which perform instant transitions, such as {@link DrawOrderTimeline} or
+  /// {link AttachmentTimeline}, use the setup value before the first frame.
+  /// <p>
+  /// <code>first</code> is intended for the first animations applied, not for animations layered on top of those.
+  first(1),
+
+  /// Transitions from the current value to the timeline value. No change is made before the first frame (the current value is
+  /// kept until the first frame).
+  /// <p>
+  /// <code>replace</code> is intended for animations layered on top of others, not for the first animations applied.
+  replace(2),
+
+  /// Transitions from the current value to the current value plus the timeline value. No change is made before the first
+  /// frame (the current value is kept until the first frame).
+  /// <p>
+  /// <code>add</code> is intended for animations layered on top of others, not for the first animations applied. Properties
+  /// set by additive animations must be set manually or by another animation before applying the additive animations, else the
+  /// property values will increase each time the additive animations are applied.
+  add(3);
+
+  final int value;
+
+  const MixBlend(this.value);
+}
+
+/// Stores settings and other state for the playback of an animation on an [AnimationState] track.
+///
+/// References to a track entry must not be kept after the dispose [EventType] is reported to [AnimationStateListener].
+class TrackEntry {
+  final spine_track_entry _entry;
+  final AnimationState _state;
+
+  TrackEntry._(this._entry, this._state);
+
+  /// The index of the track where this track entry is either current or queued.
+  ///
+  /// See [AnimationState.getCurrent].
+  int getTtrackIndex() {
+    return _bindings.spine_track_entry_get_track_index(_entry);
+  }
+
+  /// The animation to apply for this track entry.
+  Animation getAnimation() {
+    return Animation._(_bindings.spine_track_entry_get_animation(_entry));
+  }
+
+  /// If true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
+  /// duration.
+  bool getLoop() {
+    return _bindings.spine_track_entry_get_loop(_entry) == -1;
+  }
+
+  void setLoop(bool loop) {
+    _bindings.spine_track_entry_set_loop(_entry, loop ? -1 : 0);
+  }
+
+  /// Seconds to postpone playing the animation. When this track entry is the current track entry, <code>delay</code>
+  /// postpones incrementing the [getTrackTime]. When this track entry is queued, <code>delay</code> is the time from
+  /// the start of the previous animation to when this track entry will become the current track entry (ie when the previous
+  /// track entry [getTrackTime] >= this track entry's <code>delay</code>).
+  ///
+  /// [getTimeScale] affects the delay.
+  ///
+  /// When using [AnimationState.addAnimation] with a <code>delay</code> <= 0, the delay
+  /// is set using the mix duration from the [AnimationStateData]. If [getMixDuration] is set afterward, the delay
+  /// may need to be adjusted.
+  bool getHoldPrevious() {
+    return _bindings.spine_track_entry_get_hold_previous(_entry) == -1;
+  }
+
+  void setHoldPrevious(bool holdPrevious) {
+    _bindings.spine_track_entry_set_hold_previous(_entry, holdPrevious ? -1 : 0);
+  }
+
+  /// If true, the animation will be applied in reverse. Events are not fired when an animation is applied in reverse.
+  bool getReverse() {
+    return _bindings.spine_track_entry_get_reverse(_entry) == -1;
+  }
+
+  void setReverse(bool reverse) {
+    _bindings.spine_track_entry_set_reverse(_entry, reverse ? -1 : 0);
+  }
+
+  /// If true, mixing rotation between tracks always uses the shortest rotation direction. If the rotation is animated, the
+  /// shortest rotation direction may change during the mix.
+  ///
+  /// If false, the shortest rotation direction is remembered when the mix starts and the same direction is used for the rest
+  /// of the mix. Defaults to false.
+  bool getShortestRotation() {
+    return _bindings.spine_track_entry_get_shortest_rotation(_entry) == 1;
+  }
+
+  void setShortestRotation(bool shortestRotation) {
+    _bindings.spine_track_entry_set_shortest_rotation(_entry, shortestRotation ? -1 : 0);
+  }
+
+  /// Seconds to postpone playing the animation. When this track entry is the current track entry, <code>delay</code>
+  /// postpones incrementing the [getTrackTime]. When this track entry is queued, <code>delay</code> is the time from
+  /// the start of the previous animation to when this track entry will become the current track entry (ie when the previous
+  /// track entry [getTrackTime] >= this track entry's <code>delay</code>).
+  ///
+  /// [getTimeScale] affects the delay.
+  ///
+  /// When using [AnimationState.addAnimation] with a <code>delay</code> <= 0, the delay
+  /// is set using the mix duration from the [AnimationStateData]. If [getMixDuration] is set afterward, the delay
+  /// may need to be adjusted.
+  double getDelay() {
+    return _bindings.spine_track_entry_get_delay(_entry);
+  }
+
+  void setDelay(double delay) {
+    _bindings.spine_track_entry_set_delay(_entry, delay);
+  }
+
+  /// Current time in seconds this track entry has been the current track entry. The track time determines
+  /// [getAnimationTime]. The track time can be set to start the animation at a time other than 0, without affecting
+  /// looping.
+  double getTrackTime() {
+    return _bindings.spine_track_entry_get_track_time(_entry);
+  }
+
+  void setTrackTime(double trackTime) {
+    _bindings.spine_track_entry_set_track_time(_entry, trackTime);
+  }
+
+  /// The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float
+  /// value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time
+  /// is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the
+  /// properties keyed by the animation are set to the setup pose and the track is cleared.
+  ///
+  /// It may be desired to use [AnimationState.addEmptyAnimation] rather than have the animation
+  /// abruptly cease being applied.
+  double getTrackEnd() {
+    return _bindings.spine_track_entry_get_track_end(_entry);
+  }
+
+  void setTrackEnd(double trackEnd) {
+    _bindings.spine_track_entry_set_track_end(_entry, trackEnd);
+  }
+
+  /// Seconds when this animation starts, both initially and after looping. Defaults to 0.
+  ///
+  /// When changing the <code>animationStart</code> time, it often makes sense to set [getAnimationLast] to the same
+  /// value to prevent timeline keys before the start time from triggering.
+  double getAnimationStart() {
+    return _bindings.spine_track_entry_get_animation_start(_entry);
+  }
+
+  void setAnimationStart(double animationStart) {
+    _bindings.spine_track_entry_set_animation_start(_entry, animationStart);
+  }
+
+  /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will
+  /// loop back to [getAnimationStart] at this time. Defaults to the animation [Animation.getDuration].
+  double getAnimationEnd() {
+    return _bindings.spine_track_entry_get_animation_end(_entry);
+  }
+
+  void setAnimationEnd(double animationEnd) {
+    _bindings.spine_track_entry_set_animation_end(_entry, animationEnd);
+  }
+
+  /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this
+  /// animation is applied, event timelines will fire all events between the <code>animationLast</code> time (exclusive) and
+  /// <code>animationTime</code> (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation
+  /// is applied.
+  double getAnimationLast() {
+    return _bindings.spine_track_entry_get_animation_last(_entry);
+  }
+
+  void setAnimationLast(double animationLast) {
+    _bindings.spine_track_entry_set_animation_last(_entry, animationLast);
+  }
+
+  /// Uses [getTrackTime] to compute the <code>animationTime</code>. When the <code>trackTime</code> is 0, the
+  /// <code>animationTime</code> is equal to the <code>animationStart</code> time.
+  /// <p>
+  /// The <code>animationTime</code> is between [getAnimationStart] and [getAnimationEnd], except if this
+  /// track entry is non-looping and [getAnimationEnd] is >= to the animation [Animation.getDuration], then
+  /// <code>animationTime</code> continues to increase past [getAnimationEnd].
+  double getAnimationTime() {
+    return _bindings.spine_track_entry_get_animation_time(_entry);
+  }
+
+  /// Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or
+  /// faster. Defaults to 1.
+  ///
+  /// Values < 0 are not supported. To play an animation in reverse, use [getReverse].
+  ///
+  /// [getMixTime] is not affected by track entry time scale, so [getMixDuration] may need to be adjusted to
+  /// match the animation speed.
+  ///
+  /// When using [AnimationState.addAnimation] with a <code>delay</code> <= 0, the
+  /// [getDelay] is set using the mix duration from the [AnimationStateData], assuming time scale to be 1. If
+  /// the time scale is not 1, the delay may need to be adjusted.
+  ///
+  /// See [AnimationState.getTimeScale] for affecting all animations.
+  double getTimeScale() {
+    return _bindings.spine_track_entry_get_time_scale(_entry);
+  }
+
+  void setTimeScale(double timeScale) {
+    _bindings.spine_track_entry_set_time_scale(_entry, timeScale);
+  }
+
+  /// Values < 1 mix this animation with the skeleton's current pose (usually the pose resulting from lower tracks). Defaults
+  /// to 1, which overwrites the skeleton's current pose with this animation.
+  ///
+  /// Typically track 0 is used to completely pose the skeleton, then alpha is used on higher tracks. It doesn't make sense to
+  /// use alpha on track 0 if the skeleton pose is from the last frame render.
+  Future<double> getAlpha() async {
+    return _bindings.spine_track_entry_get_alpha(_entry);
+  }
+
+  void setAlpha(double alpha) {
+    _bindings.spine_track_entry_set_alpha(_entry, alpha);
+  }
+
+  /// When the mix percentage ([getMixTime] / [getMixDuration]) is less than the
+  /// <code>eventThreshold</code>, event timelines are applied while this animation is being mixed out. Defaults to 0, so event
+  /// timelines are not applied while this animation is being mixed out.
+  double getEventThreshold() {
+    return _bindings.spine_track_entry_get_event_threshold(_entry);
+  }
+
+  void setEventThreshold(double eventThreshold) {
+    _bindings.spine_track_entry_set_event_threshold(_entry, eventThreshold);
+  }
+
+  /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with
+  /// this animation.
+  ///
+  /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense
+  /// to use alpha on track 0 if the skeleton pose is from the last frame render.
+  double getAlphaAttachmentThreshold() {
+    return _bindings.spine_track_entry_get_alpha_attachment_threshold(_entry);
+  }
+
+  void setAlphaAttachmentThreshold(double attachmentThreshold) {
+    _bindings.spine_track_entry_set_alpha_attachment_threshold(_entry, attachmentThreshold);
+  }
+
+  /// When the mix percentage ([getMixTime] / [getMixDuration]) is less than the
+  /// <code>attachmentThreshold</code>, attachment timelines are applied while this animation is being mixed out. Defaults to
+  /// 0, so attachment timelines are not applied while this animation is being mixed out.
+  double getMixAttachmentThreshold() {
+    return _bindings.spine_track_entry_get_mix_attachment_threshold(_entry);
+  }
+
+  void setMixAttachmentThreshold(double attachmentThreshold) {
+    _bindings.spine_track_entry_set_mix_attachment_threshold(_entry, attachmentThreshold);
+  }
+
+  /// When the mix percentage ([getMixTime] / [getMixDuration]) is less than the
+  /// <code>drawOrderThreshold</code>, draw order timelines are applied while this animation is being mixed out. Defaults to 0,
+  /// so draw order timelines are not applied while this animation is being mixed out.
+  double getMixDrawOrderThreshold() {
+    return _bindings.spine_track_entry_get_mix_draw_order_threshold(_entry);
+  }
+
+  void setMixDrawOrderThreshold(double drawOrderThreshold) {
+    _bindings.spine_track_entry_set_mix_draw_order_threshold(_entry, drawOrderThreshold);
+  }
+
+  /// The animation queued to start after this animation, or null if there is none. <code>next</code> makes up a doubly linked
+  /// list.
+  ///
+  /// See [AnimationState.clearNext] to truncate the list.
+  TrackEntry? getNext() {
+    final next = _bindings.spine_track_entry_get_next(_entry);
+    if (next.address == nullptr.address) return null;
+    return TrackEntry._(next, _state);
+  }
+
+  /// Returns true if at least one loop has been completed.
+  bool isComplete() {
+    return _bindings.spine_track_entry_is_complete(_entry) == -1;
+  }
+
+  /// Seconds from 0 to the [getMixDuration] when mixing from the previous animation to this animation. May be
+  /// slightly more than <code>mixDuration</code> when the mix is complete.
+  double getMixTime() {
+    return _bindings.spine_track_entry_get_mix_time(_entry);
+  }
+
+  void setMixTime(double mixTime) {
+    _bindings.spine_track_entry_set_mix_time(_entry, mixTime);
+  }
+
+  /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by
+  /// [AnimationStateData.getMix] based on the animation before this animation (if any).
+  ///
+  /// A mix duration of 0 still mixes out over one frame to provide the track entry being mixed out a chance to revert the
+  /// properties it was animating. A mix duration of 0 can be set at any time to end the mix on the next
+  /// [AnimationState.update].
+  ///
+  /// The <code>mixDuration</code> can be set manually rather than use the value from
+  /// [AnimationStateData.getMix]. In that case, the <code>mixDuration</code> can be set for a new
+  /// track entry only before [AnimationState.update] is first called.
+  /// <p>
+  /// When using [AnimationState.addAnimation] with a <code>delay</code> <= 0, the
+  /// [getDelay] is set using the mix duration from the [AnimationStateData]. If <code>mixDuration</code> is set
+  /// afterward, the delay may need to be adjusted. For example:
+  /// <code>entry.delay = entry.previous.getTrackComplete() - entry.mixDuration;</code>
+  double getMixDuration() {
+    return _bindings.spine_track_entry_get_mix_duration(_entry);
+  }
+
+  void setMixDuration(double mixDuration) {
+    _bindings.spine_track_entry_set_mix_duration(_entry, mixDuration);
+  }
+
+  /// Controls how properties keyed in the animation are mixed with lower tracks. Defaults to [MixBlend.replace].
+  ///
+  /// Track entries on track 0 ignore this setting and always use {@link MixBlend#first}.
+  ///
+  /// The <code>mixBlend</code> can be set for a new track entry only before [AnimationState.apply] is first
+  /// called.
+  MixBlend getMixBlend() {
+    return MixBlend.values[_bindings.spine_track_entry_get_mix_blend(_entry)];
+  }
+
+  void setMixBlend(MixBlend mixBlend) {
+    _bindings.spine_track_entry_set_mix_blend(_entry, mixBlend.value);
+  }
+
+  /// The track entry for the previous animation when mixing from the previous animation to this animation, or null if no
+  /// mixing is currently occurring. When mixing from multiple animations, <code>mixingFrom</code> makes up a linked list.
+  TrackEntry? getMixingFrom() {
+    final from = _bindings.spine_track_entry_get_mixing_from(_entry);
+    if (from.address == nullptr.address) return null;
+    return TrackEntry._(from, _state);
+  }
+
+  /// The track entry for the next animation when mixing from this animation to the next animation, or null if no mixing is
+  /// currently occurring. When mixing to multiple animations, <code>mixingTo</code> makes up a linked list.
+  TrackEntry? getMixingTo() {
+    final to = _bindings.spine_track_entry_get_mixing_to(_entry);
+    if (to.address == nullptr.address) return null;
+    return TrackEntry._(to, _state);
+  }
+
+  /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the
+  /// long way around when using alpha and starting animations on other tracks.
+  ///
+  /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around.
+  /// The two rotations likely change over time, so which direction is the short or long way also changes.
+  /// If the short way was always chosen, bones would flip to the other side when that direction became the long way.
+  /// TrackEntry chooses the short way the first time it is applied and remembers that direction.
+  void resetRotationDirections() {
+    _bindings.spine_track_entry_reset_rotation_directions(_entry);
+  }
+
+  /// If this track entry is non-looping, the track time in seconds when [getAnimationEnd] is reached, or the current
+  /// [getTrackTime] if it has already been reached. If this track entry is looping, the track time when this
+  /// animation will reach its next [getAnimationEnd] (the next loop completion).
+  double getTrackComplete() {
+    return _bindings.spine_track_entry_get_track_complete(_entry);
+  }
+
+  bool wasApplied() {
+    return _bindings.spine_track_entry_was_applied(_entry) == -1;
+  }
+
+  bool isNextReady() {
+    return _bindings.spine_track_entry_is_next_ready(_entry) == -1;
+  }
+
+  /// The listener for events generated by this track entry, or null.
+  ///
+  /// A track entry returned from [AnimationState.setAnimation] is already the current animation
+  /// for the track, so the track entry listener will not be called for [EventType.start].
+  void setListener(AnimationStateListener? listener) {
+    _state._setTrackEntryListener(_entry, listener);
+  }
+}
+
+/// The event type passed to [AnimationStateListener]
+enum EventType {
+  /// Emitted when [TrackEntry] has been set as the current entry. [EventType.end] will occur when this entry will no
+  /// longer be applied.
+  start,
+
+  /// Emitted when another entry has replaced the current entry. This entry may continue being applied for
+  /// mixing.
+  interrupt,
+
+  /// Emitted when this entry will never be applied again. This only occurs if this entry has previously been set as the
+  /// current entry ([EventType.start] was emitted).
+  end,
+
+  /// Emitted every time the current entry's animation completes a loop. This may occur during mixing (after
+  /// [EventType.interrupted] is emitted).
+  ///
+  /// If [TrackEntry.getMixingTo] of the entry reported by the event is not null, the entry is mixing out (it is not the current entry).
+  ///
+  /// Because this event is triggered at the end of [AnimationState.apply], any animations set in response to
+  /// the event won't be applied until the next time the [AnimationState] is applied.
+  complete,
+
+  /// Emitted when this entry will be disposed. This may occur without the entry ever being set as the current entry.
+  ///
+  /// References to the entry should not be kept after <code>dispose</code> is called, as it may be destroyed or reused.
+  dispose,
+
+  /// Invoked when the current entry's animation triggers an event. This may occur during mixing (after
+  /// [EventType.interrupt] is emitted), see [TrackEntry.getEventThreshold].
+  ///
+  /// Because this event is triggered at the end of [AnimationState.apply], any animations set in response to
+  /// the event won't be applied until the next time the [AnimationState] is applied.
+  event,
+}
+
+/// Stores the setup pose values for an [Event].
+///
+/// See <a href="http://esotericsoftware.com/spine-events">Events</a> in the Spine User Guide.
+class EventData {
+  final spine_event_data _data;
+
+  EventData._(this._data);
+
+  /// The name of the event, which is unique across all events in the skeleton.
+  String getName() {
+    final Pointer<Utf8> value = _bindings.spine_event_data_get_name(_data).cast();
+    return value.toDartString();
+  }
+
+  int getIntValue() {
+    return _bindings.spine_event_data_get_int_value(_data);
+  }
+
+  void setIntValue(int value) {
+    _bindings.spine_event_data_set_int_value(_data, value);
+  }
+
+  double getFloatValue() {
+    return _bindings.spine_event_data_get_float_value(_data);
+  }
+
+  void setFloatValue(double value) {
+    _bindings.spine_event_data_set_float_value(_data, value);
+  }
+
+  String getStringValue() {
+    final Pointer<Utf8> value = _bindings.spine_event_data_get_string_value(_data).cast();
+    return value.toDartString();
+  }
+
+  void setStringValue(String value) {
+    final nativeString = value.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_event_data_set_string_value(_data, nativeString.cast());
+    _allocator.free(nativeString);
+  }
+
+  String getAudioPath() {
+    final Pointer<Utf8> value = _bindings.spine_event_data_get_audio_path(_data).cast();
+    return value.toDartString();
+  }
+
+  double getVolume() {
+    return _bindings.spine_event_data_get_volume(_data);
+  }
+
+  void setVolume(double volume) {
+    _bindings.spine_event_data_set_volume(_data, volume);
+  }
+
+  double getBalance() {
+    return _bindings.spine_event_data_get_balance(_data);
+  }
+
+  void setBalance(double value) {
+    _bindings.spine_event_data_set_balance(_data, value);
+  }
+}
+
+/// Stores the current pose values for an {@link Event}.
+///
+/// See [AnimationStateListener], [EventType.event], and
+/// <a href="http://esotericsoftware.com/spine-events">Events</a> in the Spine User Guide.
+class Event {
+  final spine_event _event;
+
+  Event._(this._event);
+
+  /// The events's setup pose data.
+  EventData getData() {
+    return EventData._(_bindings.spine_event_get_data(_event));
+  }
+
+  /// The animation time this event was keyed.
+  double getTime() {
+    return _bindings.spine_event_get_time(_event);
+  }
+
+  int getIntValue() {
+    return _bindings.spine_event_get_int_value(_event);
+  }
+
+  void setIntValue(int value) {
+    _bindings.spine_event_set_int_value(_event, value);
+  }
+
+  double getFloatValue() {
+    return _bindings.spine_event_get_float_value(_event);
+  }
+
+  void setFloatValue(double value) {
+    _bindings.spine_event_set_float_value(_event, value);
+  }
+
+  String getStringValue() {
+    final Pointer<Utf8> value = _bindings.spine_event_get_string_value(_event).cast();
+    return value.toDartString();
+  }
+
+  void setStringValue(String value) {
+    final nativeString = value.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_event_set_string_value(_event, nativeString.cast());
+    _allocator.free(nativeString);
+  }
+
+  double getVolume() {
+    return _bindings.spine_event_get_volume(_event);
+  }
+
+  void setVolume(double volume) {
+    _bindings.spine_event_set_volume(_event, volume);
+  }
+
+  double getBalance() {
+    return _bindings.spine_event_get_balance(_event);
+  }
+
+  void setBalance(double balance) {
+    _bindings.spine_event_set_balance(_event, balance);
+  }
+}
+
+/// The callback to implement for receiving [TrackEntry] events. It is always safe to call [AnimationState] methods when receiving
+/// events.
+///
+/// TrackEntry events are collected during [AnimationState.update] and [AnimationState.apply] and
+/// fired only after those methods are finished.
+///
+/// See [TrackEntry.setListener] and [AnimationState.setListener].
+typedef AnimationStateListener = void Function(EventType type, TrackEntry entry, Event? event);
+
+/// Stores mix (crossfade) durations to be applied when {@link AnimationState} animations are changed.
+class AnimationStateData {
+  final spine_animation_state_data _data;
+
+  AnimationStateData._(this._data);
+
+  /// The SkeletonData to look up animations when they are specified by name.
+  SkeletonData getSkeletonData() {
+    return SkeletonData._(_bindings.spine_animation_state_data_get_skeleton_data(_data));
+  }
+
+  double getDefaultMix() {
+    return _bindings.spine_animation_state_data_get_default_mix(_data);
+  }
+
+  void setDefaultMix(double defaultMix) {
+    _bindings.spine_animation_state_data_set_default_mix(_data, defaultMix);
+  }
+
+  /// Sets a mix duration by animation name.
+  ///
+  /// See [setMix].
+  void setMixByName(String fromName, String toName, double duration) {
+    final fromNative = fromName.toNativeUtf8(allocator: _allocator);
+    final toNative = toName.toNativeUtf8(allocator: _allocator);
+    _bindings.spine_animation_state_data_set_mix_by_name(_data, fromNative.cast(), toNative.cast(), duration);
+    _allocator.free(fromNative);
+    _allocator.free(toNative);
+  }
+
+  /// Returns the mix duration to use when changing from the specified animation to the other, or the [getDefaultMix] if
+  /// no mix duration has been set.
+  double getMixByName(String fromName, String toName) {
+    final fromNative = fromName.toNativeUtf8(allocator: _allocator);
+    final toNative = toName.toNativeUtf8(allocator: _allocator);
+    final duration = _bindings.spine_animation_state_data_get_mix_by_name(_data, fromNative.cast(), toNative.cast());
+    _allocator.free(fromNative);
+    _allocator.free(toNative);
+    return duration;
+  }
+
+  /// Sets the mix duration when changing from the specified animation to the other.
+  ///
+  /// See [TrackEntry.mixDuration].
+  Future<void> setMix(Animation from, Animation to, double duration) async {
+    _bindings.spine_animation_state_data_set_mix(_data, from._animation, to._animation, duration);
+  }
+
+  /// Returns the mix duration to use when changing from the specified animation to the other, or the [getDefaultMix] if
+  /// no mix duration has been set.
+  double getMix(Animation from, Animation to) {
+    return _bindings.spine_animation_state_data_get_mix(_data, from._animation, to._animation);
+  }
+
+  /// Removes all mix durations.
+  void clear() {
+    _bindings.spine_animation_state_data_clear(_data);
+  }
+}
+
+/// Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
+/// multiple animations on top of each other (layering).
+///
+/// See <a href='http://esotericsoftware.com/spine-applying-animations/'>Applying Animations</a> in the Spine Runtimes Guide.
+class AnimationState {
+  final spine_animation_state _state;
+  final spine_animation_state_events _events;
+  final Map<spine_track_entry, AnimationStateListener> _trackEntryListeners;
+  AnimationStateListener? _stateListener;
+
+  AnimationState._(this._state, this._events) : _trackEntryListeners = {};
+
+  void _setTrackEntryListener(spine_track_entry entry, AnimationStateListener? listener) {
+    if (listener == null) {
+      _trackEntryListeners.remove(entry);
+    } else {
+      _trackEntryListeners[entry] = listener;
+    }
+  }
+
+  /// Increments each track entry [TrackEntry.getTrackTime], setting queued animations as current if needed.
+  void update(double delta) {
+    _bindings.spine_animation_state_update(_state, delta);
+
+    final numEvents = _bindings.spine_animation_state_events_get_num_events(_events);
+    if (numEvents > 0) {
+      for (int i = 0; i < numEvents; i++) {
+        late final EventType type;
+        switch (_bindings.spine_animation_state_events_get_event_type(_events, i)) {
+          case 0:
+            type = EventType.start;
+            break;
+          case 1:
+            type = EventType.interrupt;
+            break;
+          case 2:
+            type = EventType.end;
+            break;
+          case 3:
+            type = EventType.complete;
+            break;
+          case 4:
+            type = EventType.dispose;
+            break;
+          case 5:
+            type = EventType.event;
+            break;
+        }
+        final nativeEntry = _bindings.spine_animation_state_events_get_track_entry(_events, i);
+        final entry = TrackEntry._(nativeEntry, this);
+        final nativeEvent = _bindings.spine_animation_state_events_get_event(_events, i);
+        final event = nativeEvent.address == nullptr.address ? null : Event._(nativeEvent);
+        if (_trackEntryListeners.containsKey(nativeEntry)) {
+          _trackEntryListeners[nativeEntry]?.call(type, entry, event);
+        }
+        if (_stateListener != null) {
+          _stateListener?.call(type, entry, event);
+        }
+        if (type == EventType.dispose) {
+          _bindings.spine_animation_state_dispose_track_entry(_state, nativeEntry);
+        }
+      }
+    }
+    _bindings.spine_animation_state_events_reset(_events);
+  }
+
+  /// Poses the skeleton using the track entry animations. The animation state is not changed, so can be applied to multiple
+  /// skeletons to pose them identically.
+  ///
+  /// Returns true if any animations were applied.
+  void apply(Skeleton skeleton) {
+    _bindings.spine_animation_state_apply(_state, skeleton._skeleton);
+  }
+
+  /// Removes all animations from all tracks, leaving skeletons in their current pose.
+  ///
+  /// It may be desired to use [setEmptyAnimations] to mix the skeletons back to the setup pose,
+  /// rather than leaving them in their current pose.
+  void clearTracks() {
+    _bindings.spine_animation_state_clear_tracks(_state);
+  }
+
+  /// Removes all animations from the track, leaving skeletons in their current pose.
+  ///
+  /// It may be desired to use [setEmptyAnimations] to mix the skeletons back to the setup pose,
+  /// rather than leaving them in their current pose.
+  void clearTrack(int trackIndex) {
+    _bindings.spine_animation_state_clear_track(_state, trackIndex);
+  }
+
+  /// Sets an animation by name.
+  ///
+  /// See [setAnimation].
+  TrackEntry setAnimationByName(int trackIndex, String animationName, bool loop) {
+    final animation = animationName.toNativeUtf8(allocator: _allocator);
+    final entry = _bindings.spine_animation_state_set_animation_by_name(
+      _state,
+      trackIndex,
+      animation.cast(),
+      loop ? -1 : 0,
+    );
+    _allocator.free(animation);
+    if (entry.address == nullptr.address) throw Exception("Couldn't set animation $animationName");
+    return TrackEntry._(entry, this);
+  }
+
+  /// Sets the current [animation] for a track at [trackIndex], discarding any queued animations. If the formerly current track entry was never
+  /// applied to a skeleton, it is replaced (not mixed from).
+  ///
+  /// If [loop] is true, the animation will repeat. If false it will not, instead its last frame is applied if played beyond its
+  /// duration. In either case [TrackEntry.getTrackEnd] determines when the track is cleared.
+  ///
+  /// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
+  /// after the [EventType.dispose] event occurs.
+  TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) {
+    final entry = _bindings.spine_animation_state_set_animation(
+      _state,
+      trackIndex,
+      animation._animation,
+      loop ? -1 : 0,
+    );
+    if (entry.address == nullptr.address) throw Exception("Couldn't set animation ${animation.getName()}");
+    return TrackEntry._(entry, this);
+  }
+
+  /// Queues an animation by name.
+  ///
+  /// See [addAnimation].
+  TrackEntry addAnimationByName(int trackIndex, String animationName, bool loop, double delay) {
+    final animation = animationName.toNativeUtf8(allocator: _allocator);
+    final entry = _bindings.spine_animation_state_add_animation_by_name(
+      _state,
+      trackIndex,
+      animation.cast(),
+      loop ? -1 : 0,
+      delay,
+    );
+    _allocator.free(animation);
+    if (entry.address == nullptr.address) throw Exception("Couldn't add animation $animationName");
+    return TrackEntry._(entry, this);
+  }
+
+  /// Adds an [animation] to be played after the current or last queued animation for a track at [trackIndex]. If the track is empty, it is
+  /// equivalent to calling [setAnimation].
+  ///
+  /// If [delay] > 0, sets [TrackEntry.getDelay]. If [delay] <= 0, the delay set is the duration of the previous track entry
+  /// minus any mix duration (from the [AnimationStateData]) plus the specified <code>delay</code> (ie the mix
+  /// ends at (<code>delay</code> = 0) or before (<code>delay</code> < 0) the previous track entry duration). If the
+  /// previous entry is looping, its next loop completion is used instead of its duration.
+  ///
+  /// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
+  /// after the [EventType.dispose] event occurs.
+  TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, double delay) {
+    final entry = _bindings.spine_animation_state_add_animation(
+      _state,
+      trackIndex,
+      animation._animation,
+      loop ? -1 : 0,
+      delay,
+    );
+    if (entry.address == nullptr.address) throw Exception("Couldn't add animation ${animation.getName()}");
+    return TrackEntry._(entry, this);
+  }
+
+  /// Sets an empty animation for a track at [trackIndex], discarding any queued animations, and sets the track entry's
+  /// [TrackEntry.getMixDuration] to [mixDuration]. An empty animation has no timelines and serves as a placeholder for mixing in or out.
+  ///
+  /// Mixing out is done by setting an empty animation with a mix duration using either [setEmptyAnimation],
+  /// [setEmptyAnimations], or [addEmptyAnimation]. Mixing to an empty animation causes
+  /// the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation
+  /// transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of
+  /// 0 still mixes out over one frame.
+  ///
+  /// Mixing in is done by first setting an empty animation, then adding an animation using
+  /// [addAnimation] with the desired delay (an empty animation has a duration of 0) and on
+  /// the returned track entry, set the [TrackEntry.setMixDuration]. Mixing from an empty animation causes the new
+  /// animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value
+  /// from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new
+  /// animation.
+  TrackEntry setEmptyAnimation(int trackIndex, double mixDuration) {
+    final entry = _bindings.spine_animation_state_set_empty_animation(_state, trackIndex, mixDuration);
+    return TrackEntry._(entry, this);
+  }
+
+  /// Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
+  /// [TrackEntry.getMixDuration]. If the track is empty, it is equivalent to calling
+  /// [setEmptyAnimation].
+  ///
+  /// See [setEmptyAnimation].
+  ///
+  /// If [delay] > 0, sets [TrackEntry.getDelay]. If <= 0, the delay set is the duration of the previous track entry
+  /// minus any mix duration plus the specified <code>delay</code> (ie the mix ends at (<code>delay</code> = 0) or
+  /// before (<code>delay</code> < 0) the previous track entry duration). If the previous entry is looping, its next
+  /// loop completion is used instead of its duration.
+  ///
+  /// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
+  /// after the [EventType.dispose] event occurs.
+  TrackEntry addEmptyAnimation(int trackIndex, double mixDuration, double delay) {
+    final entry = _bindings.spine_animation_state_add_empty_animation(_state, trackIndex, mixDuration, delay);
+    return TrackEntry._(entry, this);
+  }
+
+  /// Returns the track entry for the animation currently playing on the track, or null if no animation is currently playing.
+  TrackEntry? getCurrent(int trackIndex) {
+    final entry = _bindings.spine_animation_state_get_current(_state, trackIndex);
+    if (entry.address == nullptr.address) return null;
+    return TrackEntry._(entry, this);
+  }
+
+  /// Returns the number of tracks that have animations queued.
+  int getNumTracks() {
+    return _bindings.spine_animation_state_get_num_tracks(_state);
+  }
+
+  /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix
+  /// duration.
+  void setEmptyAnimations(double mixDuration) {
+    _bindings.spine_animation_state_set_empty_animations(_state, mixDuration);
+  }
+
+  /// Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower
+  /// or faster. Defaults to 1.
+  ///
+  /// See [TrackEntry.getTimeScale] for affecting a single animation.
+  double getTimeScale() {
+    return _bindings.spine_animation_state_get_time_scale(_state);
+  }
+
+  void setTimeScale(double timeScale) {
+    _bindings.spine_animation_state_set_time_scale(_state, timeScale);
+  }
+
+  /// The [AnimationStateData] to look up mix durations.
+  AnimationStateData getData() {
+    return AnimationStateData._(_bindings.spine_animation_state_get_data(_state));
+  }
+
+  /// The listener for events generated for all tracks managed by the AnimationState, or null.
+  ///
+  /// A track entry returned from [setAnimation] is already the current animation
+  /// for the track, so the track entry listener will not be called for [EventType.start].
+  void setListener(AnimationStateListener? listener) {
+    _stateListener = listener;
+  }
+}
+
+/// A SkeletonDrawable bundles loading, updating, and rendering an [Atlas], [Skeleton], and [AnimationState]
+/// into a single easy to use class.
+///
+/// Use the [fromAsset], [fromFile], or [fromHttp] methods to construct a SkeletonDrawable. To have
+/// multiple skeleton drawable instances share the same [Atlas] and [SkeletonData], use the constructor.
+///
+/// You can then directly access the [atlas], [skeletonData], [skeleton], [animationStateData], and [animationState]
+/// to query and animate the skeleton. Use the [AnimationState] to queue animations on one or more tracks
+/// via [AnimationState.setAnimation] or [AnimationState.addAnimation].
+///
+/// To update the [AnimationState] and apply it to the [Skeleton] call the [update] function, providing it
+/// a delta time in seconds to advance the animations.
+///
+/// To render the current pose of the [Skeleton], use the rendering methods [render], [renderToCanvas], [renderToPictureRecorder],
+/// [renderToPng], or [renderToRawImageData], depending on your needs.
+///
+/// When the skeleton drawable is no longer needed, call the [dispose] method to release its resources. If
+/// the skeleton drawable was constructed from a shared [Atlas] and [SkeletonData], make sure to dispose the
+/// atlas and skeleton data as well, if no skeleton drawable references them anymore.
+class SkeletonDrawable {
+  final Atlas atlas;
+  final SkeletonData skeletonData;
+  late final spine_skeleton_drawable _drawable;
+  late final Skeleton skeleton;
+  late final AnimationStateData animationStateData;
+  late final AnimationState animationState;
+  final bool _ownsAtlasAndSkeletonData;
+  bool _disposed;
+
+  /// Constructs a new skeleton drawable from the given (possibly shared) [Atlas] and [SkeletonData]. If
+  /// the atlas and skeleton data are not shared, the drawable can take ownership by passing true for [_ownsAtlasAndSkeletonData].
+  /// In that case a call to [dispose] will also dispose the atlas and skeleton data.
+  SkeletonDrawable(this.atlas, this.skeletonData, this._ownsAtlasAndSkeletonData) : _disposed = false {
+    _drawable = _bindings.spine_skeleton_drawable_create(skeletonData._data);
+    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),
+    );
+    skeleton.updateWorldTransform(Physics.none);
+  }
+
+  /// Constructs a new skeleton drawable from the [atlasFile] and [skeletonFile] from the root asset bundle
+  /// or the optionally provided [bundle].
+  ///
+  /// Throws an exception in case the data could not be loaded.
+  static Future<SkeletonDrawable> fromAsset(String atlasFile, String skeletonFile, {AssetBundle? bundle}) async {
+    bundle ??= rootBundle;
+    var atlas = await Atlas.fromAsset(atlasFile, bundle: bundle);
+    var skeletonData = await SkeletonData.fromAsset(atlas, skeletonFile, bundle: bundle);
+    return SkeletonDrawable(atlas, skeletonData, true);
+  }
+
+  /// Constructs a new skeleton drawable from the [atlasFile] and [skeletonFile].
+  ///
+  /// Throws an exception in case the data could not be loaded.
+  static Future<SkeletonDrawable> fromFile(String atlasFile, String skeletonFile) async {
+    var atlas = await Atlas.fromFile(atlasFile);
+    var skeletonData = await SkeletonData.fromFile(atlas, skeletonFile);
+    return SkeletonDrawable(atlas, skeletonData, true);
+  }
+
+  /// Constructs a new skeleton drawable from the [atlasUrl] and [skeletonUrl].
+  ///
+  /// Throws an exception in case the data could not be loaded.
+  static Future<SkeletonDrawable> fromHttp(String atlasUrl, String skeletonUrl) async {
+    var atlas = await Atlas.fromHttp(atlasUrl);
+    var skeletonData = await SkeletonData.fromHttp(atlas, skeletonUrl);
+    return SkeletonDrawable(atlas, skeletonData, true);
+  }
+
+  /// Updates the [AnimationState] using the [delta] time given in seconds, applies the
+  /// animation state to the [Skeleton] and updates the world transforms of the skeleton
+  /// to calculate its current pose.
+  void update(double delta) {
+    if (_disposed) return;
+    animationState.update(delta);
+    animationState.apply(skeleton);
+    skeleton.update(delta);
+    skeleton.updateWorldTransform(Physics.update);
+  }
+
+  /// Renders to current skeleton pose to a list of [RenderCommand] instances. The render commands
+  /// can be rendered via [Canvas.drawVertices].
+  List<RenderCommand> render() {
+    if (_disposed) return [];
+    spine_render_command nativeCmd = _bindings.spine_skeleton_drawable_render(_drawable);
+    List<RenderCommand> commands = [];
+    while (nativeCmd.address != nullptr.address) {
+      final atlasPage = atlas.atlasPages[_bindings.spine_render_command_get_atlas_page(nativeCmd)];
+      commands.add(RenderCommand._(nativeCmd, atlasPage.width.toDouble(), atlasPage.height.toDouble()));
+      nativeCmd = _bindings.spine_render_command_get_next(nativeCmd);
+    }
+    return commands;
+  }
+
+  /// Renders the skeleton drawable's current pose to the given [canvas]. Does not perform any
+  /// scaling or fitting.
+  List<RenderCommand> renderToCanvas(Canvas canvas) {
+    var commands = render();
+    for (final cmd in commands) {
+      canvas.drawVertices(
+        cmd.vertices,
+        rendering.BlendMode.modulate,
+        atlas.atlasPagePaints[cmd.atlasPageIndex][cmd.blendMode]!,
+      );
+    }
+    return commands;
+  }
+
+  /// Renders the skeleton drawable's current pose to a [PictureRecorder] with the given [width] and [height].
+  /// Uses [bgColor], a 32-bit ARGB color value, to paint the background.
+  /// Scales and centers the skeleton to fit the within the bounds of [width] and [height].
+  PictureRecorder renderToPictureRecorder(double width, double height, int bgColor) {
+    var bounds = skeleton.getBounds();
+    var scale = 1 / (bounds.width > bounds.height ? bounds.width / width : bounds.height / height);
+
+    var recorder = PictureRecorder();
+    var canvas = Canvas(recorder);
+    var paint = Paint()
+      ..color = material.Color(bgColor)
+      ..style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromLTWH(0, 0, width, height), paint);
+    canvas.translate(width / 2, height / 2);
+    canvas.scale(scale, scale);
+    canvas.translate(-(bounds.x + bounds.width / 2), -(bounds.y + bounds.height / 2));
+    canvas.drawRect(const Rect.fromLTRB(-5, -5, 5, -5), paint..color = material.Colors.red);
+    renderToCanvas(canvas);
+    return recorder;
+  }
+
+  /// Renders the skeleton drawable's current pose to a PNG encoded in a [Uint8List], with the given [width] and [height].
+  /// Uses [bgColor], a 32-bit ARGB color value, to paint the background.
+  /// Scales and centers the skeleton to fit the within the bounds of [width] and [height].
+  Future<Uint8List> renderToPng(double width, double height, int bgColor) async {
+    final recorder = renderToPictureRecorder(width, height, bgColor);
+    final image = await recorder.endRecording().toImage(width.toInt(), height.toInt());
+    return (await image.toByteData(format: ImageByteFormat.png))!.buffer.asUint8List();
+  }
+
+  /// Renders the skeleton drawable's current pose to a [RawImageData], with the given [width] and [height].
+  /// Uses [bgColor], a 32-bit ARGB color value, to paint the background.
+  /// Scales and centers the skeleton to fit the within the bounds of [width] and [height].
+  Future<RawImageData> renderToRawImageData(double width, double height, int bgColor) async {
+    final recorder = renderToPictureRecorder(width, height, bgColor);
+    var rawImageData = (await (await recorder.endRecording().toImage(
+      width.toInt(),
+      height.toInt(),
+    )).toByteData(format: ImageByteFormat.rawRgba))!.buffer.asUint8List();
+    return RawImageData(rawImageData, width.toInt(), height.toInt());
+  }
+
+  /// Disposes the skeleton drawable's resources. If the skeleton drawable owns the atlas
+  /// and skeleton data, they are disposed as well. Must be called when the skeleton drawable
+  /// is no longer in use.
+  void dispose() {
+    if (_disposed) return;
+    _disposed = true;
+    if (_ownsAtlasAndSkeletonData) {
+      atlas.dispose();
+      skeletonData.dispose();
+    }
+    _bindings.spine_skeleton_drawable_dispose(_drawable);
+  }
+}
+
+/// Stores the vertices, indices, and atlas page index to be used for rendering one or more attachments
+/// of a [Skeleton] to a [Canvas]. See the implementation of [SkeletonDrawable.renderToCanvas] on how to use this data to render it to a
+/// [Canvas].
+class RenderCommand {
+  late final Vertices vertices;
+  late final int atlasPageIndex;
+  late final Float32List positions;
+  late final Float32List uvs;
+  late final Int32List colors;
+  late final Uint16List indices;
+  late final BlendMode blendMode;
+
+  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);
+    positions = _bindings.spine_render_command_get_positions(nativeCmd).asTypedList(numVertices * 2);
+    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;
+    }
+    colors = _bindings.spine_render_command_get_colors(nativeCmd).asTypedList(numVertices);
+    indices = _bindings.spine_render_command_get_indices(nativeCmd).asTypedList(numIndices);
+    blendMode = BlendMode.values[_bindings.spine_render_command_get_blend_mode(nativeCmd)];
+
+    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
+      //
+      // Impeller is currently using a slow path when using vertex colors.
+      // See https://github.com/flutter/flutter/issues/127486
+      //
+      // We thus batch all meshes not only by atlas page and blend mode, but also vertex color.
+      // See spine_flutter.cpp, batch_commands().
+      //
+      // If the vertex color equals (1, 1, 1, 1), we do not store
+      // colors, which will trigger the fast path in Impeller. Otherwise we have to go the slow path, which
+      // has to render to an offscreen surface.
+      if (colors.isNotEmpty && colors[0] == -1) {
+        vertices = Vertices.raw(VertexMode.triangles, positions, textureCoordinates: uvs, indices: indices);
+      } else {
+        vertices = Vertices.raw(
+          VertexMode.triangles,
+          positions,
+          textureCoordinates: uvs,
+          colors: colors,
+          indices: indices,
+        );
+      }
+    } 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,
+      );
+    }
+  }
+}
+
+/// Renders debug information for a [SkeletonDrawable], like bone locations, to a [Canvas].
+/// See [DebugRenderer.render].
+class DebugRenderer {
+  const DebugRenderer();
+
+  void render(SkeletonDrawable drawable, Canvas canvas, List<RenderCommand> commands) {
+    final bonePaint = Paint()
+      ..color = material.Colors.blue
+      ..style = PaintingStyle.fill;
+    for (final bone in drawable.skeleton.getBones()) {
+      canvas.drawRect(
+        Rect.fromCenter(center: Offset(bone.getWorldX(), bone.getWorldY()), width: 5, height: 5),
+        bonePaint,
+      );
+    }
+  }
+}

+ 1 - 1
spine-flutter/lib/ffi_utf8.dart

@@ -12,7 +12,7 @@ import 'ffi_proxy.dart';
 /// 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 {}
+final class Utf8 extends Opaque {}
 
 /// Extension method for converting a`Pointer<Utf8>` to a [String].
 extension Utf8Pointer on Pointer<Utf8> {

+ 162 - 0
spine-flutter/lib/generated/alpha_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// AlphaTimeline wrapper
+class AlphaTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_alpha_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AlphaTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AlphaTimeline(int frameCount, int bezierCount, int slotIndex) {
+    final ptr = _bindings.spine_alpha_timeline_create(frameCount, bezierCount, slotIndex);
+    return AlphaTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_alpha_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_alpha_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_alpha_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_alpha_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_alpha_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_alpha_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_alpha_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_alpha_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_alpha_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_alpha_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_alpha_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_alpha_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_alpha_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_alpha_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_alpha_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_alpha_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get slotIndex {
+    final result = _bindings.spine_alpha_timeline_get_slot_index(_ptr);
+    return result;
+  }
+
+  set slotIndex(int value) {
+    _bindings.spine_alpha_timeline_set_slot_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_alpha_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_alpha_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_alpha_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_alpha_timeline_dispose(_ptr);
+  }
+}

+ 110 - 0
spine-flutter/lib/generated/animation.dart

@@ -0,0 +1,110 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// Animation wrapper
+class Animation implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_animation_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Animation.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory Animation(String name, ArrayTimeline timelines, double duration) {
+    final ptr = _bindings.spine_animation_create(name.toNativeUtf8().cast<Char>(), timelines.nativePtr.cast(), duration);
+    return Animation.fromPointer(ptr);
+  }
+
+  ArrayTimeline get timelines {
+    final result = _bindings.spine_animation_get_timelines(_ptr);
+    return ArrayTimeline.fromPointer(result);
+  }
+
+  set timelines(ArrayTimeline value) {
+    _bindings.spine_animation_set_timelines(_ptr, value.nativePtr.cast());
+  }
+
+  bool hasTimeline(ArrayPropertyId ids) {
+    final result = _bindings.spine_animation_has_timeline(_ptr, ids.nativePtr.cast());
+    return result;
+  }
+
+  double get duration {
+    final result = _bindings.spine_animation_get_duration(_ptr);
+    return result;
+  }
+
+  set duration(double value) {
+    _bindings.spine_animation_set_duration(_ptr, value);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, bool loop, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_animation_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, loop, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  String get name {
+    final result = _bindings.spine_animation_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  ArrayInt get bones {
+    final result = _bindings.spine_animation_get_bones(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  static int search1(ArrayFloat values, double target) {
+    final result = _bindings.spine_animation_search_1(values.nativePtr.cast(), target);
+    return result;
+  }
+
+  static int search2(ArrayFloat values, double target, int step) {
+    final result = _bindings.spine_animation_search_2(values.nativePtr.cast(), target, step);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_animation_dispose(_ptr);
+  }
+}

+ 160 - 0
spine-flutter/lib/generated/animation_state.dart

@@ -0,0 +1,160 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'skeleton.dart';
+import 'track_entry.dart';
+import 'animation.dart';
+import 'animation_state_data.dart';
+import 'arrays.dart';
+
+/// AnimationState wrapper
+class AnimationState implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_animation_state_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AnimationState.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AnimationState(AnimationStateData data) {
+    final ptr = _bindings.spine_animation_state_create(data.nativePtr.cast());
+    return AnimationState.fromPointer(ptr);
+  }
+
+  void update(double delta) {
+    _bindings.spine_animation_state_update(_ptr, delta);
+  }
+
+  bool apply(Skeleton skeleton) {
+    final result = _bindings.spine_animation_state_apply(_ptr, skeleton.nativePtr.cast());
+    return result;
+  }
+
+  void clearTracks() {
+    _bindings.spine_animation_state_clear_tracks(_ptr);
+  }
+
+  void clearTrack(int trackIndex) {
+    _bindings.spine_animation_state_clear_track(_ptr, trackIndex);
+  }
+
+  TrackEntry setEmptyAnimation(int trackIndex, double mixDuration) {
+    final result = _bindings.spine_animation_state_set_empty_animation(_ptr, trackIndex, mixDuration);
+    return TrackEntry.fromPointer(result);
+  }
+
+  TrackEntry addEmptyAnimation(int trackIndex, double mixDuration, double delay) {
+    final result = _bindings.spine_animation_state_add_empty_animation(_ptr, trackIndex, mixDuration, delay);
+    return TrackEntry.fromPointer(result);
+  }
+
+  set emptyAnimations(double value) {
+    _bindings.spine_animation_state_set_empty_animations(_ptr, value);
+  }
+
+  TrackEntry getCurrent(int trackIndex) {
+    final result = _bindings.spine_animation_state_get_current(_ptr, trackIndex);
+    return TrackEntry.fromPointer(result);
+  }
+
+  AnimationStateData get data {
+    final result = _bindings.spine_animation_state_get_data(_ptr);
+    return AnimationStateData.fromPointer(result);
+  }
+
+  ArrayTrackEntry get tracks {
+    final result = _bindings.spine_animation_state_get_tracks(_ptr);
+    return ArrayTrackEntry.fromPointer(result);
+  }
+
+  double get timeScale {
+    final result = _bindings.spine_animation_state_get_time_scale(_ptr);
+    return result;
+  }
+
+  set timeScale(double value) {
+    _bindings.spine_animation_state_set_time_scale(_ptr, value);
+  }
+
+  void disableQueue() {
+    _bindings.spine_animation_state_disable_queue(_ptr);
+  }
+
+  void enableQueue() {
+    _bindings.spine_animation_state_enable_queue(_ptr);
+  }
+
+  set manualTrackEntryDisposal(bool value) {
+    _bindings.spine_animation_state_set_manual_track_entry_disposal(_ptr, value);
+  }
+
+  bool get manualTrackEntryDisposal {
+    final result = _bindings.spine_animation_state_get_manual_track_entry_disposal(_ptr);
+    return result;
+  }
+
+  void disposeTrackEntry(TrackEntry entry) {
+    _bindings.spine_animation_state_dispose_track_entry(_ptr, entry.nativePtr.cast());
+  }
+
+  TrackEntry setAnimation1(int trackIndex, String animationName, bool loop) {
+    final result = _bindings.spine_animation_state_set_animation_1(_ptr, trackIndex, animationName.toNativeUtf8().cast<Char>(), loop);
+    return TrackEntry.fromPointer(result);
+  }
+
+  TrackEntry setAnimation2(int trackIndex, Animation animation, bool loop) {
+    final result = _bindings.spine_animation_state_set_animation_2(_ptr, trackIndex, animation.nativePtr.cast(), loop);
+    return TrackEntry.fromPointer(result);
+  }
+
+  TrackEntry addAnimation1(int trackIndex, String animationName, bool loop, double delay) {
+    final result = _bindings.spine_animation_state_add_animation_1(_ptr, trackIndex, animationName.toNativeUtf8().cast<Char>(), loop, delay);
+    return TrackEntry.fromPointer(result);
+  }
+
+  TrackEntry addAnimation2(int trackIndex, Animation animation, bool loop, double delay) {
+    final result = _bindings.spine_animation_state_add_animation_2(_ptr, trackIndex, animation.nativePtr.cast(), loop, delay);
+    return TrackEntry.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_animation_state_dispose(_ptr);
+  }
+}

+ 92 - 0
spine-flutter/lib/generated/animation_state_data.dart

@@ -0,0 +1,92 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'skeleton_data.dart';
+import 'animation.dart';
+
+/// AnimationStateData wrapper
+class AnimationStateData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_animation_state_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AnimationStateData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AnimationStateData(SkeletonData skeletonData) {
+    final ptr = _bindings.spine_animation_state_data_create(skeletonData.nativePtr.cast());
+    return AnimationStateData.fromPointer(ptr);
+  }
+
+  SkeletonData get skeletonData {
+    final result = _bindings.spine_animation_state_data_get_skeleton_data(_ptr);
+    return SkeletonData.fromPointer(result);
+  }
+
+  double get defaultMix {
+    final result = _bindings.spine_animation_state_data_get_default_mix(_ptr);
+    return result;
+  }
+
+  set defaultMix(double value) {
+    _bindings.spine_animation_state_data_set_default_mix(_ptr, value);
+  }
+
+  double getMix(Animation from, Animation to) {
+    final result = _bindings.spine_animation_state_data_get_mix(_ptr, from.nativePtr.cast(), to.nativePtr.cast());
+    return result;
+  }
+
+  void clear() {
+    _bindings.spine_animation_state_data_clear(_ptr);
+  }
+
+  void setMix1(String fromName, String toName, double duration) {
+    _bindings.spine_animation_state_data_set_mix_1(_ptr, fromName.toNativeUtf8().cast<Char>(), toName.toNativeUtf8().cast<Char>(), duration);
+  }
+
+  void setMix2(Animation from, Animation to, double duration) {
+    _bindings.spine_animation_state_data_set_mix_2(_ptr, from.nativePtr.cast(), to.nativePtr.cast(), duration);
+  }
+
+  void dispose() {
+    _bindings.spine_animation_state_data_dispose(_ptr);
+  }
+}

+ 787 - 0
spine-flutter/lib/generated/arrays.dart

@@ -0,0 +1,787 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import '../native_array.dart';
+import 'animation.dart';
+import 'atlas_page.dart';
+import 'atlas_region.dart';
+import 'attachment.dart';
+import 'bone.dart';
+import 'bone_data.dart';
+import 'bone_pose.dart';
+import 'bounding_box_attachment.dart';
+import 'constraint.dart';
+import 'constraint_data.dart';
+import 'event.dart';
+import 'event_data.dart';
+import 'from_property.dart';
+import 'physics_constraint.dart';
+import 'polygon.dart';
+import 'skin.dart';
+import 'slot.dart';
+import 'slot_data.dart';
+import 'texture_region.dart';
+import 'timeline.dart';
+import 'to_property.dart';
+import 'track_entry.dart';
+import 'update.dart';
+
+/// Array of float elements
+class ArrayFloat extends NativeArray<double> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayFloat.fromPointer(Pointer<spine_array_float_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_float_size(nativePtr.cast());
+  }
+
+  @override
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_float_buffer(nativePtr.cast());
+    return buffer.cast<Float>()[index];
+  }
+
+}
+
+/// Array of int elements
+class ArrayInt extends NativeArray<int> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayInt.fromPointer(Pointer<spine_array_int_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_int_size(nativePtr.cast());
+  }
+
+  @override
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_int_buffer(nativePtr.cast());
+    return buffer.cast<Int32>()[index];
+  }
+
+}
+
+/// Array of unsigned_short elements
+class ArrayUnsignedShort extends NativeArray<int> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayUnsignedShort.fromPointer(Pointer<spine_array_unsigned_short_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_unsigned_short_size(nativePtr.cast());
+  }
+
+  @override
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_unsigned_short_buffer(nativePtr.cast());
+    return buffer.cast<Uint16>()[index];
+  }
+
+}
+
+/// Array of property_id elements
+class ArrayPropertyId extends NativeArray<int> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayPropertyId.fromPointer(Pointer<spine_array_property_id_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_property_id_size(nativePtr.cast());
+  }
+
+  @override
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_property_id_buffer(nativePtr.cast());
+    // NOTE: This will not compile due to C API bug - buffer() returns int instead of Pointer
+    return buffer.cast<Int64>()[index];
+  }
+
+}
+
+/// Array of Animation elements
+class ArrayAnimation extends NativeArray<Animation> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayAnimation.fromPointer(Pointer<spine_array_animation_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_animation_size(nativePtr.cast());
+  }
+
+  @override
+  Animation operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_animation_buffer(nativePtr.cast());
+    return Animation.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of AtlasPage elements
+class ArrayAtlasPage extends NativeArray<AtlasPage> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayAtlasPage.fromPointer(Pointer<spine_array_atlas_page_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_atlas_page_size(nativePtr.cast());
+  }
+
+  @override
+  AtlasPage operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_atlas_page_buffer(nativePtr.cast());
+    return AtlasPage.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of AtlasRegion elements
+class ArrayAtlasRegion extends NativeArray<AtlasRegion> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayAtlasRegion.fromPointer(Pointer<spine_array_atlas_region_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_atlas_region_size(nativePtr.cast());
+  }
+
+  @override
+  AtlasRegion operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_atlas_region_buffer(nativePtr.cast());
+    return AtlasRegion.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Attachment elements
+class ArrayAttachment extends NativeArray<Attachment> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayAttachment.fromPointer(Pointer<spine_array_attachment_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_attachment_size(nativePtr.cast());
+  }
+
+  @override
+  Attachment operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_attachment_buffer(nativePtr.cast());
+    return Attachment.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Bone elements
+class ArrayBone extends NativeArray<Bone> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayBone.fromPointer(Pointer<spine_array_bone_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_bone_size(nativePtr.cast());
+  }
+
+  @override
+  Bone operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_bone_buffer(nativePtr.cast());
+    return Bone.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of BoneData elements
+class ArrayBoneData extends NativeArray<BoneData> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayBoneData.fromPointer(Pointer<spine_array_bone_data_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_bone_data_size(nativePtr.cast());
+  }
+
+  @override
+  BoneData operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_bone_data_buffer(nativePtr.cast());
+    return BoneData.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of BonePose elements
+class ArrayBonePose extends NativeArray<BonePose> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayBonePose.fromPointer(Pointer<spine_array_bone_pose_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_bone_pose_size(nativePtr.cast());
+  }
+
+  @override
+  BonePose operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_bone_pose_buffer(nativePtr.cast());
+    return BonePose.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of BoundingBoxAttachment elements
+class ArrayBoundingBoxAttachment extends NativeArray<BoundingBoxAttachment> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayBoundingBoxAttachment.fromPointer(Pointer<spine_array_bounding_box_attachment_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_bounding_box_attachment_size(nativePtr.cast());
+  }
+
+  @override
+  BoundingBoxAttachment operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_bounding_box_attachment_buffer(nativePtr.cast());
+    return BoundingBoxAttachment.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Constraint elements
+class ArrayConstraint extends NativeArray<Constraint> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayConstraint.fromPointer(Pointer<spine_array_constraint_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_constraint_size(nativePtr.cast());
+  }
+
+  @override
+  Constraint operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_constraint_buffer(nativePtr.cast());
+    return Constraint.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of ConstraintData elements
+class ArrayConstraintData extends NativeArray<ConstraintData> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayConstraintData.fromPointer(Pointer<spine_array_constraint_data_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_constraint_data_size(nativePtr.cast());
+  }
+
+  @override
+  ConstraintData operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_constraint_data_buffer(nativePtr.cast());
+    return ConstraintData.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Event elements
+class ArrayEvent extends NativeArray<Event> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayEvent.fromPointer(Pointer<spine_array_event_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_event_size(nativePtr.cast());
+  }
+
+  @override
+  Event operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_event_buffer(nativePtr.cast());
+    return Event.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of EventData elements
+class ArrayEventData extends NativeArray<EventData> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayEventData.fromPointer(Pointer<spine_array_event_data_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_event_data_size(nativePtr.cast());
+  }
+
+  @override
+  EventData operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_event_data_buffer(nativePtr.cast());
+    return EventData.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of FromProperty elements
+class ArrayFromProperty extends NativeArray<FromProperty> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayFromProperty.fromPointer(Pointer<spine_array_from_property_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_from_property_size(nativePtr.cast());
+  }
+
+  @override
+  FromProperty operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_from_property_buffer(nativePtr.cast());
+    return FromProperty.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of PhysicsConstraint elements
+class ArrayPhysicsConstraint extends NativeArray<PhysicsConstraint> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayPhysicsConstraint.fromPointer(Pointer<spine_array_physics_constraint_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_physics_constraint_size(nativePtr.cast());
+  }
+
+  @override
+  PhysicsConstraint operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_physics_constraint_buffer(nativePtr.cast());
+    return PhysicsConstraint.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Polygon elements
+class ArrayPolygon extends NativeArray<Polygon> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayPolygon.fromPointer(Pointer<spine_array_polygon_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_polygon_size(nativePtr.cast());
+  }
+
+  @override
+  Polygon operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_polygon_buffer(nativePtr.cast());
+    return Polygon.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Skin elements
+class ArraySkin extends NativeArray<Skin> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArraySkin.fromPointer(Pointer<spine_array_skin_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_skin_size(nativePtr.cast());
+  }
+
+  @override
+  Skin operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_skin_buffer(nativePtr.cast());
+    return Skin.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Slot elements
+class ArraySlot extends NativeArray<Slot> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArraySlot.fromPointer(Pointer<spine_array_slot_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_slot_size(nativePtr.cast());
+  }
+
+  @override
+  Slot operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_slot_buffer(nativePtr.cast());
+    return Slot.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of SlotData elements
+class ArraySlotData extends NativeArray<SlotData> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArraySlotData.fromPointer(Pointer<spine_array_slot_data_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_slot_data_size(nativePtr.cast());
+  }
+
+  @override
+  SlotData operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_slot_data_buffer(nativePtr.cast());
+    return SlotData.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of TextureRegion elements
+class ArrayTextureRegion extends NativeArray<TextureRegion> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayTextureRegion.fromPointer(Pointer<spine_array_texture_region_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_texture_region_size(nativePtr.cast());
+  }
+
+  @override
+  TextureRegion operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_texture_region_buffer(nativePtr.cast());
+    return TextureRegion.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Timeline elements
+class ArrayTimeline extends NativeArray<Timeline> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayTimeline.fromPointer(Pointer<spine_array_timeline_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_timeline_size(nativePtr.cast());
+  }
+
+  @override
+  Timeline operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_timeline_buffer(nativePtr.cast());
+    return Timeline.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of ToProperty elements
+class ArrayToProperty extends NativeArray<ToProperty> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayToProperty.fromPointer(Pointer<spine_array_to_property_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_to_property_size(nativePtr.cast());
+  }
+
+  @override
+  ToProperty operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_to_property_buffer(nativePtr.cast());
+    return ToProperty.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of TrackEntry elements
+class ArrayTrackEntry extends NativeArray<TrackEntry> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayTrackEntry.fromPointer(Pointer<spine_array_track_entry_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_track_entry_size(nativePtr.cast());
+  }
+
+  @override
+  TrackEntry operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_track_entry_buffer(nativePtr.cast());
+    return TrackEntry.fromPointer(buffer[index]);
+  }
+
+}
+
+/// Array of Update elements
+class ArrayUpdate extends NativeArray<Update> {
+  static late SpineFlutterBindings _bindings;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ArrayUpdate.fromPointer(Pointer<spine_array_update_wrapper> super.ptr);
+
+  @override
+  int get length {
+    return _bindings.spine_array_update_size(nativePtr.cast());
+  }
+
+  @override
+  Update operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw RangeError.index(index, this, 'index');
+    }
+    final buffer = _bindings.spine_array_update_buffer(nativePtr.cast());
+    return Update.fromPointer(buffer[index]);
+  }
+
+}

+ 72 - 0
spine-flutter/lib/generated/atlas.dart

@@ -0,0 +1,72 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'atlas_region.dart';
+import 'arrays.dart';
+
+/// Atlas wrapper
+class Atlas implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_atlas_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Atlas.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  void flipV() {
+    _bindings.spine_atlas_flip_v(_ptr);
+  }
+
+  AtlasRegion findRegion(String name) {
+    final result = _bindings.spine_atlas_find_region(_ptr, name.toNativeUtf8().cast<Char>());
+    return AtlasRegion.fromPointer(result);
+  }
+
+  ArrayAtlasPage get pages {
+    final result = _bindings.spine_atlas_get_pages(_ptr);
+    return ArrayAtlasPage.fromPointer(result);
+  }
+
+  ArrayAtlasRegion get regions {
+    final result = _bindings.spine_atlas_get_regions(_ptr);
+    return ArrayAtlasRegion.fromPointer(result);
+  }
+
+}

+ 104 - 0
spine-flutter/lib/generated/atlas_attachment_loader.dart

@@ -0,0 +1,104 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'region_attachment.dart';
+import 'skin.dart';
+import 'sequence.dart';
+import 'mesh_attachment.dart';
+import 'bounding_box_attachment.dart';
+import 'path_attachment.dart';
+import 'point_attachment.dart';
+import 'clipping_attachment.dart';
+import 'atlas_region.dart';
+import 'atlas.dart';
+
+/// AtlasAttachmentLoader wrapper
+class AtlasAttachmentLoader implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_atlas_attachment_loader_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AtlasAttachmentLoader.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AtlasAttachmentLoader(Atlas atlas) {
+    final ptr = _bindings.spine_atlas_attachment_loader_create(atlas.nativePtr.cast());
+    return AtlasAttachmentLoader.fromPointer(ptr);
+  }
+
+  RegionAttachment newRegionAttachment(Skin skin, String name, String path, Sequence sequence) {
+    final result = _bindings.spine_atlas_attachment_loader_new_region_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>(), path.toNativeUtf8().cast<Char>(), sequence.nativePtr.cast());
+    return RegionAttachment.fromPointer(result);
+  }
+
+  MeshAttachment newMeshAttachment(Skin skin, String name, String path, Sequence sequence) {
+    final result = _bindings.spine_atlas_attachment_loader_new_mesh_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>(), path.toNativeUtf8().cast<Char>(), sequence.nativePtr.cast());
+    return MeshAttachment.fromPointer(result);
+  }
+
+  BoundingBoxAttachment newBoundingBoxAttachment(Skin skin, String name) {
+    final result = _bindings.spine_atlas_attachment_loader_new_bounding_box_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return BoundingBoxAttachment.fromPointer(result);
+  }
+
+  PathAttachment newPathAttachment(Skin skin, String name) {
+    final result = _bindings.spine_atlas_attachment_loader_new_path_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return PathAttachment.fromPointer(result);
+  }
+
+  PointAttachment newPointAttachment(Skin skin, String name) {
+    final result = _bindings.spine_atlas_attachment_loader_new_point_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return PointAttachment.fromPointer(result);
+  }
+
+  ClippingAttachment newClippingAttachment(Skin skin, String name) {
+    final result = _bindings.spine_atlas_attachment_loader_new_clipping_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return ClippingAttachment.fromPointer(result);
+  }
+
+  AtlasRegion findRegion(String name) {
+    final result = _bindings.spine_atlas_attachment_loader_find_region(_ptr, name.toNativeUtf8().cast<Char>());
+    return AtlasRegion.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_atlas_attachment_loader_dispose(_ptr);
+  }
+}

+ 161 - 0
spine-flutter/lib/generated/atlas_page.dart

@@ -0,0 +1,161 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'format.dart';
+import 'texture_filter.dart';
+import 'texture_wrap.dart';
+
+/// AtlasPage wrapper
+class AtlasPage implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_atlas_page_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AtlasPage.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AtlasPage(String inName) {
+    final ptr = _bindings.spine_atlas_page_create(inName.toNativeUtf8().cast<Char>());
+    return AtlasPage.fromPointer(ptr);
+  }
+
+  String get name {
+    final result = _bindings.spine_atlas_page_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set name(String value) {
+    _bindings.spine_atlas_page_set_name(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  String get texturePath {
+    final result = _bindings.spine_atlas_page_get_texture_path(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set texturePath(String value) {
+    _bindings.spine_atlas_page_set_texture_path(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  Format get format {
+    final result = _bindings.spine_atlas_page_get_format(_ptr);
+    return Format.fromValue(result);
+  }
+
+  set format(Format value) {
+    _bindings.spine_atlas_page_set_format(_ptr, value.value);
+  }
+
+  TextureFilter get minFilter {
+    final result = _bindings.spine_atlas_page_get_min_filter(_ptr);
+    return TextureFilter.fromValue(result);
+  }
+
+  set minFilter(TextureFilter value) {
+    _bindings.spine_atlas_page_set_min_filter(_ptr, value.value);
+  }
+
+  TextureFilter get magFilter {
+    final result = _bindings.spine_atlas_page_get_mag_filter(_ptr);
+    return TextureFilter.fromValue(result);
+  }
+
+  set magFilter(TextureFilter value) {
+    _bindings.spine_atlas_page_set_mag_filter(_ptr, value.value);
+  }
+
+  TextureWrap get uWrap {
+    final result = _bindings.spine_atlas_page_get_u_wrap(_ptr);
+    return TextureWrap.fromValue(result);
+  }
+
+  set uWrap(TextureWrap value) {
+    _bindings.spine_atlas_page_set_u_wrap(_ptr, value.value);
+  }
+
+  TextureWrap get vWrap {
+    final result = _bindings.spine_atlas_page_get_v_wrap(_ptr);
+    return TextureWrap.fromValue(result);
+  }
+
+  set vWrap(TextureWrap value) {
+    _bindings.spine_atlas_page_set_v_wrap(_ptr, value.value);
+  }
+
+  int get width {
+    final result = _bindings.spine_atlas_page_get_width(_ptr);
+    return result;
+  }
+
+  set width(int value) {
+    _bindings.spine_atlas_page_set_width(_ptr, value);
+  }
+
+  int get height {
+    final result = _bindings.spine_atlas_page_get_height(_ptr);
+    return result;
+  }
+
+  set height(int value) {
+    _bindings.spine_atlas_page_set_height(_ptr, value);
+  }
+
+  bool get pma {
+    final result = _bindings.spine_atlas_page_get_pma(_ptr);
+    return result;
+  }
+
+  set pma(bool value) {
+    _bindings.spine_atlas_page_set_pma(_ptr, value);
+  }
+
+  int get index {
+    final result = _bindings.spine_atlas_page_get_index(_ptr);
+    return result;
+  }
+
+  set index(int value) {
+    _bindings.spine_atlas_page_set_index(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_atlas_page_dispose(_ptr);
+  }
+}

+ 265 - 0
spine-flutter/lib/generated/atlas_region.dart

@@ -0,0 +1,265 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'atlas_page.dart';
+import 'arrays.dart';
+
+/// AtlasRegion wrapper
+class AtlasRegion implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_atlas_region_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AtlasRegion.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AtlasRegion() {
+    final ptr = _bindings.spine_atlas_region_create();
+    return AtlasRegion.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_atlas_region_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  AtlasPage get page {
+    final result = _bindings.spine_atlas_region_get_page(_ptr);
+    return AtlasPage.fromPointer(result);
+  }
+
+  int get index {
+    final result = _bindings.spine_atlas_region_get_index(_ptr);
+    return result;
+  }
+
+  int get x {
+    final result = _bindings.spine_atlas_region_get_x(_ptr);
+    return result;
+  }
+
+  int get y {
+    final result = _bindings.spine_atlas_region_get_y(_ptr);
+    return result;
+  }
+
+  double get offsetX {
+    final result = _bindings.spine_atlas_region_get_offset_x(_ptr);
+    return result;
+  }
+
+  double get offsetY {
+    final result = _bindings.spine_atlas_region_get_offset_y(_ptr);
+    return result;
+  }
+
+  int get packedWidth {
+    final result = _bindings.spine_atlas_region_get_packed_width(_ptr);
+    return result;
+  }
+
+  int get packedHeight {
+    final result = _bindings.spine_atlas_region_get_packed_height(_ptr);
+    return result;
+  }
+
+  int get originalWidth {
+    final result = _bindings.spine_atlas_region_get_original_width(_ptr);
+    return result;
+  }
+
+  int get originalHeight {
+    final result = _bindings.spine_atlas_region_get_original_height(_ptr);
+    return result;
+  }
+
+  bool get rotate {
+    final result = _bindings.spine_atlas_region_get_rotate(_ptr);
+    return result;
+  }
+
+  int get degrees {
+    final result = _bindings.spine_atlas_region_get_degrees(_ptr);
+    return result;
+  }
+
+  ArrayInt get splits {
+    final result = _bindings.spine_atlas_region_get_splits(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  ArrayInt get pads {
+    final result = _bindings.spine_atlas_region_get_pads(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  ArrayFloat get values {
+    final result = _bindings.spine_atlas_region_get_values(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set page(AtlasPage value) {
+    _bindings.spine_atlas_region_set_page(_ptr, value.nativePtr.cast());
+  }
+
+  set name(String value) {
+    _bindings.spine_atlas_region_set_name(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  set index(int value) {
+    _bindings.spine_atlas_region_set_index(_ptr, value);
+  }
+
+  set x(int value) {
+    _bindings.spine_atlas_region_set_x(_ptr, value);
+  }
+
+  set y(int value) {
+    _bindings.spine_atlas_region_set_y(_ptr, value);
+  }
+
+  set offsetX(double value) {
+    _bindings.spine_atlas_region_set_offset_x(_ptr, value);
+  }
+
+  set offsetY(double value) {
+    _bindings.spine_atlas_region_set_offset_y(_ptr, value);
+  }
+
+  set packedWidth(int value) {
+    _bindings.spine_atlas_region_set_packed_width(_ptr, value);
+  }
+
+  set packedHeight(int value) {
+    _bindings.spine_atlas_region_set_packed_height(_ptr, value);
+  }
+
+  set originalWidth(int value) {
+    _bindings.spine_atlas_region_set_original_width(_ptr, value);
+  }
+
+  set originalHeight(int value) {
+    _bindings.spine_atlas_region_set_original_height(_ptr, value);
+  }
+
+  set rotate(bool value) {
+    _bindings.spine_atlas_region_set_rotate(_ptr, value);
+  }
+
+  set degrees(int value) {
+    _bindings.spine_atlas_region_set_degrees(_ptr, value);
+  }
+
+  set splits(ArrayInt value) {
+    _bindings.spine_atlas_region_set_splits(_ptr, value.nativePtr.cast());
+  }
+
+  set pads(ArrayInt value) {
+    _bindings.spine_atlas_region_set_pads(_ptr, value.nativePtr.cast());
+  }
+
+  set values(ArrayFloat value) {
+    _bindings.spine_atlas_region_set_values(_ptr, value.nativePtr.cast());
+  }
+
+  double get u {
+    final result = _bindings.spine_atlas_region_get_u(_ptr);
+    return result;
+  }
+
+  set u(double value) {
+    _bindings.spine_atlas_region_set_u(_ptr, value);
+  }
+
+  double get v {
+    final result = _bindings.spine_atlas_region_get_v(_ptr);
+    return result;
+  }
+
+  set v(double value) {
+    _bindings.spine_atlas_region_set_v(_ptr, value);
+  }
+
+  double get u2 {
+    final result = _bindings.spine_atlas_region_get_u2(_ptr);
+    return result;
+  }
+
+  set u2(double value) {
+    _bindings.spine_atlas_region_set_u2(_ptr, value);
+  }
+
+  double get v2 {
+    final result = _bindings.spine_atlas_region_get_v2(_ptr);
+    return result;
+  }
+
+  set v2(double value) {
+    _bindings.spine_atlas_region_set_v2(_ptr, value);
+  }
+
+  int get regionWidth {
+    final result = _bindings.spine_atlas_region_get_region_width(_ptr);
+    return result;
+  }
+
+  set regionWidth(int value) {
+    _bindings.spine_atlas_region_set_region_width(_ptr, value);
+  }
+
+  int get regionHeight {
+    final result = _bindings.spine_atlas_region_get_region_height(_ptr);
+    return result;
+  }
+
+  set regionHeight(int value) {
+    _bindings.spine_atlas_region_set_region_height(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_atlas_region_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_atlas_region_dispose(_ptr);
+  }
+}

+ 88 - 0
spine-flutter/lib/generated/attachment.dart

@@ -0,0 +1,88 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// Attachment wrapper
+class Attachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Attachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  String get name {
+    final result = _bindings.spine_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  int get refCount {
+    final result = _bindings.spine_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_attachment_dispose(_ptr);
+  }
+}

+ 92 - 0
spine-flutter/lib/generated/attachment_loader.dart

@@ -0,0 +1,92 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'region_attachment.dart';
+import 'skin.dart';
+import 'sequence.dart';
+import 'mesh_attachment.dart';
+import 'bounding_box_attachment.dart';
+import 'path_attachment.dart';
+import 'point_attachment.dart';
+import 'clipping_attachment.dart';
+
+/// AttachmentLoader wrapper
+class AttachmentLoader implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_attachment_loader_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AttachmentLoader.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  RegionAttachment newRegionAttachment(Skin skin, String name, String path, Sequence sequence) {
+    final result = _bindings.spine_attachment_loader_new_region_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>(), path.toNativeUtf8().cast<Char>(), sequence.nativePtr.cast());
+    return RegionAttachment.fromPointer(result);
+  }
+
+  MeshAttachment newMeshAttachment(Skin skin, String name, String path, Sequence sequence) {
+    final result = _bindings.spine_attachment_loader_new_mesh_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>(), path.toNativeUtf8().cast<Char>(), sequence.nativePtr.cast());
+    return MeshAttachment.fromPointer(result);
+  }
+
+  BoundingBoxAttachment newBoundingBoxAttachment(Skin skin, String name) {
+    final result = _bindings.spine_attachment_loader_new_bounding_box_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return BoundingBoxAttachment.fromPointer(result);
+  }
+
+  PathAttachment newPathAttachment(Skin skin, String name) {
+    final result = _bindings.spine_attachment_loader_new_path_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return PathAttachment.fromPointer(result);
+  }
+
+  PointAttachment newPointAttachment(Skin skin, String name) {
+    final result = _bindings.spine_attachment_loader_new_point_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return PointAttachment.fromPointer(result);
+  }
+
+  ClippingAttachment newClippingAttachment(Skin skin, String name) {
+    final result = _bindings.spine_attachment_loader_new_clipping_attachment(_ptr, skin.nativePtr.cast(), name.toNativeUtf8().cast<Char>());
+    return ClippingAttachment.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_attachment_loader_dispose(_ptr);
+  }
+}

+ 116 - 0
spine-flutter/lib/generated/attachment_timeline.dart

@@ -0,0 +1,116 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// AttachmentTimeline wrapper
+class AttachmentTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_attachment_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  AttachmentTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory AttachmentTimeline(int frameCount, int slotIndex) {
+    final ptr = _bindings.spine_attachment_timeline_create(frameCount, slotIndex);
+    return AttachmentTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_attachment_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_attachment_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, String attachmentName) {
+    _bindings.spine_attachment_timeline_set_frame(_ptr, frame, time, attachmentName.toNativeUtf8().cast<Char>());
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_attachment_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_attachment_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_attachment_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_attachment_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_attachment_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get slotIndex {
+    final result = _bindings.spine_attachment_timeline_get_slot_index(_ptr);
+    return result;
+  }
+
+  set slotIndex(int value) {
+    _bindings.spine_attachment_timeline_set_slot_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_attachment_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_attachment_timeline_dispose(_ptr);
+  }
+}

+ 51 - 0
spine-flutter/lib/generated/attachment_type.dart

@@ -0,0 +1,51 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// AttachmentType enum
+enum AttachmentType {
+  region(0),
+  boundingbox(1),
+  mesh(2),
+  linkedmesh(3),
+  path(4),
+  point(5),
+  clipping(6);
+
+  const AttachmentType(this.value);
+  final int value;
+
+  static AttachmentType fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid AttachmentType value: $value'),
+    );
+  }
+}

+ 48 - 0
spine-flutter/lib/generated/blend_mode.dart

@@ -0,0 +1,48 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// BlendMode enum
+enum BlendMode {
+  normal(0),
+  additive(1),
+  multiply(2),
+  screen(3);
+
+  const BlendMode(this.value);
+  final int value;
+
+  static BlendMode fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid BlendMode value: $value'),
+    );
+  }
+}

+ 140 - 0
spine-flutter/lib/generated/bone.dart

@@ -0,0 +1,140 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'physics.dart';
+import 'bone_data.dart';
+import 'bone_local.dart';
+import 'bone_pose.dart';
+import 'arrays.dart';
+
+/// Bone wrapper
+class Bone implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Bone.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory Bone(BoneData data, Bone parent) {
+    final ptr = _bindings.spine_bone_create(data.nativePtr.cast(), parent.nativePtr.cast());
+    return Bone.fromPointer(ptr);
+  }
+
+  factory Bone.from(Bone bone, Bone parent) {
+    final ptr = _bindings.spine_bone_create2(bone.nativePtr.cast(), parent.nativePtr.cast());
+    return Bone.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_bone_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  Bone get parent {
+    final result = _bindings.spine_bone_get_parent(_ptr);
+    return Bone.fromPointer(result);
+  }
+
+  ArrayBone get children {
+    final result = _bindings.spine_bone_get_children(_ptr);
+    return ArrayBone.fromPointer(result);
+  }
+
+  static bool isYDown() {
+    final result = _bindings.spine_bone_is_y_down();
+    return result;
+  }
+
+  static void setYDown(bool value) {
+    _bindings.spine_bone_set_y_down(value);
+  }
+
+  void update(Skeleton skeleton, Physics physics) {
+    _bindings.spine_bone_update(_ptr, skeleton.nativePtr.cast(), physics.value);
+  }
+
+  BoneData get data {
+    final result = _bindings.spine_bone_get_data(_ptr);
+    return BoneData.fromPointer(result);
+  }
+
+  BoneLocal get pose {
+    final result = _bindings.spine_bone_get_pose(_ptr);
+    return BoneLocal.fromPointer(result);
+  }
+
+  BonePose get appliedPose {
+    final result = _bindings.spine_bone_get_applied_pose(_ptr);
+    return BonePose.fromPointer(result);
+  }
+
+  void resetConstrained() {
+    _bindings.spine_bone_reset_constrained(_ptr);
+  }
+
+  void constrained() {
+    _bindings.spine_bone_constrained(_ptr);
+  }
+
+  bool get isPoseEqualToApplied {
+    final result = _bindings.spine_bone_is_pose_equal_to_applied(_ptr);
+    return result;
+  }
+
+  bool get isActive {
+    final result = _bindings.spine_bone_is_active(_ptr);
+    return result;
+  }
+
+  set active(bool value) {
+    _bindings.spine_bone_set_active(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_bone_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_bone_dispose(_ptr);
+  }
+}

+ 122 - 0
spine-flutter/lib/generated/bone_data.dart

@@ -0,0 +1,122 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'color.dart';
+import 'bone_local.dart';
+
+/// BoneData wrapper
+class BoneData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BoneData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory BoneData(int index, String name, BoneData parent) {
+    final ptr = _bindings.spine_bone_data_create(index, name.toNativeUtf8().cast<Char>(), parent.nativePtr.cast());
+    return BoneData.fromPointer(ptr);
+  }
+
+  int get index {
+    final result = _bindings.spine_bone_data_get_index(_ptr);
+    return result;
+  }
+
+  BoneData get parent {
+    final result = _bindings.spine_bone_data_get_parent(_ptr);
+    return BoneData.fromPointer(result);
+  }
+
+  double get length {
+    final result = _bindings.spine_bone_data_get_length(_ptr);
+    return result;
+  }
+
+  set length(double value) {
+    _bindings.spine_bone_data_set_length(_ptr, value);
+  }
+
+  Color get color {
+    final result = _bindings.spine_bone_data_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  String get icon {
+    final result = _bindings.spine_bone_data_get_icon(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set icon(String value) {
+    _bindings.spine_bone_data_set_icon(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  bool get visible {
+    final result = _bindings.spine_bone_data_get_visible(_ptr);
+    return result;
+  }
+
+  set visible(bool value) {
+    _bindings.spine_bone_data_set_visible(_ptr, value);
+  }
+
+  BoneLocal get setupPose {
+    final result = _bindings.spine_bone_data_get_setup_pose(_ptr);
+    return BoneLocal.fromPointer(result);
+  }
+
+  String get name {
+    final result = _bindings.spine_bone_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  bool get skinRequired {
+    final result = _bindings.spine_bone_data_get_skin_required(_ptr);
+    return result;
+  }
+
+  set skinRequired(bool value) {
+    _bindings.spine_bone_data_set_skin_required(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_bone_data_dispose(_ptr);
+  }
+}

+ 147 - 0
spine-flutter/lib/generated/bone_local.dart

@@ -0,0 +1,147 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'inherit.dart';
+
+/// BoneLocal wrapper
+class BoneLocal implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_local_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BoneLocal.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory BoneLocal() {
+    final ptr = _bindings.spine_bone_local_create();
+    return BoneLocal.fromPointer(ptr);
+  }
+
+  void set(BoneLocal pose) {
+    _bindings.spine_bone_local_set(_ptr, pose.nativePtr.cast());
+  }
+
+  double get x {
+    final result = _bindings.spine_bone_local_get_x(_ptr);
+    return result;
+  }
+
+  set x(double value) {
+    _bindings.spine_bone_local_set_x(_ptr, value);
+  }
+
+  double get y {
+    final result = _bindings.spine_bone_local_get_y(_ptr);
+    return result;
+  }
+
+  set y(double value) {
+    _bindings.spine_bone_local_set_y(_ptr, value);
+  }
+
+  void setPosition(double x, double y) {
+    _bindings.spine_bone_local_set_position(_ptr, x, y);
+  }
+
+  double get rotation {
+    final result = _bindings.spine_bone_local_get_rotation(_ptr);
+    return result;
+  }
+
+  set rotation(double value) {
+    _bindings.spine_bone_local_set_rotation(_ptr, value);
+  }
+
+  double get scaleX {
+    final result = _bindings.spine_bone_local_get_scale_x(_ptr);
+    return result;
+  }
+
+  set scaleX(double value) {
+    _bindings.spine_bone_local_set_scale_x(_ptr, value);
+  }
+
+  double get scaleY {
+    final result = _bindings.spine_bone_local_get_scale_y(_ptr);
+    return result;
+  }
+
+  set scaleY(double value) {
+    _bindings.spine_bone_local_set_scale_y(_ptr, value);
+  }
+
+  double get shearX {
+    final result = _bindings.spine_bone_local_get_shear_x(_ptr);
+    return result;
+  }
+
+  set shearX(double value) {
+    _bindings.spine_bone_local_set_shear_x(_ptr, value);
+  }
+
+  double get shearY {
+    final result = _bindings.spine_bone_local_get_shear_y(_ptr);
+    return result;
+  }
+
+  set shearY(double value) {
+    _bindings.spine_bone_local_set_shear_y(_ptr, value);
+  }
+
+  Inherit get inherit {
+    final result = _bindings.spine_bone_local_get_inherit(_ptr);
+    return Inherit.fromValue(result);
+  }
+
+  set inherit(Inherit value) {
+    _bindings.spine_bone_local_set_inherit(_ptr, value.value);
+  }
+
+  void setScale1(double scaleX, double scaleY) {
+    _bindings.spine_bone_local_set_scale_1(_ptr, scaleX, scaleY);
+  }
+
+  set scale2(double value) {
+    _bindings.spine_bone_local_set_scale_2(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_bone_local_dispose(_ptr);
+  }
+}

+ 277 - 0
spine-flutter/lib/generated/bone_pose.dart

@@ -0,0 +1,277 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'physics.dart';
+import 'bone_local.dart';
+import 'inherit.dart';
+
+/// BonePose wrapper
+class BonePose implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_pose_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BonePose.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory BonePose() {
+    final ptr = _bindings.spine_bone_pose_create();
+    return BonePose.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_bone_pose_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void update(Skeleton skeleton, Physics physics) {
+    _bindings.spine_bone_pose_update(_ptr, skeleton.nativePtr.cast(), physics.value);
+  }
+
+  void updateWorldTransform(Skeleton skeleton) {
+    _bindings.spine_bone_pose_update_world_transform(_ptr, skeleton.nativePtr.cast());
+  }
+
+  void updateLocalTransform(Skeleton skeleton) {
+    _bindings.spine_bone_pose_update_local_transform(_ptr, skeleton.nativePtr.cast());
+  }
+
+  void validateLocalTransform(Skeleton skeleton) {
+    _bindings.spine_bone_pose_validate_local_transform(_ptr, skeleton.nativePtr.cast());
+  }
+
+  void modifyLocal(Skeleton skeleton) {
+    _bindings.spine_bone_pose_modify_local(_ptr, skeleton.nativePtr.cast());
+  }
+
+  void modifyWorld(int update) {
+    _bindings.spine_bone_pose_modify_world(_ptr, update);
+  }
+
+  void resetWorld(int update) {
+    _bindings.spine_bone_pose_reset_world(_ptr, update);
+  }
+
+  double get a {
+    final result = _bindings.spine_bone_pose_get_a(_ptr);
+    return result;
+  }
+
+  set a(double value) {
+    _bindings.spine_bone_pose_set_a(_ptr, value);
+  }
+
+  double get b {
+    final result = _bindings.spine_bone_pose_get_b(_ptr);
+    return result;
+  }
+
+  set b(double value) {
+    _bindings.spine_bone_pose_set_b(_ptr, value);
+  }
+
+  double get c {
+    final result = _bindings.spine_bone_pose_get_c(_ptr);
+    return result;
+  }
+
+  set c(double value) {
+    _bindings.spine_bone_pose_set_c(_ptr, value);
+  }
+
+  double get d {
+    final result = _bindings.spine_bone_pose_get_d(_ptr);
+    return result;
+  }
+
+  set d(double value) {
+    _bindings.spine_bone_pose_set_d(_ptr, value);
+  }
+
+  double get worldX {
+    final result = _bindings.spine_bone_pose_get_world_x(_ptr);
+    return result;
+  }
+
+  set worldX(double value) {
+    _bindings.spine_bone_pose_set_world_x(_ptr, value);
+  }
+
+  double get worldY {
+    final result = _bindings.spine_bone_pose_get_world_y(_ptr);
+    return result;
+  }
+
+  set worldY(double value) {
+    _bindings.spine_bone_pose_set_world_y(_ptr, value);
+  }
+
+  double get worldRotationX {
+    final result = _bindings.spine_bone_pose_get_world_rotation_x(_ptr);
+    return result;
+  }
+
+  double get worldRotationY {
+    final result = _bindings.spine_bone_pose_get_world_rotation_y(_ptr);
+    return result;
+  }
+
+  double get worldScaleX {
+    final result = _bindings.spine_bone_pose_get_world_scale_x(_ptr);
+    return result;
+  }
+
+  double get worldScaleY {
+    final result = _bindings.spine_bone_pose_get_world_scale_y(_ptr);
+    return result;
+  }
+
+  double worldToLocalRotation(double worldRotation) {
+    final result = _bindings.spine_bone_pose_world_to_local_rotation(_ptr, worldRotation);
+    return result;
+  }
+
+  double localToWorldRotation(double localRotation) {
+    final result = _bindings.spine_bone_pose_local_to_world_rotation(_ptr, localRotation);
+    return result;
+  }
+
+  void rotateWorld(double degrees) {
+    _bindings.spine_bone_pose_rotate_world(_ptr, degrees);
+  }
+
+  void set(BoneLocal pose) {
+    _bindings.spine_bone_pose_set(_ptr, pose.nativePtr.cast());
+  }
+
+  double get x {
+    final result = _bindings.spine_bone_pose_get_x(_ptr);
+    return result;
+  }
+
+  set x(double value) {
+    _bindings.spine_bone_pose_set_x(_ptr, value);
+  }
+
+  double get y {
+    final result = _bindings.spine_bone_pose_get_y(_ptr);
+    return result;
+  }
+
+  set y(double value) {
+    _bindings.spine_bone_pose_set_y(_ptr, value);
+  }
+
+  void setPosition(double x, double y) {
+    _bindings.spine_bone_pose_set_position(_ptr, x, y);
+  }
+
+  double get rotation {
+    final result = _bindings.spine_bone_pose_get_rotation(_ptr);
+    return result;
+  }
+
+  set rotation(double value) {
+    _bindings.spine_bone_pose_set_rotation(_ptr, value);
+  }
+
+  double get scaleX {
+    final result = _bindings.spine_bone_pose_get_scale_x(_ptr);
+    return result;
+  }
+
+  set scaleX(double value) {
+    _bindings.spine_bone_pose_set_scale_x(_ptr, value);
+  }
+
+  double get scaleY {
+    final result = _bindings.spine_bone_pose_get_scale_y(_ptr);
+    return result;
+  }
+
+  set scaleY(double value) {
+    _bindings.spine_bone_pose_set_scale_y(_ptr, value);
+  }
+
+  double get shearX {
+    final result = _bindings.spine_bone_pose_get_shear_x(_ptr);
+    return result;
+  }
+
+  set shearX(double value) {
+    _bindings.spine_bone_pose_set_shear_x(_ptr, value);
+  }
+
+  double get shearY {
+    final result = _bindings.spine_bone_pose_get_shear_y(_ptr);
+    return result;
+  }
+
+  set shearY(double value) {
+    _bindings.spine_bone_pose_set_shear_y(_ptr, value);
+  }
+
+  Inherit get inherit {
+    final result = _bindings.spine_bone_pose_get_inherit(_ptr);
+    return Inherit.fromValue(result);
+  }
+
+  set inherit(Inherit value) {
+    _bindings.spine_bone_pose_set_inherit(_ptr, value.value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_bone_pose_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void setScale1(double scaleX, double scaleY) {
+    _bindings.spine_bone_pose_set_scale_1(_ptr, scaleX, scaleY);
+  }
+
+  set scale2(double value) {
+    _bindings.spine_bone_pose_set_scale_2(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_bone_pose_dispose(_ptr);
+  }
+}

+ 73 - 0
spine-flutter/lib/generated/bone_timeline.dart

@@ -0,0 +1,73 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// BoneTimeline wrapper
+class BoneTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BoneTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_bone_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  int get boneIndex {
+    final result = _bindings.spine_bone_timeline_get_bone_index(_ptr);
+    return result;
+  }
+
+  set boneIndex(int value) {
+    _bindings.spine_bone_timeline_set_bone_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_bone_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_bone_timeline_dispose(_ptr);
+  }
+}

+ 157 - 0
spine-flutter/lib/generated/bone_timeline1.dart

@@ -0,0 +1,157 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// BoneTimeline1 wrapper
+class BoneTimeline1 implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_timeline1_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BoneTimeline1.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_bone_timeline1_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_bone_timeline1_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_bone_timeline1_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_bone_timeline1_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_bone_timeline1_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_bone_timeline1_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_bone_timeline1_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_bone_timeline1_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_bone_timeline1_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_bone_timeline1_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_bone_timeline1_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_bone_timeline1_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_bone_timeline1_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_bone_timeline1_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_bone_timeline1_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_bone_timeline1_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get boneIndex {
+    final result = _bindings.spine_bone_timeline1_get_bone_index(_ptr);
+    return result;
+  }
+
+  set boneIndex(int value) {
+    _bindings.spine_bone_timeline1_set_bone_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_bone_timeline1_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_bone_timeline1_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_bone_timeline1_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_bone_timeline1_dispose(_ptr);
+  }
+}

+ 137 - 0
spine-flutter/lib/generated/bone_timeline2.dart

@@ -0,0 +1,137 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// BoneTimeline2 wrapper
+class BoneTimeline2 implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bone_timeline2_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BoneTimeline2.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_bone_timeline2_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_bone_timeline2_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value1, double value2) {
+    _bindings.spine_bone_timeline2_set_frame(_ptr, frame, time, value1, value2);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_bone_timeline2_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_bone_timeline2_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_bone_timeline2_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_bone_timeline2_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_bone_timeline2_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_bone_timeline2_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_bone_timeline2_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_bone_timeline2_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_bone_timeline2_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_bone_timeline2_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_bone_timeline2_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get boneIndex {
+    final result = _bindings.spine_bone_timeline2_get_bone_index(_ptr);
+    return result;
+  }
+
+  set boneIndex(int value) {
+    _bindings.spine_bone_timeline2_set_bone_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_bone_timeline2_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_bone_timeline2_dispose(_ptr);
+  }
+}

+ 153 - 0
spine-flutter/lib/generated/bounding_box_attachment.dart

@@ -0,0 +1,153 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'color.dart';
+import 'attachment.dart';
+import 'skeleton.dart';
+import 'slot.dart';
+import 'vertex_attachment.dart';
+import 'arrays.dart';
+
+/// BoundingBoxAttachment wrapper
+class BoundingBoxAttachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_bounding_box_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  BoundingBoxAttachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory BoundingBoxAttachment(String name) {
+    final ptr = _bindings.spine_bounding_box_attachment_create(name.toNativeUtf8().cast<Char>());
+    return BoundingBoxAttachment.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_bounding_box_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  Color get color {
+    final result = _bindings.spine_bounding_box_attachment_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_bounding_box_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  int get id {
+    final result = _bindings.spine_bounding_box_attachment_get_id(_ptr);
+    return result;
+  }
+
+  ArrayInt get bones {
+    final result = _bindings.spine_bounding_box_attachment_get_bones(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  set bones(ArrayInt value) {
+    _bindings.spine_bounding_box_attachment_set_bones(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayFloat get vertices {
+    final result = _bindings.spine_bounding_box_attachment_get_vertices(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set vertices(ArrayFloat value) {
+    _bindings.spine_bounding_box_attachment_set_vertices(_ptr, value.nativePtr.cast());
+  }
+
+  int get worldVerticesLength {
+    final result = _bindings.spine_bounding_box_attachment_get_world_vertices_length(_ptr);
+    return result;
+  }
+
+  set worldVerticesLength(int value) {
+    _bindings.spine_bounding_box_attachment_set_world_vertices_length(_ptr, value);
+  }
+
+  Attachment get timelineAttachment {
+    final result = _bindings.spine_bounding_box_attachment_get_timeline_attachment(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  set timelineAttachment(Attachment value) {
+    _bindings.spine_bounding_box_attachment_set_timeline_attachment(_ptr, value.nativePtr.cast());
+  }
+
+  void copyTo(VertexAttachment other) {
+    _bindings.spine_bounding_box_attachment_copy_to(_ptr, other.nativePtr.cast());
+  }
+
+  String get name {
+    final result = _bindings.spine_bounding_box_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get refCount {
+    final result = _bindings.spine_bounding_box_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_bounding_box_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_bounding_box_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_bounding_box_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void computeWorldVertices(Skeleton skeleton, Slot slot, int start, int count, ArrayFloat worldVertices, int offset, int stride) {
+    _bindings.spine_bounding_box_attachment_compute_world_vertices_2(_ptr, skeleton.nativePtr.cast(), slot.nativePtr.cast(), start, count, worldVertices.nativePtr.cast(), offset, stride);
+  }
+
+  void dispose() {
+    _bindings.spine_bounding_box_attachment_dispose(_ptr);
+  }
+}

+ 163 - 0
spine-flutter/lib/generated/clipping_attachment.dart

@@ -0,0 +1,163 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'slot_data.dart';
+import 'color.dart';
+import 'attachment.dart';
+import 'skeleton.dart';
+import 'slot.dart';
+import 'vertex_attachment.dart';
+import 'arrays.dart';
+
+/// ClippingAttachment wrapper
+class ClippingAttachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_clipping_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ClippingAttachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory ClippingAttachment(String name) {
+    final ptr = _bindings.spine_clipping_attachment_create(name.toNativeUtf8().cast<Char>());
+    return ClippingAttachment.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_clipping_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  SlotData get endSlot {
+    final result = _bindings.spine_clipping_attachment_get_end_slot(_ptr);
+    return SlotData.fromPointer(result);
+  }
+
+  set endSlot(SlotData value) {
+    _bindings.spine_clipping_attachment_set_end_slot(_ptr, value.nativePtr.cast());
+  }
+
+  Color get color {
+    final result = _bindings.spine_clipping_attachment_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_clipping_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  int get id {
+    final result = _bindings.spine_clipping_attachment_get_id(_ptr);
+    return result;
+  }
+
+  ArrayInt get bones {
+    final result = _bindings.spine_clipping_attachment_get_bones(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  set bones(ArrayInt value) {
+    _bindings.spine_clipping_attachment_set_bones(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayFloat get vertices {
+    final result = _bindings.spine_clipping_attachment_get_vertices(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set vertices(ArrayFloat value) {
+    _bindings.spine_clipping_attachment_set_vertices(_ptr, value.nativePtr.cast());
+  }
+
+  int get worldVerticesLength {
+    final result = _bindings.spine_clipping_attachment_get_world_vertices_length(_ptr);
+    return result;
+  }
+
+  set worldVerticesLength(int value) {
+    _bindings.spine_clipping_attachment_set_world_vertices_length(_ptr, value);
+  }
+
+  Attachment get timelineAttachment {
+    final result = _bindings.spine_clipping_attachment_get_timeline_attachment(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  set timelineAttachment(Attachment value) {
+    _bindings.spine_clipping_attachment_set_timeline_attachment(_ptr, value.nativePtr.cast());
+  }
+
+  void copyTo(VertexAttachment other) {
+    _bindings.spine_clipping_attachment_copy_to(_ptr, other.nativePtr.cast());
+  }
+
+  String get name {
+    final result = _bindings.spine_clipping_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get refCount {
+    final result = _bindings.spine_clipping_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_clipping_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_clipping_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_clipping_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void computeWorldVertices(Skeleton skeleton, Slot slot, int start, int count, ArrayFloat worldVertices, int offset, int stride) {
+    _bindings.spine_clipping_attachment_compute_world_vertices_2(_ptr, skeleton.nativePtr.cast(), slot.nativePtr.cast(), start, count, worldVertices.nativePtr.cast(), offset, stride);
+  }
+
+  void dispose() {
+    _bindings.spine_clipping_attachment_dispose(_ptr);
+  }
+}

+ 148 - 0
spine-flutter/lib/generated/color.dart

@@ -0,0 +1,148 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+
+/// Color wrapper
+class Color implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_color_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Color.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory Color() {
+    final ptr = _bindings.spine_color_create();
+    return Color.fromPointer(ptr);
+  }
+
+  factory Color.fromRGBA(double r, double g, double b, double a) {
+    final ptr = _bindings.spine_color_create2(r, g, b, a);
+    return Color.fromPointer(ptr);
+  }
+
+  Color clamp() {
+    final result = _bindings.spine_color_clamp(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  static double parseHex(String value, int index) {
+    final result = _bindings.spine_color_parse_hex(value.toNativeUtf8().cast<Char>(), index);
+    return result;
+  }
+
+  void rgba8888ToColor(int value) {
+    _bindings.spine_color_rgba8888_to_color(_ptr, value);
+  }
+
+  void rgb888ToColor(int value) {
+    _bindings.spine_color_rgb888_to_color(_ptr, value);
+  }
+
+  double get r {
+    final result = _bindings.spine_color_get_r(_ptr);
+    return result;
+  }
+
+  set r(double value) {
+    _bindings.spine_color_set_r(_ptr, value);
+  }
+
+  double get g {
+    final result = _bindings.spine_color_get_g(_ptr);
+    return result;
+  }
+
+  set g(double value) {
+    _bindings.spine_color_set_g(_ptr, value);
+  }
+
+  double get b {
+    final result = _bindings.spine_color_get_b(_ptr);
+    return result;
+  }
+
+  set b(double value) {
+    _bindings.spine_color_set_b(_ptr, value);
+  }
+
+  double get a {
+    final result = _bindings.spine_color_get_a(_ptr);
+    return result;
+  }
+
+  set a(double value) {
+    _bindings.spine_color_set_a(_ptr, value);
+  }
+
+  Color set1(double _r, double _g, double _b, double _a) {
+    final result = _bindings.spine_color_set_1(_ptr, _r, _g, _b, _a);
+    return Color.fromPointer(result);
+  }
+
+  Color set2(double _r, double _g, double _b) {
+    final result = _bindings.spine_color_set_2(_ptr, _r, _g, _b);
+    return Color.fromPointer(result);
+  }
+
+  Color set3(Color other) {
+    final result = _bindings.spine_color_set_3(_ptr, other.nativePtr.cast());
+    return Color.fromPointer(result);
+  }
+
+  Color add1(double _r, double _g, double _b, double _a) {
+    final result = _bindings.spine_color_add_1(_ptr, _r, _g, _b, _a);
+    return Color.fromPointer(result);
+  }
+
+  Color add2(double _r, double _g, double _b) {
+    final result = _bindings.spine_color_add_2(_ptr, _r, _g, _b);
+    return Color.fromPointer(result);
+  }
+
+  Color add3(Color other) {
+    final result = _bindings.spine_color_add_3(_ptr, other.nativePtr.cast());
+    return Color.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_color_dispose(_ptr);
+  }
+}

+ 85 - 0
spine-flutter/lib/generated/constraint.dart

@@ -0,0 +1,85 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'constraint_data.dart';
+import 'skeleton.dart';
+import 'physics.dart';
+
+/// Constraint wrapper
+class Constraint implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_constraint_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Constraint.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_constraint_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  ConstraintData get data {
+    final result = _bindings.spine_constraint_get_data(_ptr);
+    return ConstraintData.fromPointer(result);
+  }
+
+  void sort(Skeleton skeleton) {
+    _bindings.spine_constraint_sort(_ptr, skeleton.nativePtr.cast());
+  }
+
+  bool get isSourceActive {
+    final result = _bindings.spine_constraint_is_source_active(_ptr);
+    return result;
+  }
+
+  void update(Skeleton skeleton, Physics physics) {
+    _bindings.spine_constraint_update(_ptr, skeleton.nativePtr.cast(), physics.value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_constraint_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_constraint_dispose(_ptr);
+  }
+}

+ 82 - 0
spine-flutter/lib/generated/constraint_data.dart

@@ -0,0 +1,82 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'constraint.dart';
+import 'skeleton.dart';
+
+/// ConstraintData wrapper
+class ConstraintData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_constraint_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ConstraintData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_constraint_data_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  Constraint createMethod(Skeleton skeleton) {
+    final result = _bindings.spine_constraint_data_create_method(_ptr, skeleton.nativePtr.cast());
+    return Constraint.fromPointer(result);
+  }
+
+  String get name {
+    final result = _bindings.spine_constraint_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  bool get skinRequired {
+    final result = _bindings.spine_constraint_data_get_skin_required(_ptr);
+    return result;
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_constraint_data_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_constraint_data_dispose(_ptr);
+  }
+}

+ 73 - 0
spine-flutter/lib/generated/constraint_timeline.dart

@@ -0,0 +1,73 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// ConstraintTimeline wrapper
+class ConstraintTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_constraint_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ConstraintTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_constraint_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_constraint_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_constraint_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_constraint_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_constraint_timeline_dispose(_ptr);
+  }
+}

+ 157 - 0
spine-flutter/lib/generated/constraint_timeline1.dart

@@ -0,0 +1,157 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'skeleton.dart';
+import 'arrays.dart';
+
+/// ConstraintTimeline1 wrapper
+class ConstraintTimeline1 implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_constraint_timeline1_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  ConstraintTimeline1.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_constraint_timeline1_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_constraint_timeline1_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_constraint_timeline1_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_constraint_timeline1_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_constraint_timeline1_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_constraint_timeline1_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_constraint_timeline1_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_constraint_timeline1_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_constraint_timeline1_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_constraint_timeline1_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_constraint_timeline1_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_constraint_timeline1_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_constraint_timeline1_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_constraint_timeline1_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_constraint_timeline1_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_constraint_timeline1_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_constraint_timeline1_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_constraint_timeline1_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_constraint_timeline1_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_constraint_timeline1_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_constraint_timeline1_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_constraint_timeline1_dispose(_ptr);
+  }
+}

+ 119 - 0
spine-flutter/lib/generated/curve_timeline.dart

@@ -0,0 +1,119 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// CurveTimeline wrapper
+class CurveTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_curve_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  CurveTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_curve_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  set linear(int value) {
+    _bindings.spine_curve_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_curve_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_curve_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_curve_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_curve_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_curve_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_curve_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_curve_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_curve_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_curve_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_curve_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_curve_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_curve_timeline_dispose(_ptr);
+  }
+}

+ 148 - 0
spine-flutter/lib/generated/curve_timeline1.dart

@@ -0,0 +1,148 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'skeleton.dart';
+import 'arrays.dart';
+
+/// CurveTimeline1 wrapper
+class CurveTimeline1 implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_curve_timeline1_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  CurveTimeline1.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_curve_timeline1_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_curve_timeline1_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_curve_timeline1_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_curve_timeline1_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_curve_timeline1_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_curve_timeline1_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_curve_timeline1_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_curve_timeline1_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_curve_timeline1_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_curve_timeline1_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_curve_timeline1_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_curve_timeline1_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_curve_timeline1_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_curve_timeline1_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_curve_timeline1_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_curve_timeline1_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_curve_timeline1_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_curve_timeline1_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_curve_timeline1_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_curve_timeline1_dispose(_ptr);
+  }
+}

+ 128 - 0
spine-flutter/lib/generated/curve_timeline2.dart

@@ -0,0 +1,128 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// CurveTimeline2 wrapper
+class CurveTimeline2 implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_curve_timeline2_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  CurveTimeline2.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_curve_timeline2_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void setFrame(int frame, double time, double value1, double value2) {
+    _bindings.spine_curve_timeline2_set_frame(_ptr, frame, time, value1, value2);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_curve_timeline2_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_curve_timeline2_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_curve_timeline2_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_curve_timeline2_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_curve_timeline2_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_curve_timeline2_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_curve_timeline2_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_curve_timeline2_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_curve_timeline2_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_curve_timeline2_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_curve_timeline2_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_curve_timeline2_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_curve_timeline2_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_curve_timeline2_dispose(_ptr);
+  }
+}

+ 152 - 0
spine-flutter/lib/generated/deform_timeline.dart

@@ -0,0 +1,152 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'vertex_attachment.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// DeformTimeline wrapper
+class DeformTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_deform_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  DeformTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory DeformTimeline(int frameCount, int bezierCount, int slotIndex, VertexAttachment attachment) {
+    final ptr = _bindings.spine_deform_timeline_create(frameCount, bezierCount, slotIndex, attachment.nativePtr.cast());
+    return DeformTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_deform_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void setFrame(int frameIndex, double time, ArrayFloat vertices) {
+    _bindings.spine_deform_timeline_set_frame(_ptr, frameIndex, time, vertices.nativePtr.cast());
+  }
+
+  VertexAttachment get attachment {
+    final result = _bindings.spine_deform_timeline_get_attachment(_ptr);
+    return VertexAttachment.fromPointer(result);
+  }
+
+  set attachment(VertexAttachment value) {
+    _bindings.spine_deform_timeline_set_attachment(_ptr, value.nativePtr.cast());
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_deform_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getCurvePercent(double time, int frame) {
+    final result = _bindings.spine_deform_timeline_get_curve_percent(_ptr, time, frame);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_deform_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_deform_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  set linear(int value) {
+    _bindings.spine_deform_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_deform_timeline_set_stepped(_ptr, value);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_deform_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_deform_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_deform_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_deform_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_deform_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_deform_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get slotIndex {
+    final result = _bindings.spine_deform_timeline_get_slot_index(_ptr);
+    return result;
+  }
+
+  set slotIndex(int value) {
+    _bindings.spine_deform_timeline_set_slot_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_deform_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_deform_timeline_dispose(_ptr);
+  }
+}

+ 106 - 0
spine-flutter/lib/generated/draw_order_timeline.dart

@@ -0,0 +1,106 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// DrawOrderTimeline wrapper
+class DrawOrderTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_draw_order_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  DrawOrderTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory DrawOrderTimeline(int frameCount) {
+    final ptr = _bindings.spine_draw_order_timeline_create(frameCount);
+    return DrawOrderTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_draw_order_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_draw_order_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_draw_order_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  void setFrame(int frame, double time, ArrayInt drawOrder) {
+    _bindings.spine_draw_order_timeline_set_frame(_ptr, frame, time, drawOrder.nativePtr.cast());
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_draw_order_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_draw_order_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_draw_order_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_draw_order_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_draw_order_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_draw_order_timeline_dispose(_ptr);
+  }
+}

+ 115 - 0
spine-flutter/lib/generated/event.dart

@@ -0,0 +1,115 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'event_data.dart';
+
+/// Event wrapper
+class Event implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_event_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Event.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory Event(double time, EventData data) {
+    final ptr = _bindings.spine_event_create(time, data.nativePtr.cast());
+    return Event.fromPointer(ptr);
+  }
+
+  EventData get data {
+    final result = _bindings.spine_event_get_data(_ptr);
+    return EventData.fromPointer(result);
+  }
+
+  double get time {
+    final result = _bindings.spine_event_get_time(_ptr);
+    return result;
+  }
+
+  int get intValue {
+    final result = _bindings.spine_event_get_int(_ptr);
+    return result;
+  }
+
+  set intValue(int value) {
+    _bindings.spine_event_set_int(_ptr, value);
+  }
+
+  double get floatValue {
+    final result = _bindings.spine_event_get_float(_ptr);
+    return result;
+  }
+
+  set floatValue(double value) {
+    _bindings.spine_event_set_float(_ptr, value);
+  }
+
+  String get stringValue {
+    final result = _bindings.spine_event_get_string(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set stringValue(String value) {
+    _bindings.spine_event_set_string(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  double get volume {
+    final result = _bindings.spine_event_get_volume(_ptr);
+    return result;
+  }
+
+  set volume(double value) {
+    _bindings.spine_event_set_volume(_ptr, value);
+  }
+
+  double get balance {
+    final result = _bindings.spine_event_get_balance(_ptr);
+    return result;
+  }
+
+  set balance(double value) {
+    _bindings.spine_event_set_balance(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_event_dispose(_ptr);
+  }
+}

+ 118 - 0
spine-flutter/lib/generated/event_data.dart

@@ -0,0 +1,118 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+
+/// EventData wrapper
+class EventData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_event_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  EventData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory EventData(String name) {
+    final ptr = _bindings.spine_event_data_create(name.toNativeUtf8().cast<Char>());
+    return EventData.fromPointer(ptr);
+  }
+
+  String get name {
+    final result = _bindings.spine_event_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get intValue {
+    final result = _bindings.spine_event_data_get_int(_ptr);
+    return result;
+  }
+
+  set intValue(int value) {
+    _bindings.spine_event_data_set_int(_ptr, value);
+  }
+
+  double get floatValue {
+    final result = _bindings.spine_event_data_get_float(_ptr);
+    return result;
+  }
+
+  set floatValue(double value) {
+    _bindings.spine_event_data_set_float(_ptr, value);
+  }
+
+  String get stringValue {
+    final result = _bindings.spine_event_data_get_string(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set stringValue(String value) {
+    _bindings.spine_event_data_set_string(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  String get audioPath {
+    final result = _bindings.spine_event_data_get_audio_path(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set audioPath(String value) {
+    _bindings.spine_event_data_set_audio_path(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  double get volume {
+    final result = _bindings.spine_event_data_get_volume(_ptr);
+    return result;
+  }
+
+  set volume(double value) {
+    _bindings.spine_event_data_set_volume(_ptr, value);
+  }
+
+  double get balance {
+    final result = _bindings.spine_event_data_get_balance(_ptr);
+    return result;
+  }
+
+  set balance(double value) {
+    _bindings.spine_event_data_set_balance(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_event_data_dispose(_ptr);
+  }
+}

+ 88 - 0
spine-flutter/lib/generated/event_queue_entry.dart

@@ -0,0 +1,88 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'event_type.dart';
+import 'track_entry.dart';
+import 'event.dart';
+
+/// EventQueueEntry wrapper
+class EventQueueEntry implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_event_queue_entry_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  EventQueueEntry.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory EventQueueEntry(EventType eventType, TrackEntry trackEntry, Event event) {
+    final ptr = _bindings.spine_event_queue_entry_create(eventType.value, trackEntry.nativePtr.cast(), event.nativePtr.cast());
+    return EventQueueEntry.fromPointer(ptr);
+  }
+
+  EventType get type {
+    final result = _bindings.spine_event_queue_entry_get__type(_ptr);
+    return EventType.fromValue(result);
+  }
+
+  set type(EventType value) {
+    _bindings.spine_event_queue_entry_set__type(_ptr, value.value);
+  }
+
+  TrackEntry get entry {
+    final result = _bindings.spine_event_queue_entry_get__entry(_ptr);
+    return TrackEntry.fromPointer(result);
+  }
+
+  set entry(TrackEntry value) {
+    _bindings.spine_event_queue_entry_set__entry(_ptr, value.nativePtr.cast());
+  }
+
+  Event get event {
+    final result = _bindings.spine_event_queue_entry_get__event(_ptr);
+    return Event.fromPointer(result);
+  }
+
+  set event(Event value) {
+    _bindings.spine_event_queue_entry_set__event(_ptr, value.nativePtr.cast());
+  }
+
+  void dispose() {
+    _bindings.spine_event_queue_entry_dispose(_ptr);
+  }
+}

+ 112 - 0
spine-flutter/lib/generated/event_timeline.dart

@@ -0,0 +1,112 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'event.dart';
+import 'arrays.dart';
+
+/// EventTimeline wrapper
+class EventTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_event_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  EventTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory EventTimeline(int frameCount) {
+    final ptr = _bindings.spine_event_timeline_create(frameCount);
+    return EventTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_event_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_event_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_event_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayEvent get events {
+    final result = _bindings.spine_event_timeline_get_events(_ptr);
+    return ArrayEvent.fromPointer(result);
+  }
+
+  void setFrame(int frame, Event event) {
+    _bindings.spine_event_timeline_set_frame(_ptr, frame, event.nativePtr.cast());
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_event_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_event_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_event_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_event_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_event_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_event_timeline_dispose(_ptr);
+  }
+}

+ 50 - 0
spine-flutter/lib/generated/event_type.dart

@@ -0,0 +1,50 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// EventType enum
+enum EventType {
+  start(0),
+  interrupt(1),
+  end(2),
+  dispose(3),
+  complete(4),
+  event(5);
+
+  const EventType(this.value);
+  final int value;
+
+  static EventType fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid EventType value: $value'),
+    );
+  }
+}

+ 51 - 0
spine-flutter/lib/generated/format.dart

@@ -0,0 +1,51 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// Format enum
+enum Format {
+  alpha(0),
+  intensity(1),
+  luminanceAlpha(2),
+  rgb565(3),
+  rgba4444(4),
+  rgb888(5),
+  rgba8888(6);
+
+  const Format(this.value);
+  final int value;
+
+  static Format fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid Format value: $value'),
+    );
+  }
+}

+ 83 - 0
spine-flutter/lib/generated/from_property.dart

@@ -0,0 +1,83 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'arrays.dart';
+
+/// FromProperty wrapper
+class FromProperty implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_property_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromProperty.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_property_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_property_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double get offset {
+    final result = _bindings.spine_from_property_get__offset(_ptr);
+    return result;
+  }
+
+  set offset(double value) {
+    _bindings.spine_from_property_set__offset(_ptr, value);
+  }
+
+  ArrayToProperty get to {
+    final result = _bindings.spine_from_property_get__to(_ptr);
+    return ArrayToProperty.fromPointer(result);
+  }
+
+  set to(ArrayToProperty value) {
+    _bindings.spine_from_property_set__to(_ptr, value.nativePtr.cast());
+  }
+
+  void dispose() {
+    _bindings.spine_from_property_dispose(_ptr);
+  }
+}

+ 69 - 0
spine-flutter/lib/generated/from_rotate.dart

@@ -0,0 +1,69 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// FromRotate wrapper
+class FromRotate implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_rotate_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromRotate.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory FromRotate() {
+    final ptr = _bindings.spine_from_rotate_create();
+    return FromRotate.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_rotate_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_rotate_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_from_rotate_dispose(_ptr);
+  }
+}

+ 69 - 0
spine-flutter/lib/generated/from_scale_x.dart

@@ -0,0 +1,69 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// FromScaleX wrapper
+class FromScaleX implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_scale_x_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromScaleX.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory FromScaleX() {
+    final ptr = _bindings.spine_from_scale_x_create();
+    return FromScaleX.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_scale_x_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_scale_x_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_from_scale_x_dispose(_ptr);
+  }
+}

+ 69 - 0
spine-flutter/lib/generated/from_scale_y.dart

@@ -0,0 +1,69 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// FromScaleY wrapper
+class FromScaleY implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_scale_y_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromScaleY.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory FromScaleY() {
+    final ptr = _bindings.spine_from_scale_y_create();
+    return FromScaleY.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_scale_y_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_scale_y_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_from_scale_y_dispose(_ptr);
+  }
+}

+ 69 - 0
spine-flutter/lib/generated/from_shear_y.dart

@@ -0,0 +1,69 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// FromShearY wrapper
+class FromShearY implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_shear_y_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromShearY.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory FromShearY() {
+    final ptr = _bindings.spine_from_shear_y_create();
+    return FromShearY.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_shear_y_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_shear_y_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_from_shear_y_dispose(_ptr);
+  }
+}

+ 69 - 0
spine-flutter/lib/generated/from_x.dart

@@ -0,0 +1,69 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// FromX wrapper
+class FromX implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_x_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromX.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory FromX() {
+    final ptr = _bindings.spine_from_x_create();
+    return FromX.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_x_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_x_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_from_x_dispose(_ptr);
+  }
+}

+ 69 - 0
spine-flutter/lib/generated/from_y.dart

@@ -0,0 +1,69 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+
+/// FromY wrapper
+class FromY implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_from_y_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  FromY.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory FromY() {
+    final ptr = _bindings.spine_from_y_create();
+    return FromY.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_from_y_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_from_y_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_from_y_dispose(_ptr);
+  }
+}

+ 153 - 0
spine-flutter/lib/generated/ik_constraint.dart

@@ -0,0 +1,153 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'physics.dart';
+import 'ik_constraint_data.dart';
+import 'bone.dart';
+import 'bone_pose.dart';
+import 'ik_constraint_pose.dart';
+import 'arrays.dart';
+
+/// IkConstraint wrapper
+class IkConstraint implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_ik_constraint_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  IkConstraint.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory IkConstraint(IkConstraintData data, Skeleton skeleton) {
+    final ptr = _bindings.spine_ik_constraint_create(data.nativePtr.cast(), skeleton.nativePtr.cast());
+    return IkConstraint.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_ik_constraint_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  IkConstraint copy(Skeleton skeleton) {
+    final result = _bindings.spine_ik_constraint_copy(_ptr, skeleton.nativePtr.cast());
+    return IkConstraint.fromPointer(result);
+  }
+
+  void update(Skeleton skeleton, Physics physics) {
+    _bindings.spine_ik_constraint_update(_ptr, skeleton.nativePtr.cast(), physics.value);
+  }
+
+  void sort(Skeleton skeleton) {
+    _bindings.spine_ik_constraint_sort(_ptr, skeleton.nativePtr.cast());
+  }
+
+  bool get isSourceActive {
+    final result = _bindings.spine_ik_constraint_is_source_active(_ptr);
+    return result;
+  }
+
+  IkConstraintData get data {
+    final result = _bindings.spine_ik_constraint_get_data(_ptr);
+    return IkConstraintData.fromPointer(result);
+  }
+
+  ArrayBonePose get bones {
+    final result = _bindings.spine_ik_constraint_get_bones(_ptr);
+    return ArrayBonePose.fromPointer(result);
+  }
+
+  Bone get target {
+    final result = _bindings.spine_ik_constraint_get_target(_ptr);
+    return Bone.fromPointer(result);
+  }
+
+  set target(Bone value) {
+    _bindings.spine_ik_constraint_set_target(_ptr, value.nativePtr.cast());
+  }
+
+  IkConstraintPose get pose {
+    final result = _bindings.spine_ik_constraint_get_pose(_ptr);
+    return IkConstraintPose.fromPointer(result);
+  }
+
+  IkConstraintPose get appliedPose {
+    final result = _bindings.spine_ik_constraint_get_applied_pose(_ptr);
+    return IkConstraintPose.fromPointer(result);
+  }
+
+  void resetConstrained() {
+    _bindings.spine_ik_constraint_reset_constrained(_ptr);
+  }
+
+  void constrained() {
+    _bindings.spine_ik_constraint_constrained(_ptr);
+  }
+
+  bool get isPoseEqualToApplied {
+    final result = _bindings.spine_ik_constraint_is_pose_equal_to_applied(_ptr);
+    return result;
+  }
+
+  bool get isActive {
+    final result = _bindings.spine_ik_constraint_is_active(_ptr);
+    return result;
+  }
+
+  set active(bool value) {
+    _bindings.spine_ik_constraint_set_active(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_ik_constraint_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  static void apply1(Skeleton skeleton, BonePose bone, double targetX, double targetY, bool compress, bool stretch, bool uniform, double mix) {
+    _bindings.spine_ik_constraint_apply_1(skeleton.nativePtr.cast(), bone.nativePtr.cast(), targetX, targetY, compress, stretch, uniform, mix);
+  }
+
+  static void apply2(Skeleton skeleton, BonePose parent, BonePose child, double targetX, double targetY, int bendDirection, bool stretch, bool uniform, double softness, double mix) {
+    _bindings.spine_ik_constraint_apply_2(skeleton.nativePtr.cast(), parent.nativePtr.cast(), child.nativePtr.cast(), targetX, targetY, bendDirection, stretch, uniform, softness, mix);
+  }
+
+  void dispose() {
+    _bindings.spine_ik_constraint_dispose(_ptr);
+  }
+}

+ 122 - 0
spine-flutter/lib/generated/ik_constraint_data.dart

@@ -0,0 +1,122 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'constraint.dart';
+import 'skeleton.dart';
+import 'bone_data.dart';
+import 'ik_constraint_pose.dart';
+import 'arrays.dart';
+
+/// IkConstraintData wrapper
+class IkConstraintData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_ik_constraint_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  IkConstraintData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory IkConstraintData(String name) {
+    final ptr = _bindings.spine_ik_constraint_data_create(name.toNativeUtf8().cast<Char>());
+    return IkConstraintData.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_ik_constraint_data_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  Constraint createMethod(Skeleton skeleton) {
+    final result = _bindings.spine_ik_constraint_data_create_method(_ptr, skeleton.nativePtr.cast());
+    return Constraint.fromPointer(result);
+  }
+
+  ArrayBoneData get bones {
+    final result = _bindings.spine_ik_constraint_data_get_bones(_ptr);
+    return ArrayBoneData.fromPointer(result);
+  }
+
+  BoneData get target {
+    final result = _bindings.spine_ik_constraint_data_get_target(_ptr);
+    return BoneData.fromPointer(result);
+  }
+
+  set target(BoneData value) {
+    _bindings.spine_ik_constraint_data_set_target(_ptr, value.nativePtr.cast());
+  }
+
+  bool get uniform {
+    final result = _bindings.spine_ik_constraint_data_get_uniform(_ptr);
+    return result;
+  }
+
+  set uniform(bool value) {
+    _bindings.spine_ik_constraint_data_set_uniform(_ptr, value);
+  }
+
+  String get name {
+    final result = _bindings.spine_ik_constraint_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  bool get skinRequired {
+    final result = _bindings.spine_ik_constraint_data_get_skin_required(_ptr);
+    return result;
+  }
+
+  IkConstraintPose get setupPose {
+    final result = _bindings.spine_ik_constraint_data_get_setup_pose(_ptr);
+    return IkConstraintPose.fromPointer(result);
+  }
+
+  set skinRequired(bool value) {
+    _bindings.spine_ik_constraint_data_set_skin_required(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_ik_constraint_data_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_ik_constraint_data_dispose(_ptr);
+  }
+}

+ 107 - 0
spine-flutter/lib/generated/ik_constraint_pose.dart

@@ -0,0 +1,107 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+
+/// IkConstraintPose wrapper
+class IkConstraintPose implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_ik_constraint_pose_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  IkConstraintPose.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory IkConstraintPose() {
+    final ptr = _bindings.spine_ik_constraint_pose_create();
+    return IkConstraintPose.fromPointer(ptr);
+  }
+
+  void set(IkConstraintPose pose) {
+    _bindings.spine_ik_constraint_pose_set(_ptr, pose.nativePtr.cast());
+  }
+
+  double get mix {
+    final result = _bindings.spine_ik_constraint_pose_get_mix(_ptr);
+    return result;
+  }
+
+  set mix(double value) {
+    _bindings.spine_ik_constraint_pose_set_mix(_ptr, value);
+  }
+
+  double get softness {
+    final result = _bindings.spine_ik_constraint_pose_get_softness(_ptr);
+    return result;
+  }
+
+  set softness(double value) {
+    _bindings.spine_ik_constraint_pose_set_softness(_ptr, value);
+  }
+
+  int get bendDirection {
+    final result = _bindings.spine_ik_constraint_pose_get_bend_direction(_ptr);
+    return result;
+  }
+
+  set bendDirection(int value) {
+    _bindings.spine_ik_constraint_pose_set_bend_direction(_ptr, value);
+  }
+
+  bool get compress {
+    final result = _bindings.spine_ik_constraint_pose_get_compress(_ptr);
+    return result;
+  }
+
+  set compress(bool value) {
+    _bindings.spine_ik_constraint_pose_set_compress(_ptr, value);
+  }
+
+  bool get stretch {
+    final result = _bindings.spine_ik_constraint_pose_get_stretch(_ptr);
+    return result;
+  }
+
+  set stretch(bool value) {
+    _bindings.spine_ik_constraint_pose_set_stretch(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_ik_constraint_pose_dispose(_ptr);
+  }
+}

+ 137 - 0
spine-flutter/lib/generated/ik_constraint_timeline.dart

@@ -0,0 +1,137 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// IkConstraintTimeline wrapper
+class IkConstraintTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_ik_constraint_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  IkConstraintTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory IkConstraintTimeline(int frameCount, int bezierCount, int constraintIndex) {
+    final ptr = _bindings.spine_ik_constraint_timeline_create(frameCount, bezierCount, constraintIndex);
+    return IkConstraintTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_ik_constraint_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_ik_constraint_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double mix, double softness, int bendDirection, bool compress, bool stretch) {
+    _bindings.spine_ik_constraint_timeline_set_frame(_ptr, frame, time, mix, softness, bendDirection, compress, stretch);
+  }
+
+  set linear(int value) {
+    _bindings.spine_ik_constraint_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_ik_constraint_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_ik_constraint_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_ik_constraint_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_ik_constraint_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_ik_constraint_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_ik_constraint_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_ik_constraint_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_ik_constraint_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_ik_constraint_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_ik_constraint_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_ik_constraint_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_ik_constraint_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_ik_constraint_timeline_dispose(_ptr);
+  }
+}

+ 49 - 0
spine-flutter/lib/generated/inherit.dart

@@ -0,0 +1,49 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// Inherit enum
+enum Inherit {
+  normal(0),
+  onlyTranslation(1),
+  noRotationOrReflection(2),
+  noScale(3),
+  noScaleOrReflection(4);
+
+  const Inherit(this.value);
+  final int value;
+
+  static Inherit fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid Inherit value: $value'),
+    );
+  }
+}

+ 116 - 0
spine-flutter/lib/generated/inherit_timeline.dart

@@ -0,0 +1,116 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'inherit.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// InheritTimeline wrapper
+class InheritTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_inherit_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  InheritTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory InheritTimeline(int frameCount, int boneIndex) {
+    final ptr = _bindings.spine_inherit_timeline_create(frameCount, boneIndex);
+    return InheritTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_inherit_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void setFrame(int frame, double time, Inherit inherit) {
+    _bindings.spine_inherit_timeline_set_frame(_ptr, frame, time, inherit.value);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_inherit_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_inherit_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_inherit_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_inherit_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_inherit_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_inherit_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get boneIndex {
+    final result = _bindings.spine_inherit_timeline_get_bone_index(_ptr);
+    return result;
+  }
+
+  set boneIndex(int value) {
+    _bindings.spine_inherit_timeline_set_bone_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_inherit_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_inherit_timeline_dispose(_ptr);
+  }
+}

+ 65 - 0
spine-flutter/lib/generated/linked_mesh.dart

@@ -0,0 +1,65 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'mesh_attachment.dart';
+
+/// LinkedMesh wrapper
+class LinkedMesh implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_linked_mesh_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  LinkedMesh.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory LinkedMesh(MeshAttachment mesh, dynamic skinIndex, int slotIndex, String parent, bool inheritTimelines) {
+    final ptr = _bindings.spine_linked_mesh_create(mesh.nativePtr.cast(), skinIndex, slotIndex, parent.toNativeUtf8().cast<Char>(), inheritTimelines);
+    return LinkedMesh.fromPointer(ptr);
+  }
+
+  factory LinkedMesh.variant2(MeshAttachment mesh, String skin, int slotIndex, String parent, bool inheritTimelines) {
+    final ptr = _bindings.spine_linked_mesh_create2(mesh.nativePtr.cast(), skin.toNativeUtf8().cast<Char>(), slotIndex, parent.toNativeUtf8().cast<Char>(), inheritTimelines);
+    return LinkedMesh.fromPointer(ptr);
+  }
+
+  void dispose() {
+    _bindings.spine_linked_mesh_dispose(_ptr);
+  }
+}

+ 259 - 0
spine-flutter/lib/generated/mesh_attachment.dart

@@ -0,0 +1,259 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'slot.dart';
+import 'color.dart';
+import 'texture_region.dart';
+import 'sequence.dart';
+import 'attachment.dart';
+import 'vertex_attachment.dart';
+import 'arrays.dart';
+
+/// MeshAttachment wrapper
+class MeshAttachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_mesh_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  MeshAttachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory MeshAttachment(String name) {
+    final ptr = _bindings.spine_mesh_attachment_create(name.toNativeUtf8().cast<Char>());
+    return MeshAttachment.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_mesh_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void updateRegion() {
+    _bindings.spine_mesh_attachment_update_region(_ptr);
+  }
+
+  int get hullLength {
+    final result = _bindings.spine_mesh_attachment_get_hull_length(_ptr);
+    return result;
+  }
+
+  set hullLength(int value) {
+    _bindings.spine_mesh_attachment_set_hull_length(_ptr, value);
+  }
+
+  ArrayFloat get regionUVs {
+    final result = _bindings.spine_mesh_attachment_get_region_u_vs(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set regionUVs(ArrayFloat value) {
+    _bindings.spine_mesh_attachment_set_region_u_vs(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayFloat get uVs {
+    final result = _bindings.spine_mesh_attachment_get_u_vs(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  ArrayUnsignedShort get triangles {
+    final result = _bindings.spine_mesh_attachment_get_triangles(_ptr);
+    return ArrayUnsignedShort.fromPointer(result);
+  }
+
+  set triangles(ArrayUnsignedShort value) {
+    _bindings.spine_mesh_attachment_set_triangles(_ptr, value.nativePtr.cast());
+  }
+
+  Color get color {
+    final result = _bindings.spine_mesh_attachment_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  String get path {
+    final result = _bindings.spine_mesh_attachment_get_path(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set path(String value) {
+    _bindings.spine_mesh_attachment_set_path(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  TextureRegion get region {
+    final result = _bindings.spine_mesh_attachment_get_region(_ptr);
+    return TextureRegion.fromPointer(result);
+  }
+
+  set region(TextureRegion value) {
+    _bindings.spine_mesh_attachment_set_region(_ptr, value.nativePtr.cast());
+  }
+
+  Sequence get sequence {
+    final result = _bindings.spine_mesh_attachment_get_sequence(_ptr);
+    return Sequence.fromPointer(result);
+  }
+
+  set sequence(Sequence value) {
+    _bindings.spine_mesh_attachment_set_sequence(_ptr, value.nativePtr.cast());
+  }
+
+  MeshAttachment get parentMesh {
+    final result = _bindings.spine_mesh_attachment_get_parent_mesh(_ptr);
+    return MeshAttachment.fromPointer(result);
+  }
+
+  set parentMesh(MeshAttachment value) {
+    _bindings.spine_mesh_attachment_set_parent_mesh(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayUnsignedShort get edges {
+    final result = _bindings.spine_mesh_attachment_get_edges(_ptr);
+    return ArrayUnsignedShort.fromPointer(result);
+  }
+
+  set edges(ArrayUnsignedShort value) {
+    _bindings.spine_mesh_attachment_set_edges(_ptr, value.nativePtr.cast());
+  }
+
+  double get width {
+    final result = _bindings.spine_mesh_attachment_get_width(_ptr);
+    return result;
+  }
+
+  set width(double value) {
+    _bindings.spine_mesh_attachment_set_width(_ptr, value);
+  }
+
+  double get height {
+    final result = _bindings.spine_mesh_attachment_get_height(_ptr);
+    return result;
+  }
+
+  set height(double value) {
+    _bindings.spine_mesh_attachment_set_height(_ptr, value);
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_mesh_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  MeshAttachment newLinkedMesh() {
+    final result = _bindings.spine_mesh_attachment_new_linked_mesh(_ptr);
+    return MeshAttachment.fromPointer(result);
+  }
+
+  int get id {
+    final result = _bindings.spine_mesh_attachment_get_id(_ptr);
+    return result;
+  }
+
+  ArrayInt get bones {
+    final result = _bindings.spine_mesh_attachment_get_bones(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  set bones(ArrayInt value) {
+    _bindings.spine_mesh_attachment_set_bones(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayFloat get vertices {
+    final result = _bindings.spine_mesh_attachment_get_vertices(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set vertices(ArrayFloat value) {
+    _bindings.spine_mesh_attachment_set_vertices(_ptr, value.nativePtr.cast());
+  }
+
+  int get worldVerticesLength {
+    final result = _bindings.spine_mesh_attachment_get_world_vertices_length(_ptr);
+    return result;
+  }
+
+  set worldVerticesLength(int value) {
+    _bindings.spine_mesh_attachment_set_world_vertices_length(_ptr, value);
+  }
+
+  Attachment get timelineAttachment {
+    final result = _bindings.spine_mesh_attachment_get_timeline_attachment(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  set timelineAttachment(Attachment value) {
+    _bindings.spine_mesh_attachment_set_timeline_attachment(_ptr, value.nativePtr.cast());
+  }
+
+  void copyTo(VertexAttachment other) {
+    _bindings.spine_mesh_attachment_copy_to(_ptr, other.nativePtr.cast());
+  }
+
+  String get name {
+    final result = _bindings.spine_mesh_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get refCount {
+    final result = _bindings.spine_mesh_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_mesh_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_mesh_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_mesh_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void computeWorldVertices(Skeleton skeleton, Slot slot, int start, int count, ArrayFloat worldVertices, int offset, int stride) {
+    _bindings.spine_mesh_attachment_compute_world_vertices_2(_ptr, skeleton.nativePtr.cast(), slot.nativePtr.cast(), start, count, worldVertices.nativePtr.cast(), offset, stride);
+  }
+
+  void dispose() {
+    _bindings.spine_mesh_attachment_dispose(_ptr);
+  }
+}

+ 48 - 0
spine-flutter/lib/generated/mix_blend.dart

@@ -0,0 +1,48 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// MixBlend enum
+enum MixBlend {
+  setup(0),
+  first(1),
+  replace(2),
+  add(3);
+
+  const MixBlend(this.value);
+  final int value;
+
+  static MixBlend fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid MixBlend value: $value'),
+    );
+  }
+}

+ 46 - 0
spine-flutter/lib/generated/mix_direction.dart

@@ -0,0 +1,46 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// MixDirection enum
+enum MixDirection {
+  directionIn(0),
+  directionOut(1);
+
+  const MixDirection(this.value);
+  final int value;
+
+  static MixDirection fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid MixDirection value: $value'),
+    );
+  }
+}

+ 180 - 0
spine-flutter/lib/generated/path_attachment.dart

@@ -0,0 +1,180 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'color.dart';
+import 'attachment.dart';
+import 'skeleton.dart';
+import 'slot.dart';
+import 'vertex_attachment.dart';
+import 'arrays.dart';
+
+/// PathAttachment wrapper
+class PathAttachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathAttachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathAttachment(String name) {
+    final ptr = _bindings.spine_path_attachment_create(name.toNativeUtf8().cast<Char>());
+    return PathAttachment.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_path_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  ArrayFloat get lengths {
+    final result = _bindings.spine_path_attachment_get_lengths(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set lengths(ArrayFloat value) {
+    _bindings.spine_path_attachment_set_lengths(_ptr, value.nativePtr.cast());
+  }
+
+  bool get closed {
+    final result = _bindings.spine_path_attachment_get_closed(_ptr);
+    return result;
+  }
+
+  set closed(bool value) {
+    _bindings.spine_path_attachment_set_closed(_ptr, value);
+  }
+
+  bool get constantSpeed {
+    final result = _bindings.spine_path_attachment_get_constant_speed(_ptr);
+    return result;
+  }
+
+  set constantSpeed(bool value) {
+    _bindings.spine_path_attachment_set_constant_speed(_ptr, value);
+  }
+
+  Color get color {
+    final result = _bindings.spine_path_attachment_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_path_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  int get id {
+    final result = _bindings.spine_path_attachment_get_id(_ptr);
+    return result;
+  }
+
+  ArrayInt get bones {
+    final result = _bindings.spine_path_attachment_get_bones(_ptr);
+    return ArrayInt.fromPointer(result);
+  }
+
+  set bones(ArrayInt value) {
+    _bindings.spine_path_attachment_set_bones(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayFloat get vertices {
+    final result = _bindings.spine_path_attachment_get_vertices(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set vertices(ArrayFloat value) {
+    _bindings.spine_path_attachment_set_vertices(_ptr, value.nativePtr.cast());
+  }
+
+  int get worldVerticesLength {
+    final result = _bindings.spine_path_attachment_get_world_vertices_length(_ptr);
+    return result;
+  }
+
+  set worldVerticesLength(int value) {
+    _bindings.spine_path_attachment_set_world_vertices_length(_ptr, value);
+  }
+
+  Attachment get timelineAttachment {
+    final result = _bindings.spine_path_attachment_get_timeline_attachment(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  set timelineAttachment(Attachment value) {
+    _bindings.spine_path_attachment_set_timeline_attachment(_ptr, value.nativePtr.cast());
+  }
+
+  void copyTo(VertexAttachment other) {
+    _bindings.spine_path_attachment_copy_to(_ptr, other.nativePtr.cast());
+  }
+
+  String get name {
+    final result = _bindings.spine_path_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get refCount {
+    final result = _bindings.spine_path_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_path_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_path_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_path_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void computeWorldVertices(Skeleton skeleton, Slot slot, int start, int count, ArrayFloat worldVertices, int offset, int stride) {
+    _bindings.spine_path_attachment_compute_world_vertices_2(_ptr, skeleton.nativePtr.cast(), slot.nativePtr.cast(), start, count, worldVertices.nativePtr.cast(), offset, stride);
+  }
+
+  void dispose() {
+    _bindings.spine_path_attachment_dispose(_ptr);
+  }
+}

+ 144 - 0
spine-flutter/lib/generated/path_constraint.dart

@@ -0,0 +1,144 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'physics.dart';
+import 'slot.dart';
+import 'path_constraint_data.dart';
+import 'path_constraint_pose.dart';
+import 'arrays.dart';
+
+/// PathConstraint wrapper
+class PathConstraint implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_constraint_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathConstraint.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathConstraint(PathConstraintData data, Skeleton skeleton) {
+    final ptr = _bindings.spine_path_constraint_create(data.nativePtr.cast(), skeleton.nativePtr.cast());
+    return PathConstraint.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_path_constraint_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  PathConstraint copy(Skeleton skeleton) {
+    final result = _bindings.spine_path_constraint_copy(_ptr, skeleton.nativePtr.cast());
+    return PathConstraint.fromPointer(result);
+  }
+
+  void update(Skeleton skeleton, Physics physics) {
+    _bindings.spine_path_constraint_update(_ptr, skeleton.nativePtr.cast(), physics.value);
+  }
+
+  void sort(Skeleton skeleton) {
+    _bindings.spine_path_constraint_sort(_ptr, skeleton.nativePtr.cast());
+  }
+
+  bool get isSourceActive {
+    final result = _bindings.spine_path_constraint_is_source_active(_ptr);
+    return result;
+  }
+
+  ArrayBonePose get bones {
+    final result = _bindings.spine_path_constraint_get_bones(_ptr);
+    return ArrayBonePose.fromPointer(result);
+  }
+
+  Slot get slot {
+    final result = _bindings.spine_path_constraint_get_slot(_ptr);
+    return Slot.fromPointer(result);
+  }
+
+  set slot(Slot value) {
+    _bindings.spine_path_constraint_set_slot(_ptr, value.nativePtr.cast());
+  }
+
+  PathConstraintData get data {
+    final result = _bindings.spine_path_constraint_get_data(_ptr);
+    return PathConstraintData.fromPointer(result);
+  }
+
+  PathConstraintPose get pose {
+    final result = _bindings.spine_path_constraint_get_pose(_ptr);
+    return PathConstraintPose.fromPointer(result);
+  }
+
+  PathConstraintPose get appliedPose {
+    final result = _bindings.spine_path_constraint_get_applied_pose(_ptr);
+    return PathConstraintPose.fromPointer(result);
+  }
+
+  void resetConstrained() {
+    _bindings.spine_path_constraint_reset_constrained(_ptr);
+  }
+
+  void constrained() {
+    _bindings.spine_path_constraint_constrained(_ptr);
+  }
+
+  bool get isPoseEqualToApplied {
+    final result = _bindings.spine_path_constraint_is_pose_equal_to_applied(_ptr);
+    return result;
+  }
+
+  bool get isActive {
+    final result = _bindings.spine_path_constraint_is_active(_ptr);
+    return result;
+  }
+
+  set active(bool value) {
+    _bindings.spine_path_constraint_set_active(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_path_constraint_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_path_constraint_dispose(_ptr);
+  }
+}

+ 152 - 0
spine-flutter/lib/generated/path_constraint_data.dart

@@ -0,0 +1,152 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'constraint.dart';
+import 'skeleton.dart';
+import 'slot_data.dart';
+import 'position_mode.dart';
+import 'spacing_mode.dart';
+import 'rotate_mode.dart';
+import 'path_constraint_pose.dart';
+import 'arrays.dart';
+
+/// PathConstraintData wrapper
+class PathConstraintData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_constraint_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathConstraintData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathConstraintData(String name) {
+    final ptr = _bindings.spine_path_constraint_data_create(name.toNativeUtf8().cast<Char>());
+    return PathConstraintData.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_path_constraint_data_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  Constraint createMethod(Skeleton skeleton) {
+    final result = _bindings.spine_path_constraint_data_create_method(_ptr, skeleton.nativePtr.cast());
+    return Constraint.fromPointer(result);
+  }
+
+  ArrayBoneData get bones {
+    final result = _bindings.spine_path_constraint_data_get_bones(_ptr);
+    return ArrayBoneData.fromPointer(result);
+  }
+
+  SlotData get slot {
+    final result = _bindings.spine_path_constraint_data_get_slot(_ptr);
+    return SlotData.fromPointer(result);
+  }
+
+  set slot(SlotData value) {
+    _bindings.spine_path_constraint_data_set_slot(_ptr, value.nativePtr.cast());
+  }
+
+  PositionMode get positionMode {
+    final result = _bindings.spine_path_constraint_data_get_position_mode(_ptr);
+    return PositionMode.fromValue(result);
+  }
+
+  set positionMode(PositionMode value) {
+    _bindings.spine_path_constraint_data_set_position_mode(_ptr, value.value);
+  }
+
+  SpacingMode get spacingMode {
+    final result = _bindings.spine_path_constraint_data_get_spacing_mode(_ptr);
+    return SpacingMode.fromValue(result);
+  }
+
+  set spacingMode(SpacingMode value) {
+    _bindings.spine_path_constraint_data_set_spacing_mode(_ptr, value.value);
+  }
+
+  RotateMode get rotateMode {
+    final result = _bindings.spine_path_constraint_data_get_rotate_mode(_ptr);
+    return RotateMode.fromValue(result);
+  }
+
+  set rotateMode(RotateMode value) {
+    _bindings.spine_path_constraint_data_set_rotate_mode(_ptr, value.value);
+  }
+
+  double get offsetRotation {
+    final result = _bindings.spine_path_constraint_data_get_offset_rotation(_ptr);
+    return result;
+  }
+
+  set offsetRotation(double value) {
+    _bindings.spine_path_constraint_data_set_offset_rotation(_ptr, value);
+  }
+
+  String get name {
+    final result = _bindings.spine_path_constraint_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  bool get skinRequired {
+    final result = _bindings.spine_path_constraint_data_get_skin_required(_ptr);
+    return result;
+  }
+
+  PathConstraintPose get setupPose {
+    final result = _bindings.spine_path_constraint_data_get_setup_pose(_ptr);
+    return PathConstraintPose.fromPointer(result);
+  }
+
+  set skinRequired(bool value) {
+    _bindings.spine_path_constraint_data_set_skin_required(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_path_constraint_data_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_path_constraint_data_dispose(_ptr);
+  }
+}

+ 137 - 0
spine-flutter/lib/generated/path_constraint_mix_timeline.dart

@@ -0,0 +1,137 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PathConstraintMixTimeline wrapper
+class PathConstraintMixTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_constraint_mix_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathConstraintMixTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathConstraintMixTimeline(int frameCount, int bezierCount, int constraintIndex) {
+    final ptr = _bindings.spine_path_constraint_mix_timeline_create(frameCount, bezierCount, constraintIndex);
+    return PathConstraintMixTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_path_constraint_mix_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double mixRotate, double mixX, double mixY) {
+    _bindings.spine_path_constraint_mix_timeline_set_frame(_ptr, frame, time, mixRotate, mixX, mixY);
+  }
+
+  set linear(int value) {
+    _bindings.spine_path_constraint_mix_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_path_constraint_mix_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_path_constraint_mix_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_path_constraint_mix_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_path_constraint_mix_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_path_constraint_mix_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_path_constraint_mix_timeline_dispose(_ptr);
+  }
+}

+ 107 - 0
spine-flutter/lib/generated/path_constraint_pose.dart

@@ -0,0 +1,107 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+
+/// PathConstraintPose wrapper
+class PathConstraintPose implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_constraint_pose_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathConstraintPose.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathConstraintPose() {
+    final ptr = _bindings.spine_path_constraint_pose_create();
+    return PathConstraintPose.fromPointer(ptr);
+  }
+
+  void set(PathConstraintPose pose) {
+    _bindings.spine_path_constraint_pose_set(_ptr, pose.nativePtr.cast());
+  }
+
+  double get position {
+    final result = _bindings.spine_path_constraint_pose_get_position(_ptr);
+    return result;
+  }
+
+  set position(double value) {
+    _bindings.spine_path_constraint_pose_set_position(_ptr, value);
+  }
+
+  double get spacing {
+    final result = _bindings.spine_path_constraint_pose_get_spacing(_ptr);
+    return result;
+  }
+
+  set spacing(double value) {
+    _bindings.spine_path_constraint_pose_set_spacing(_ptr, value);
+  }
+
+  double get mixRotate {
+    final result = _bindings.spine_path_constraint_pose_get_mix_rotate(_ptr);
+    return result;
+  }
+
+  set mixRotate(double value) {
+    _bindings.spine_path_constraint_pose_set_mix_rotate(_ptr, value);
+  }
+
+  double get mixX {
+    final result = _bindings.spine_path_constraint_pose_get_mix_x(_ptr);
+    return result;
+  }
+
+  set mixX(double value) {
+    _bindings.spine_path_constraint_pose_set_mix_x(_ptr, value);
+  }
+
+  double get mixY {
+    final result = _bindings.spine_path_constraint_pose_get_mix_y(_ptr);
+    return result;
+  }
+
+  set mixY(double value) {
+    _bindings.spine_path_constraint_pose_set_mix_y(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_path_constraint_pose_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/path_constraint_position_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PathConstraintPositionTimeline wrapper
+class PathConstraintPositionTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_constraint_position_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathConstraintPositionTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathConstraintPositionTimeline(int frameCount, int bezierCount, int constraintIndex) {
+    final ptr = _bindings.spine_path_constraint_position_timeline_create(frameCount, bezierCount, constraintIndex);
+    return PathConstraintPositionTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_path_constraint_position_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_path_constraint_position_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_path_constraint_position_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_path_constraint_position_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_path_constraint_position_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_path_constraint_position_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_path_constraint_position_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_path_constraint_position_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_path_constraint_position_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_path_constraint_position_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_path_constraint_position_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_path_constraint_position_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_path_constraint_position_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_path_constraint_position_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_path_constraint_position_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_path_constraint_position_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_path_constraint_position_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_path_constraint_position_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_path_constraint_position_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_path_constraint_position_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_path_constraint_position_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_path_constraint_position_timeline_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/path_constraint_spacing_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PathConstraintSpacingTimeline wrapper
+class PathConstraintSpacingTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_path_constraint_spacing_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PathConstraintSpacingTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PathConstraintSpacingTimeline(int frameCount, int bezierCount, int constraintIndex) {
+    final ptr = _bindings.spine_path_constraint_spacing_timeline_create(frameCount, bezierCount, constraintIndex);
+    return PathConstraintSpacingTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_path_constraint_spacing_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_path_constraint_spacing_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_path_constraint_spacing_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_path_constraint_spacing_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_path_constraint_spacing_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_path_constraint_spacing_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_path_constraint_spacing_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_path_constraint_spacing_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_path_constraint_spacing_timeline_dispose(_ptr);
+  }
+}

+ 48 - 0
spine-flutter/lib/generated/physics.dart

@@ -0,0 +1,48 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// Physics enum
+enum Physics {
+  none(0),
+  reset(1),
+  update(2),
+  pose(3);
+
+  const Physics(this.value);
+  final int value;
+
+  static Physics fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid Physics value: $value'),
+    );
+  }
+}

+ 150 - 0
spine-flutter/lib/generated/physics_constraint.dart

@@ -0,0 +1,150 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'physics.dart';
+import 'bone_pose.dart';
+import 'physics_constraint_data.dart';
+import 'physics_constraint_pose.dart';
+
+/// PhysicsConstraint wrapper
+class PhysicsConstraint implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraint.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraint(PhysicsConstraintData data, Skeleton skeleton) {
+    final ptr = _bindings.spine_physics_constraint_create(data.nativePtr.cast(), skeleton.nativePtr.cast());
+    return PhysicsConstraint.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void update(Skeleton skeleton, Physics physics) {
+    _bindings.spine_physics_constraint_update(_ptr, skeleton.nativePtr.cast(), physics.value);
+  }
+
+  void sort(Skeleton skeleton) {
+    _bindings.spine_physics_constraint_sort(_ptr, skeleton.nativePtr.cast());
+  }
+
+  bool get isSourceActive {
+    final result = _bindings.spine_physics_constraint_is_source_active(_ptr);
+    return result;
+  }
+
+  PhysicsConstraint copy(Skeleton skeleton) {
+    final result = _bindings.spine_physics_constraint_copy(_ptr, skeleton.nativePtr.cast());
+    return PhysicsConstraint.fromPointer(result);
+  }
+
+  void reset(Skeleton skeleton) {
+    _bindings.spine_physics_constraint_reset(_ptr, skeleton.nativePtr.cast());
+  }
+
+  void translate(double x, double y) {
+    _bindings.spine_physics_constraint_translate(_ptr, x, y);
+  }
+
+  void rotate(double x, double y, double degrees) {
+    _bindings.spine_physics_constraint_rotate(_ptr, x, y, degrees);
+  }
+
+  BonePose get bone {
+    final result = _bindings.spine_physics_constraint_get_bone(_ptr);
+    return BonePose.fromPointer(result);
+  }
+
+  set bone(BonePose value) {
+    _bindings.spine_physics_constraint_set_bone(_ptr, value.nativePtr.cast());
+  }
+
+  PhysicsConstraintData get data {
+    final result = _bindings.spine_physics_constraint_get_data(_ptr);
+    return PhysicsConstraintData.fromPointer(result);
+  }
+
+  PhysicsConstraintPose get pose {
+    final result = _bindings.spine_physics_constraint_get_pose(_ptr);
+    return PhysicsConstraintPose.fromPointer(result);
+  }
+
+  PhysicsConstraintPose get appliedPose {
+    final result = _bindings.spine_physics_constraint_get_applied_pose(_ptr);
+    return PhysicsConstraintPose.fromPointer(result);
+  }
+
+  void resetConstrained() {
+    _bindings.spine_physics_constraint_reset_constrained(_ptr);
+  }
+
+  void constrained() {
+    _bindings.spine_physics_constraint_constrained(_ptr);
+  }
+
+  bool get isPoseEqualToApplied {
+    final result = _bindings.spine_physics_constraint_is_pose_equal_to_applied(_ptr);
+    return result;
+  }
+
+  bool get isActive {
+    final result = _bindings.spine_physics_constraint_is_active(_ptr);
+    return result;
+  }
+
+  set active(bool value) {
+    _bindings.spine_physics_constraint_set_active(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_damping_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintDampingTimeline wrapper
+class PhysicsConstraintDampingTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_damping_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintDampingTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintDampingTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_damping_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintDampingTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_damping_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_damping_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_damping_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_damping_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_damping_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_damping_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_damping_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_damping_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_damping_timeline_dispose(_ptr);
+  }
+}

+ 233 - 0
spine-flutter/lib/generated/physics_constraint_data.dart

@@ -0,0 +1,233 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'constraint.dart';
+import 'skeleton.dart';
+import 'bone_data.dart';
+import 'physics_constraint_pose.dart';
+
+/// PhysicsConstraintData wrapper
+class PhysicsConstraintData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintData(String name) {
+    final ptr = _bindings.spine_physics_constraint_data_create(name.toNativeUtf8().cast<Char>());
+    return PhysicsConstraintData.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_data_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  Constraint createMethod(Skeleton skeleton) {
+    final result = _bindings.spine_physics_constraint_data_create_method(_ptr, skeleton.nativePtr.cast());
+    return Constraint.fromPointer(result);
+  }
+
+  BoneData get bone {
+    final result = _bindings.spine_physics_constraint_data_get_bone(_ptr);
+    return BoneData.fromPointer(result);
+  }
+
+  set bone(BoneData value) {
+    _bindings.spine_physics_constraint_data_set_bone(_ptr, value.nativePtr.cast());
+  }
+
+  double get step {
+    final result = _bindings.spine_physics_constraint_data_get_step(_ptr);
+    return result;
+  }
+
+  set step(double value) {
+    _bindings.spine_physics_constraint_data_set_step(_ptr, value);
+  }
+
+  double get x {
+    final result = _bindings.spine_physics_constraint_data_get_x(_ptr);
+    return result;
+  }
+
+  set x(double value) {
+    _bindings.spine_physics_constraint_data_set_x(_ptr, value);
+  }
+
+  double get y {
+    final result = _bindings.spine_physics_constraint_data_get_y(_ptr);
+    return result;
+  }
+
+  set y(double value) {
+    _bindings.spine_physics_constraint_data_set_y(_ptr, value);
+  }
+
+  double get rotate {
+    final result = _bindings.spine_physics_constraint_data_get_rotate(_ptr);
+    return result;
+  }
+
+  set rotate(double value) {
+    _bindings.spine_physics_constraint_data_set_rotate(_ptr, value);
+  }
+
+  double get scaleX {
+    final result = _bindings.spine_physics_constraint_data_get_scale_x(_ptr);
+    return result;
+  }
+
+  set scaleX(double value) {
+    _bindings.spine_physics_constraint_data_set_scale_x(_ptr, value);
+  }
+
+  double get shearX {
+    final result = _bindings.spine_physics_constraint_data_get_shear_x(_ptr);
+    return result;
+  }
+
+  set shearX(double value) {
+    _bindings.spine_physics_constraint_data_set_shear_x(_ptr, value);
+  }
+
+  double get limit {
+    final result = _bindings.spine_physics_constraint_data_get_limit(_ptr);
+    return result;
+  }
+
+  set limit(double value) {
+    _bindings.spine_physics_constraint_data_set_limit(_ptr, value);
+  }
+
+  bool get inertiaGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_inertia_global(_ptr);
+    return result;
+  }
+
+  set inertiaGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_inertia_global(_ptr, value);
+  }
+
+  bool get strengthGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_strength_global(_ptr);
+    return result;
+  }
+
+  set strengthGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_strength_global(_ptr, value);
+  }
+
+  bool get dampingGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_damping_global(_ptr);
+    return result;
+  }
+
+  set dampingGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_damping_global(_ptr, value);
+  }
+
+  bool get massGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_mass_global(_ptr);
+    return result;
+  }
+
+  set massGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_mass_global(_ptr, value);
+  }
+
+  bool get windGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_wind_global(_ptr);
+    return result;
+  }
+
+  set windGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_wind_global(_ptr, value);
+  }
+
+  bool get gravityGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_gravity_global(_ptr);
+    return result;
+  }
+
+  set gravityGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_gravity_global(_ptr, value);
+  }
+
+  bool get mixGlobal {
+    final result = _bindings.spine_physics_constraint_data_get_mix_global(_ptr);
+    return result;
+  }
+
+  set mixGlobal(bool value) {
+    _bindings.spine_physics_constraint_data_set_mix_global(_ptr, value);
+  }
+
+  String get name {
+    final result = _bindings.spine_physics_constraint_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  bool get skinRequired {
+    final result = _bindings.spine_physics_constraint_data_get_skin_required(_ptr);
+    return result;
+  }
+
+  PhysicsConstraintPose get setupPose {
+    final result = _bindings.spine_physics_constraint_data_get_setup_pose(_ptr);
+    return PhysicsConstraintPose.fromPointer(result);
+  }
+
+  set skinRequired(bool value) {
+    _bindings.spine_physics_constraint_data_set_skin_required(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_data_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_data_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_gravity_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintGravityTimeline wrapper
+class PhysicsConstraintGravityTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_gravity_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintGravityTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintGravityTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_gravity_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintGravityTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_gravity_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_gravity_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_gravity_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_gravity_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_gravity_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_gravity_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_gravity_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_gravity_timeline_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_inertia_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintInertiaTimeline wrapper
+class PhysicsConstraintInertiaTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_inertia_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintInertiaTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintInertiaTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_inertia_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintInertiaTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_inertia_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_inertia_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_inertia_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_inertia_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_inertia_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_inertia_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_inertia_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_inertia_timeline_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_mass_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintMassTimeline wrapper
+class PhysicsConstraintMassTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_mass_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintMassTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintMassTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_mass_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintMassTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_mass_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_mass_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_mass_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_mass_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_mass_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_mass_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_mass_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_mass_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_mass_timeline_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_mix_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintMixTimeline wrapper
+class PhysicsConstraintMixTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_mix_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintMixTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintMixTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_mix_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintMixTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_mix_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_mix_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_mix_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_mix_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_mix_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_mix_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_mix_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_mix_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_mix_timeline_dispose(_ptr);
+  }
+}

+ 125 - 0
spine-flutter/lib/generated/physics_constraint_pose.dart

@@ -0,0 +1,125 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+
+/// PhysicsConstraintPose wrapper
+class PhysicsConstraintPose implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_pose_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintPose.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintPose() {
+    final ptr = _bindings.spine_physics_constraint_pose_create();
+    return PhysicsConstraintPose.fromPointer(ptr);
+  }
+
+  void set(PhysicsConstraintPose pose) {
+    _bindings.spine_physics_constraint_pose_set(_ptr, pose.nativePtr.cast());
+  }
+
+  double get inertia {
+    final result = _bindings.spine_physics_constraint_pose_get_inertia(_ptr);
+    return result;
+  }
+
+  set inertia(double value) {
+    _bindings.spine_physics_constraint_pose_set_inertia(_ptr, value);
+  }
+
+  double get strength {
+    final result = _bindings.spine_physics_constraint_pose_get_strength(_ptr);
+    return result;
+  }
+
+  set strength(double value) {
+    _bindings.spine_physics_constraint_pose_set_strength(_ptr, value);
+  }
+
+  double get damping {
+    final result = _bindings.spine_physics_constraint_pose_get_damping(_ptr);
+    return result;
+  }
+
+  set damping(double value) {
+    _bindings.spine_physics_constraint_pose_set_damping(_ptr, value);
+  }
+
+  double get massInverse {
+    final result = _bindings.spine_physics_constraint_pose_get_mass_inverse(_ptr);
+    return result;
+  }
+
+  set massInverse(double value) {
+    _bindings.spine_physics_constraint_pose_set_mass_inverse(_ptr, value);
+  }
+
+  double get wind {
+    final result = _bindings.spine_physics_constraint_pose_get_wind(_ptr);
+    return result;
+  }
+
+  set wind(double value) {
+    _bindings.spine_physics_constraint_pose_set_wind(_ptr, value);
+  }
+
+  double get gravity {
+    final result = _bindings.spine_physics_constraint_pose_get_gravity(_ptr);
+    return result;
+  }
+
+  set gravity(double value) {
+    _bindings.spine_physics_constraint_pose_set_gravity(_ptr, value);
+  }
+
+  double get mix {
+    final result = _bindings.spine_physics_constraint_pose_get_mix(_ptr);
+    return result;
+  }
+
+  set mix(double value) {
+    _bindings.spine_physics_constraint_pose_set_mix(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_pose_dispose(_ptr);
+  }
+}

+ 115 - 0
spine-flutter/lib/generated/physics_constraint_reset_timeline.dart

@@ -0,0 +1,115 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintResetTimeline wrapper
+class PhysicsConstraintResetTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_reset_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintResetTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintResetTimeline(int frameCount, int constraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_reset_timeline_create(frameCount, constraintIndex);
+    return PhysicsConstraintResetTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_reset_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  void setFrame(int frame, double time) {
+    _bindings.spine_physics_constraint_reset_timeline_set_frame(_ptr, frame, time);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_reset_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_reset_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_reset_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_reset_timeline_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_strength_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintStrengthTimeline wrapper
+class PhysicsConstraintStrengthTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_strength_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintStrengthTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintStrengthTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_strength_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintStrengthTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_strength_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_strength_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_strength_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_strength_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_strength_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_strength_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_strength_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_strength_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_strength_timeline_dispose(_ptr);
+  }
+}

+ 157 - 0
spine-flutter/lib/generated/physics_constraint_timeline.dart

@@ -0,0 +1,157 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintTimeline wrapper
+class PhysicsConstraintTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_timeline_dispose(_ptr);
+  }
+}

+ 162 - 0
spine-flutter/lib/generated/physics_constraint_wind_timeline.dart

@@ -0,0 +1,162 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// PhysicsConstraintWindTimeline wrapper
+class PhysicsConstraintWindTimeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_physics_constraint_wind_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PhysicsConstraintWindTimeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PhysicsConstraintWindTimeline(int frameCount, int bezierCount, int physicsConstraintIndex) {
+    final ptr = _bindings.spine_physics_constraint_wind_timeline_create(frameCount, bezierCount, physicsConstraintIndex);
+    return PhysicsConstraintWindTimeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_physics_constraint_wind_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  void setFrame(int frame, double time, double value) {
+    _bindings.spine_physics_constraint_wind_timeline_set_frame(_ptr, frame, time, value);
+  }
+
+  double getCurveValue(double time) {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_curve_value(_ptr, time);
+    return result;
+  }
+
+  double getRelativeValue(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_relative_value(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getScaleValue(double time, double alpha, MixBlend blend, MixDirection direction, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_scale_value(_ptr, time, alpha, blend.value, direction.value, current, setup);
+    return result;
+  }
+
+  set linear(int value) {
+    _bindings.spine_physics_constraint_wind_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_physics_constraint_wind_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_physics_constraint_wind_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get constraintIndex {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_constraint_index(_ptr);
+    return result;
+  }
+
+  set constraintIndex(int value) {
+    _bindings.spine_physics_constraint_wind_timeline_set_constraint_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_physics_constraint_wind_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  double getAbsoluteValue1(double time, double alpha, MixBlend blend, double current, double setup) {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_absolute_value_1(_ptr, time, alpha, blend.value, current, setup);
+    return result;
+  }
+
+  double getAbsoluteValue2(double time, double alpha, MixBlend blend, double current, double setup, double value) {
+    final result = _bindings.spine_physics_constraint_wind_timeline_get_absolute_value_2(_ptr, time, alpha, blend.value, current, setup, value);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_physics_constraint_wind_timeline_dispose(_ptr);
+  }
+}

+ 133 - 0
spine-flutter/lib/generated/point_attachment.dart

@@ -0,0 +1,133 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'color.dart';
+import 'bone_pose.dart';
+import 'attachment.dart';
+
+/// PointAttachment wrapper
+class PointAttachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_point_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PointAttachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PointAttachment(String name) {
+    final ptr = _bindings.spine_point_attachment_create(name.toNativeUtf8().cast<Char>());
+    return PointAttachment.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_point_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  double get x {
+    final result = _bindings.spine_point_attachment_get_x(_ptr);
+    return result;
+  }
+
+  set x(double value) {
+    _bindings.spine_point_attachment_set_x(_ptr, value);
+  }
+
+  double get y {
+    final result = _bindings.spine_point_attachment_get_y(_ptr);
+    return result;
+  }
+
+  set y(double value) {
+    _bindings.spine_point_attachment_set_y(_ptr, value);
+  }
+
+  double get rotation {
+    final result = _bindings.spine_point_attachment_get_rotation(_ptr);
+    return result;
+  }
+
+  set rotation(double value) {
+    _bindings.spine_point_attachment_set_rotation(_ptr, value);
+  }
+
+  Color get color {
+    final result = _bindings.spine_point_attachment_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  double computeWorldRotation(BonePose bone) {
+    final result = _bindings.spine_point_attachment_compute_world_rotation(_ptr, bone.nativePtr.cast());
+    return result;
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_point_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  String get name {
+    final result = _bindings.spine_point_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get refCount {
+    final result = _bindings.spine_point_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_point_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_point_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_point_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_point_attachment_dispose(_ptr);
+  }
+}

+ 77 - 0
spine-flutter/lib/generated/polygon.dart

@@ -0,0 +1,77 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'arrays.dart';
+
+/// Polygon wrapper
+class Polygon implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_polygon_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Polygon.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory Polygon() {
+    final ptr = _bindings.spine_polygon_create();
+    return Polygon.fromPointer(ptr);
+  }
+
+  ArrayFloat get vertices {
+    final result = _bindings.spine_polygon_get__vertices(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  set vertices(ArrayFloat value) {
+    _bindings.spine_polygon_set__vertices(_ptr, value.nativePtr.cast());
+  }
+
+  int get count {
+    final result = _bindings.spine_polygon_get__count(_ptr);
+    return result;
+  }
+
+  set count(int value) {
+    _bindings.spine_polygon_set__count(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_polygon_dispose(_ptr);
+  }
+}

+ 66 - 0
spine-flutter/lib/generated/posed.dart

@@ -0,0 +1,66 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+
+/// Posed wrapper
+class Posed implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_posed_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Posed.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  void constrained() {
+    _bindings.spine_posed_constrained(_ptr);
+  }
+
+  void resetConstrained() {
+    _bindings.spine_posed_reset_constrained(_ptr);
+  }
+
+  bool get isPoseEqualToApplied {
+    final result = _bindings.spine_posed_is_pose_equal_to_applied(_ptr);
+    return result;
+  }
+
+  void dispose() {
+    _bindings.spine_posed_dispose(_ptr);
+  }
+}

+ 62 - 0
spine-flutter/lib/generated/posed_active.dart

@@ -0,0 +1,62 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+
+/// PosedActive wrapper
+class PosedActive implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_posed_active_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PosedActive.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  bool get isActive {
+    final result = _bindings.spine_posed_active_is_active(_ptr);
+    return result;
+  }
+
+  set active(bool value) {
+    _bindings.spine_posed_active_set_active(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_posed_active_dispose(_ptr);
+  }
+}

+ 73 - 0
spine-flutter/lib/generated/posed_data.dart

@@ -0,0 +1,73 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+
+/// PosedData wrapper
+class PosedData implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_posed_data_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  PosedData.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory PosedData(String name) {
+    final ptr = _bindings.spine_posed_data_create(name.toNativeUtf8().cast<Char>());
+    return PosedData.fromPointer(ptr);
+  }
+
+  String get name {
+    final result = _bindings.spine_posed_data_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  bool get skinRequired {
+    final result = _bindings.spine_posed_data_get_skin_required(_ptr);
+    return result;
+  }
+
+  set skinRequired(bool value) {
+    _bindings.spine_posed_data_set_skin_required(_ptr, value);
+  }
+
+  void dispose() {
+    _bindings.spine_posed_data_dispose(_ptr);
+  }
+}

+ 46 - 0
spine-flutter/lib/generated/position_mode.dart

@@ -0,0 +1,46 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// PositionMode enum
+enum PositionMode {
+  fixed(0),
+  percent(1);
+
+  const PositionMode(this.value);
+  final int value;
+
+  static PositionMode fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid PositionMode value: $value'),
+    );
+  }
+}

+ 75 - 0
spine-flutter/lib/generated/property.dart

@@ -0,0 +1,75 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+/// Property enum
+enum Property {
+  rotate(1 << 0),
+  x(1 << 1),
+  y(1 << 2),
+  scaleX(1 << 3),
+  scaleY(1 << 4),
+  shearX(1 << 5),
+  shearY(1 << 6),
+  inherit(1 << 7),
+  rgb(1 << 8),
+  alpha(1 << 9),
+  rgb2(1 << 10),
+  attachment(1 << 11),
+  deform(1 << 12),
+  event(1 << 13),
+  drawOrder(1 << 14),
+  ikConstraint(1 << 15),
+  transformConstraint(1 << 16),
+  pathConstraintPosition(1 << 17),
+  pathConstraintSpacing(1 << 18),
+  pathConstraintMix(1 << 19),
+  physicsConstraintInertia(1 << 20),
+  physicsConstraintStrength(1 << 21),
+  physicsConstraintDamping(1 << 22),
+  physicsConstraintMass(1 << 23),
+  physicsConstraintWind(1 << 24),
+  physicsConstraintGravity(1 << 25),
+  physicsConstraintMix(1 << 26),
+  physicsConstraintReset(1 << 27),
+  sequence(1 << 28),
+  sliderTime(1 << 29),
+  sliderMix(1 << 30);
+
+  const Property(this.value);
+  final int value;
+
+  static Property fromValue(int value) {
+    return values.firstWhere(
+      (e) => e.value == value,
+      orElse: () => throw ArgumentError('Invalid Property value: $value'),
+    );
+  }
+}

+ 212 - 0
spine-flutter/lib/generated/region_attachment.dart

@@ -0,0 +1,212 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'slot.dart';
+import 'color.dart';
+import 'texture_region.dart';
+import 'sequence.dart';
+import 'attachment.dart';
+import 'arrays.dart';
+
+/// RegionAttachment wrapper
+class RegionAttachment implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_region_attachment_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  RegionAttachment.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory RegionAttachment(String name) {
+    final ptr = _bindings.spine_region_attachment_create(name.toNativeUtf8().cast<Char>());
+    return RegionAttachment.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_region_attachment_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void updateRegion() {
+    _bindings.spine_region_attachment_update_region(_ptr);
+  }
+
+  double get x {
+    final result = _bindings.spine_region_attachment_get_x(_ptr);
+    return result;
+  }
+
+  set x(double value) {
+    _bindings.spine_region_attachment_set_x(_ptr, value);
+  }
+
+  double get y {
+    final result = _bindings.spine_region_attachment_get_y(_ptr);
+    return result;
+  }
+
+  set y(double value) {
+    _bindings.spine_region_attachment_set_y(_ptr, value);
+  }
+
+  double get rotation {
+    final result = _bindings.spine_region_attachment_get_rotation(_ptr);
+    return result;
+  }
+
+  set rotation(double value) {
+    _bindings.spine_region_attachment_set_rotation(_ptr, value);
+  }
+
+  double get scaleX {
+    final result = _bindings.spine_region_attachment_get_scale_x(_ptr);
+    return result;
+  }
+
+  set scaleX(double value) {
+    _bindings.spine_region_attachment_set_scale_x(_ptr, value);
+  }
+
+  double get scaleY {
+    final result = _bindings.spine_region_attachment_get_scale_y(_ptr);
+    return result;
+  }
+
+  set scaleY(double value) {
+    _bindings.spine_region_attachment_set_scale_y(_ptr, value);
+  }
+
+  double get width {
+    final result = _bindings.spine_region_attachment_get_width(_ptr);
+    return result;
+  }
+
+  set width(double value) {
+    _bindings.spine_region_attachment_set_width(_ptr, value);
+  }
+
+  double get height {
+    final result = _bindings.spine_region_attachment_get_height(_ptr);
+    return result;
+  }
+
+  set height(double value) {
+    _bindings.spine_region_attachment_set_height(_ptr, value);
+  }
+
+  Color get color {
+    final result = _bindings.spine_region_attachment_get_color(_ptr);
+    return Color.fromPointer(result);
+  }
+
+  String get path {
+    final result = _bindings.spine_region_attachment_get_path(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  set path(String value) {
+    _bindings.spine_region_attachment_set_path(_ptr, value.toNativeUtf8().cast<Char>());
+  }
+
+  TextureRegion get region {
+    final result = _bindings.spine_region_attachment_get_region(_ptr);
+    return TextureRegion.fromPointer(result);
+  }
+
+  set region(TextureRegion value) {
+    _bindings.spine_region_attachment_set_region(_ptr, value.nativePtr.cast());
+  }
+
+  Sequence get sequence {
+    final result = _bindings.spine_region_attachment_get_sequence(_ptr);
+    return Sequence.fromPointer(result);
+  }
+
+  set sequence(Sequence value) {
+    _bindings.spine_region_attachment_set_sequence(_ptr, value.nativePtr.cast());
+  }
+
+  ArrayFloat get offset {
+    final result = _bindings.spine_region_attachment_get_offset(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  ArrayFloat get uVs {
+    final result = _bindings.spine_region_attachment_get_u_vs(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  Attachment copy() {
+    final result = _bindings.spine_region_attachment_copy(_ptr);
+    return Attachment.fromPointer(result);
+  }
+
+  String get name {
+    final result = _bindings.spine_region_attachment_get_name(_ptr);
+    return result.cast<Utf8>().toDartString();
+  }
+
+  int get refCount {
+    final result = _bindings.spine_region_attachment_get_ref_count(_ptr);
+    return result;
+  }
+
+  void reference() {
+    _bindings.spine_region_attachment_reference(_ptr);
+  }
+
+  void dereference() {
+    _bindings.spine_region_attachment_dereference(_ptr);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_region_attachment_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void computeWorldVertices(Slot slot, ArrayFloat worldVertices, int offset, int stride) {
+    _bindings.spine_region_attachment_compute_world_vertices_2(_ptr, slot.nativePtr.cast(), worldVertices.nativePtr.cast(), offset, stride);
+  }
+
+  void dispose() {
+    _bindings.spine_region_attachment_dispose(_ptr);
+  }
+}

+ 74 - 0
spine-flutter/lib/generated/render_command.dart

@@ -0,0 +1,74 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'blend_mode.dart';
+
+/// RenderCommand wrapper
+class RenderCommand implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_render_command_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  RenderCommand.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  int get numVertices {
+    final result = _bindings.spine_render_command_get_num_vertices(_ptr);
+    return result;
+  }
+
+  int get numIndices {
+    final result = _bindings.spine_render_command_get_num_indices(_ptr);
+    return result;
+  }
+
+  BlendMode get blendMode {
+    final result = _bindings.spine_render_command_get_blend_mode(_ptr);
+    return BlendMode.fromValue(result);
+  }
+
+  RenderCommand get next {
+    final result = _bindings.spine_render_command_get_next(_ptr);
+    return RenderCommand.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_render_command_dispose(_ptr);
+  }
+}

+ 137 - 0
spine-flutter/lib/generated/rgb2_timeline.dart

@@ -0,0 +1,137 @@
+// ******************************************************************************
+// Spine Runtimes License Agreement
+// Last updated July 28, 2023. Replaces all prior versions.
+//
+// Copyright (c) 2013-2023, Esoteric Software LLC
+//
+// Integration of the Spine Runtimes into software or otherwise creating
+// derivative works of the Spine Runtimes is permitted under the terms and
+// conditions of Section 2 of the Spine Editor License Agreement:
+// http://esotericsoftware.com/spine-editor-license
+//
+// Otherwise, it is permitted to integrate the Spine Runtimes into software or
+// otherwise create derivative works of the Spine Runtimes (collectively,
+// "Products"), provided that each user of the Products must obtain their own
+// Spine Editor license and redistribution of the Products in any form must
+// include this license and copyright notice.
+//
+// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+// SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// *****************************************************************************/
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+
+import 'dart:ffi';
+import 'spine_flutter_bindings_generated.dart';
+import 'rtti.dart';
+import 'skeleton.dart';
+import 'mix_blend.dart';
+import 'mix_direction.dart';
+import 'arrays.dart';
+
+/// Rgb2Timeline wrapper
+class Rgb2Timeline implements Finalizable {
+  static late SpineFlutterBindings _bindings;
+  final Pointer<spine_rgb2_timeline_wrapper> _ptr;
+
+  /// Initialize the bindings for all spine-flutter classes
+  static void init(SpineFlutterBindings bindings) {
+    _bindings = bindings;
+  }
+
+  Rgb2Timeline.fromPointer(this._ptr);
+
+  /// Get the native pointer for FFI calls
+  Pointer get nativePtr => _ptr;
+
+  factory Rgb2Timeline(int frameCount, int bezierCount, int slotIndex) {
+    final ptr = _bindings.spine_rgb2_timeline_create(frameCount, bezierCount, slotIndex);
+    return Rgb2Timeline.fromPointer(ptr);
+  }
+
+  Rtti get rtti {
+    final result = _bindings.spine_rgb2_timeline_get_rtti(_ptr);
+    return Rtti.fromPointer(result);
+  }
+
+  void setFrame(int frame, double time, double r, double g, double b, double r2, double g2, double b2) {
+    _bindings.spine_rgb2_timeline_set_frame(_ptr, frame, time, r, g, b, r2, g2, b2);
+  }
+
+  void apply(Skeleton skeleton, double lastTime, double time, ArrayEvent pEvents, double alpha, MixBlend blend, MixDirection direction, bool appliedPose) {
+    _bindings.spine_rgb2_timeline_apply(_ptr, skeleton.nativePtr.cast(), lastTime, time, pEvents.nativePtr.cast(), alpha, blend.value, direction.value, appliedPose);
+  }
+
+  set linear(int value) {
+    _bindings.spine_rgb2_timeline_set_linear(_ptr, value);
+  }
+
+  set stepped(int value) {
+    _bindings.spine_rgb2_timeline_set_stepped(_ptr, value);
+  }
+
+  void setBezier(int bezier, int frame, double value, double time1, double value1, double cx1, double cy1, double cx2, double cy2, double time2, double value2) {
+    _bindings.spine_rgb2_timeline_set_bezier(_ptr, bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
+  }
+
+  double getBezierValue(double time, int frame, int valueOffset, int i) {
+    final result = _bindings.spine_rgb2_timeline_get_bezier_value(_ptr, time, frame, valueOffset, i);
+    return result;
+  }
+
+  ArrayFloat get curves {
+    final result = _bindings.spine_rgb2_timeline_get_curves(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  int get frameEntries {
+    final result = _bindings.spine_rgb2_timeline_get_frame_entries(_ptr);
+    return result;
+  }
+
+  int get frameCount {
+    final result = _bindings.spine_rgb2_timeline_get_frame_count(_ptr);
+    return result;
+  }
+
+  ArrayFloat get frames {
+    final result = _bindings.spine_rgb2_timeline_get_frames(_ptr);
+    return ArrayFloat.fromPointer(result);
+  }
+
+  double get duration {
+    final result = _bindings.spine_rgb2_timeline_get_duration(_ptr);
+    return result;
+  }
+
+  ArrayPropertyId get propertyIds {
+    final result = _bindings.spine_rgb2_timeline_get_property_ids(_ptr);
+    return ArrayPropertyId.fromPointer(result);
+  }
+
+  int get slotIndex {
+    final result = _bindings.spine_rgb2_timeline_get_slot_index(_ptr);
+    return result;
+  }
+
+  set slotIndex(int value) {
+    _bindings.spine_rgb2_timeline_set_slot_index(_ptr, value);
+  }
+
+  static Rtti rttiStatic() {
+    final result = _bindings.spine_rgb2_timeline_rtti();
+    return Rtti.fromPointer(result);
+  }
+
+  void dispose() {
+    _bindings.spine_rgb2_timeline_dispose(_ptr);
+  }
+}

部分文件因文件數量過多而無法顯示