import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'generated/atlas.dart'; import 'generated/skeleton_data.dart'; import 'spine_bindings.dart'; // Atlas Extensions extension AtlasExtensions on Atlas { /// Creates an Atlas from atlas data string (without loading images) static Atlas fromString(String atlasData) { final atlasDataNative = atlasData.toNativeUtf8(); final atlasPtr = SpineBindings.bindings.spine_atlas_load(atlasDataNative.cast()); malloc.free(atlasDataNative); return Atlas.fromPointer(atlasPtr); } /// Dispose the atlas and free its memory void dispose() { SpineBindings.bindings.spine_atlas_dispose(nativePtr.cast()); } } // Skeleton Data Result wrapper class SkeletonDataResult { final String? error; final SkeletonData? skeletonData; final Pointer? _resultPtr; SkeletonDataResult._(this.error, this.skeletonData, this._resultPtr); void dispose() { if (_resultPtr != null) { SpineBindings.bindings.spine_skeleton_data_result_dispose(_resultPtr!.cast()); } } } // Skeleton Data Extensions extension SkeletonDataExtensions on SkeletonData { /// Load skeleton data from JSON string static SkeletonData fromJson(Atlas atlas, String jsonData, {String? path}) { final jsonDataNative = jsonData.toNativeUtf8(); final pathNative = (path ?? '').toNativeUtf8(); final resultPtr = SpineBindings.bindings .spine_skeleton_data_load_json(atlas.nativePtr.cast(), jsonDataNative.cast(), pathNative.cast()); malloc.free(jsonDataNative); malloc.free(pathNative); // Check for error final errorPtr = SpineBindings.bindings.spine_skeleton_data_result_get_error(resultPtr.cast()); if (errorPtr != nullptr) { final error = errorPtr.cast().toDartString(); SpineBindings.bindings.spine_skeleton_data_result_dispose(resultPtr.cast()); throw Exception("Couldn't load skeleton data: $error"); } // Get skeleton data final skeletonDataPtr = SpineBindings.bindings.spine_skeleton_data_result_get_data(resultPtr.cast()); final skeletonData = SkeletonData.fromPointer(skeletonDataPtr); SpineBindings.bindings.spine_skeleton_data_result_dispose(resultPtr.cast()); return skeletonData; } }