diff --git a/spine-flutter/example/lib/main.dart b/spine-flutter/example/lib/main.dart index 37303cdad..100b4a423 100644 --- a/spine-flutter/example/lib/main.dart +++ b/spine-flutter/example/lib/main.dart @@ -80,6 +80,7 @@ class AnimationStateEvents extends StatelessWidget { controller.skeleton?.setScaleX(0.5); controller.skeleton?.setScaleY(0.5); controller.skeleton?.findSlot("gun")?.setColor(Color(1, 0, 0, 1)); + controller.animationStateData?.setDefaultMix(0.2); controller.animationState?.setAnimation(0, "walk", true)?.setListener((type, trackEntry, event) { print("Walk animation event ${type}"); }); diff --git a/spine-flutter/lib/spine_flutter.dart b/spine-flutter/lib/spine_flutter.dart index ce05b6815..db767b623 100644 --- a/spine-flutter/lib/spine_flutter.dart +++ b/spine-flutter/lib/spine_flutter.dart @@ -2654,7 +2654,50 @@ class Event { typedef AnimationStateListener = void Function(EventType type, TrackEntry entry, Event? event); class AnimationStateData { - // FIXME + spine_animation_state_data _data; + + AnimationStateData._(this._data); + + 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); + } + + void setMixByName(String fromName, String toName, double duration) { + final fromNative = fromName.toNativeUtf8(); + final toNative = toName.toNativeUtf8(); + _bindings.spine_animation_state_data_set_mix_by_name(_data, fromNative.cast(), toNative.cast(), duration); + malloc.free(fromNative); + malloc.free(toNative); + } + + double getMixByName(String fromName, String toName) { + final fromNative = fromName.toNativeUtf8(); + final toNative = toName.toNativeUtf8(); + final duration = _bindings.spine_animation_state_data_get_mix_by_name(_data, fromNative.cast(), toNative.cast()); + malloc.free(fromNative); + malloc.free(toNative); + return duration; + } + + void setMix(Animation from, Animation to, double duration) { + _bindings.spine_animation_state_data_set_mix(_data, from._animation, to._animation, duration); + } + + double getMix(Animation from, Animation to) { + return _bindings.spine_animation_state_data_get_mix(_data, from._animation, to._animation); + } + + void clear() { + _bindings.spine_animation_state_data_clear(_data); + } } class AnimationState { @@ -2820,6 +2863,7 @@ class SkeletonDrawable { final SkeletonData skeletonData; late final Pointer _drawable; late final Skeleton skeleton; + late final AnimationStateData animationStateData; late final AnimationState animationState; final bool _ownsAtlasAndSkeletonData; bool _disposed; @@ -2827,6 +2871,7 @@ class SkeletonDrawable { SkeletonDrawable(this.atlas, this.skeletonData, this._ownsAtlasAndSkeletonData): _disposed = false { _drawable = _bindings.spine_skeleton_drawable_create(skeletonData._data); skeleton = Skeleton._(_drawable.ref.skeleton); + animationStateData = AnimationStateData._(_drawable.ref.animationStateData); animationState = AnimationState._(_drawable.ref.animationState, _drawable.ref.animationStateEvents); } diff --git a/spine-flutter/lib/spine_flutter_bindings_generated.dart b/spine-flutter/lib/spine_flutter_bindings_generated.dart index e67c218a8..8786b4ac8 100644 --- a/spine-flutter/lib/spine_flutter_bindings_generated.dart +++ b/spine-flutter/lib/spine_flutter_bindings_generated.dart @@ -873,6 +873,165 @@ class SpineFlutterBindings { late final _spine_animation_get_duration = _spine_animation_get_durationPtr .asFunction(); + spine_skeleton_data spine_animation_state_data_get_skeleton_data( + spine_animation_state_data stateData, + ) { + return _spine_animation_state_data_get_skeleton_data( + stateData, + ); + } + + late final _spine_animation_state_data_get_skeleton_dataPtr = _lookup< + ffi.NativeFunction< + spine_skeleton_data Function(spine_animation_state_data)>>( + 'spine_animation_state_data_get_skeleton_data'); + late final _spine_animation_state_data_get_skeleton_data = + _spine_animation_state_data_get_skeleton_dataPtr.asFunction< + spine_skeleton_data Function(spine_animation_state_data)>(); + + double spine_animation_state_data_get_default_mix( + spine_animation_state_data stateData, + ) { + return _spine_animation_state_data_get_default_mix( + stateData, + ); + } + + late final _spine_animation_state_data_get_default_mixPtr = _lookup< + ffi.NativeFunction>( + 'spine_animation_state_data_get_default_mix'); + late final _spine_animation_state_data_get_default_mix = + _spine_animation_state_data_get_default_mixPtr + .asFunction(); + + void spine_animation_state_data_set_default_mix( + spine_animation_state_data stateData, + double defaultMix, + ) { + return _spine_animation_state_data_set_default_mix( + stateData, + defaultMix, + ); + } + + late final _spine_animation_state_data_set_default_mixPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function(spine_animation_state_data, + ffi.Float)>>('spine_animation_state_data_set_default_mix'); + late final _spine_animation_state_data_set_default_mix = + _spine_animation_state_data_set_default_mixPtr + .asFunction(); + + void spine_animation_state_data_set_mix( + spine_animation_state_data stateData, + spine_animation from, + spine_animation to, + double duration, + ) { + return _spine_animation_state_data_set_mix( + stateData, + from, + to, + duration, + ); + } + + late final _spine_animation_state_data_set_mixPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + spine_animation_state_data, + spine_animation, + spine_animation, + ffi.Float)>>('spine_animation_state_data_set_mix'); + late final _spine_animation_state_data_set_mix = + _spine_animation_state_data_set_mixPtr.asFunction< + void Function(spine_animation_state_data, spine_animation, + spine_animation, double)>(); + + double spine_animation_state_data_get_mix( + spine_animation_state_data stateData, + spine_animation from, + spine_animation to, + ) { + return _spine_animation_state_data_get_mix( + stateData, + from, + to, + ); + } + + late final _spine_animation_state_data_get_mixPtr = _lookup< + ffi.NativeFunction< + ffi.Float Function(spine_animation_state_data, spine_animation, + spine_animation)>>('spine_animation_state_data_get_mix'); + late final _spine_animation_state_data_get_mix = + _spine_animation_state_data_get_mixPtr.asFunction< + double Function( + spine_animation_state_data, spine_animation, spine_animation)>(); + + void spine_animation_state_data_set_mix_by_name( + spine_animation_state_data stateData, + ffi.Pointer fromName, + ffi.Pointer toName, + double duration, + ) { + return _spine_animation_state_data_set_mix_by_name( + stateData, + fromName, + toName, + duration, + ); + } + + late final _spine_animation_state_data_set_mix_by_namePtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + spine_animation_state_data, + ffi.Pointer, + ffi.Pointer, + ffi.Float)>>('spine_animation_state_data_set_mix_by_name'); + late final _spine_animation_state_data_set_mix_by_name = + _spine_animation_state_data_set_mix_by_namePtr.asFunction< + void Function(spine_animation_state_data, ffi.Pointer, + ffi.Pointer, double)>(); + + double spine_animation_state_data_get_mix_by_name( + spine_animation_state_data stateData, + ffi.Pointer fromName, + ffi.Pointer toName, + ) { + return _spine_animation_state_data_get_mix_by_name( + stateData, + fromName, + toName, + ); + } + + late final _spine_animation_state_data_get_mix_by_namePtr = _lookup< + ffi.NativeFunction< + ffi.Float Function(spine_animation_state_data, + ffi.Pointer, ffi.Pointer)>>( + 'spine_animation_state_data_get_mix_by_name'); + late final _spine_animation_state_data_get_mix_by_name = + _spine_animation_state_data_get_mix_by_namePtr.asFunction< + double Function(spine_animation_state_data, ffi.Pointer, + ffi.Pointer)>(); + + void spine_animation_state_data_clear( + spine_animation_state_data stateData, + ) { + return _spine_animation_state_data_clear( + stateData, + ); + } + + late final _spine_animation_state_data_clearPtr = _lookup< + ffi.NativeFunction>( + 'spine_animation_state_data_clear'); + late final _spine_animation_state_data_clear = + _spine_animation_state_data_clearPtr + .asFunction(); + void spine_animation_state_update( spine_animation_state state, double delta, @@ -8338,6 +8497,8 @@ class spine_path_constraint_data_wrapper extends ffi.Opaque {} class spine_animation_state_wrapper extends ffi.Opaque {} +class spine_animation_state_data_wrapper extends ffi.Opaque {} + class spine_animation_state_events_wrapper extends ffi.Opaque {} class spine_event_wrapper extends ffi.Opaque {} @@ -8496,6 +8657,8 @@ class spine_skeleton_drawable extends ffi.Struct { external spine_animation_state animationState; + external spine_animation_state_data animationStateData; + external spine_animation_state_events animationStateEvents; external ffi.Pointer clipping; @@ -8505,6 +8668,8 @@ class spine_skeleton_drawable extends ffi.Struct { typedef spine_skeleton = ffi.Pointer; typedef spine_animation_state = ffi.Pointer; +typedef spine_animation_state_data + = ffi.Pointer; typedef spine_animation_state_events = ffi.Pointer; diff --git a/spine-flutter/lib/spine_widget.dart b/spine-flutter/lib/spine_widget.dart index 56f8136b9..3decf9a62 100644 --- a/spine-flutter/lib/spine_widget.dart +++ b/spine-flutter/lib/spine_widget.dart @@ -29,6 +29,7 @@ class SpineWidgetController { Atlas? get atlas => _atlas; SkeletonData? get skeletonData => _data; + AnimationStateData? get animationStateData => _drawable?.animationStateData; AnimationState? get animationState => _drawable?.animationState; Skeleton? get skeleton => _drawable?.skeleton; } diff --git a/spine-flutter/src/spine_flutter.cpp b/spine-flutter/src/spine_flutter.cpp index 81b191ccb..552281091 100644 --- a/spine-flutter/src/spine_flutter.cpp +++ b/spine-flutter/src/spine_flutter.cpp @@ -370,7 +370,9 @@ void spine_render_command_dispose(spine_render_command *cmd) { FFI_PLUGIN_EXPORT spine_skeleton_drawable *spine_skeleton_drawable_create(spine_skeleton_data skeletonData) { spine_skeleton_drawable *drawable = SpineExtension::calloc(1, __FILE__, __LINE__); drawable->skeleton = (spine_skeleton)new (__FILE__, __LINE__) Skeleton((SkeletonData*)skeletonData); - AnimationState *state = new (__FILE__, __LINE__) AnimationState(new AnimationStateData((SkeletonData*)skeletonData)); + AnimationStateData *stateData = new (__FILE__, __LINE__) AnimationStateData((SkeletonData*)skeletonData); + drawable->animationStateData = (spine_animation_state_data)stateData; + AnimationState *state = new (__FILE__, __LINE__) AnimationState(stateData); drawable->animationState = (spine_animation_state)state; state->setManualTrackEntryDisposal(true); EventListener *listener = new EventListener(); @@ -383,11 +385,8 @@ FFI_PLUGIN_EXPORT spine_skeleton_drawable *spine_skeleton_drawable_create(spine_ FFI_PLUGIN_EXPORT void spine_skeleton_drawable_dispose(spine_skeleton_drawable *drawable) { if (!drawable) return; if (drawable->skeleton) delete (Skeleton*)drawable->skeleton; - if (drawable->animationState) { - AnimationState *state = (AnimationState*)drawable->animationState; - delete state->getData(); - delete (AnimationState*)state; - } + if (drawable->animationState) delete (AnimationState*)drawable->animationState; + if (drawable->animationStateData) delete (AnimationStateData*)drawable->animationStateData; if (drawable->animationStateEvents) delete (Vector*)(drawable->animationStateEvents); if (drawable->clipping) delete (SkeletonClipping*)drawable->clipping; while (drawable->renderCommand) { @@ -532,8 +531,62 @@ FFI_PLUGIN_EXPORT float spine_animation_get_duration(spine_animation animation) return _animation->getDuration(); } -// AnimationState +// AnimationStateData +FFI_PLUGIN_EXPORT spine_skeleton_data spine_animation_state_data_get_skeleton_data(spine_animation_state_data stateData) { + if (stateData == nullptr) return nullptr; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + return (spine_skeleton_data)_stateData->getSkeletonData(); +} +FFI_PLUGIN_EXPORT float spine_animation_state_data_get_default_mix(spine_animation_state_data stateData) { + if (stateData == nullptr) return 0; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + return _stateData->getDefaultMix(); +} + +FFI_PLUGIN_EXPORT void spine_animation_state_data_set_default_mix(spine_animation_state_data stateData, float defaultMix) { + if (stateData == nullptr) return; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + _stateData->setDefaultMix(defaultMix); +} + +FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to, float duration) { + if (stateData == nullptr) return; + if (from == nullptr || to == nullptr) return; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + _stateData->setMix((Animation*)from, (Animation*)to, duration); +} + +FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to) { + if (stateData == nullptr) return 0; + if (from == nullptr || to == nullptr) return 0; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + return _stateData->getMix((Animation*)from, (Animation*)to); +} + +FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix_by_name(spine_animation_state_data stateData, const char* fromName, const char* toName, float duration) { + if (stateData == nullptr) return; + if (fromName == nullptr || toName == nullptr) return; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + _stateData->setMix(fromName, toName, duration); +} + +FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix_by_name(spine_animation_state_data stateData, const char* fromName, const char* toName) { + if (stateData == nullptr) return 0; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + Animation* from = _stateData->getSkeletonData()->findAnimation(fromName); + Animation* to = _stateData->getSkeletonData()->findAnimation(toName); + if (from == nullptr || to == nullptr) return 0; + return _stateData->getMix(from, to); +} + +FFI_PLUGIN_EXPORT void spine_animation_state_data_clear(spine_animation_state_data stateData) { + if (stateData == nullptr) return ; + AnimationStateData* _stateData = (AnimationStateData*)stateData; + _stateData->clear(); +} + +// AnimationState FFI_PLUGIN_EXPORT void spine_animation_state_update(spine_animation_state state, float delta) { if (state == nullptr) return; AnimationState *_state = (AnimationState*)state; diff --git a/spine-flutter/src/spine_flutter.h b/spine-flutter/src/spine_flutter.h index 500dcb420..3e8201a65 100644 --- a/spine-flutter/src/spine_flutter.h +++ b/spine-flutter/src/spine_flutter.h @@ -53,6 +53,7 @@ SPINE_OPAQUE_TYPE(spine_transform_constraint_data) SPINE_OPAQUE_TYPE(spine_path_constraint) SPINE_OPAQUE_TYPE(spine_path_constraint_data) SPINE_OPAQUE_TYPE(spine_animation_state) +SPINE_OPAQUE_TYPE(spine_animation_state_data) SPINE_OPAQUE_TYPE(spine_animation_state_events) SPINE_OPAQUE_TYPE(spine_event) SPINE_OPAQUE_TYPE(spine_event_data) @@ -162,6 +163,7 @@ typedef struct spine_vector { typedef struct spine_skeleton_drawable { spine_skeleton skeleton; spine_animation_state animationState; + spine_animation_state_data animationStateData; spine_animation_state_events animationStateEvents; void *clipping; spine_render_command *renderCommand; @@ -236,6 +238,15 @@ FFI_PLUGIN_EXPORT void spine_skeleton_drawable_dispose(spine_skeleton_drawable * FFI_PLUGIN_EXPORT const char* spine_animation_get_name(spine_animation animation); FFI_PLUGIN_EXPORT float spine_animation_get_duration(spine_animation animation); +FFI_PLUGIN_EXPORT spine_skeleton_data spine_animation_state_data_get_skeleton_data(spine_animation_state_data stateData); +FFI_PLUGIN_EXPORT float spine_animation_state_data_get_default_mix(spine_animation_state_data stateData); +FFI_PLUGIN_EXPORT void spine_animation_state_data_set_default_mix(spine_animation_state_data stateData, float defaultMix); +FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to, float duration); +FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix(spine_animation_state_data stateData, spine_animation from, spine_animation to); +FFI_PLUGIN_EXPORT void spine_animation_state_data_set_mix_by_name(spine_animation_state_data stateData, const char* fromName, const char* toName, float duration); +FFI_PLUGIN_EXPORT float spine_animation_state_data_get_mix_by_name(spine_animation_state_data stateData, const char* fromName, const char* toName); +FFI_PLUGIN_EXPORT void spine_animation_state_data_clear(spine_animation_state_data stateData); + FFI_PLUGIN_EXPORT void spine_animation_state_update(spine_animation_state state, float delta); FFI_PLUGIN_EXPORT void spine_animation_state_dispose_track_entry(spine_animation_state state, spine_track_entry entry); FFI_PLUGIN_EXPORT void spine_animation_state_apply(spine_animation_state state, spine_skeleton skeleton);