[cpp][flutter] Add setter to AnimationState for manual track entry disposal, add support for track entry and state listeners on dart side.

This commit is contained in:
Mario Zechner 2022-08-29 13:46:39 +02:00
parent cde9519a00
commit 61560c9477
7 changed files with 134 additions and 11 deletions

View File

@ -45,7 +45,7 @@
namespace spine {
enum EventType {
EventType_Start,
EventType_Start = 0,
EventType_Interrupt,
EventType_End,
EventType_Complete,
@ -429,6 +429,12 @@ namespace spine {
void enableQueue();
void setManualTrackEntryDisposal(bool inValue);
bool getManualTrackEntryDisposal();
void disposeTrackEntry(TrackEntry *entry);
private:
static const int Subsequent = 0;
static const int First = 1;
@ -456,6 +462,8 @@ namespace spine {
float _timeScale;
bool _manualTrackEntryDisposal;
static Animation *getEmptyAnimation();
static void

View File

@ -295,8 +295,7 @@ void EventQueue::drain() {
else
state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL);
trackEntry->reset();
_trackEntryPool.free(trackEntry);
if (!_state.getManualTrackEntryDisposal()) _state.disposeTrackEntry(trackEntry);
break;
case EventType_Event:
if (!trackEntry->_listenerObject)
@ -320,7 +319,8 @@ AnimationState::AnimationState(AnimationStateData *data) : _data(data),
_listener(dummyOnAnimationEventFunc),
_listenerObject(NULL),
_unkeyedState(0),
_timeScale(1) {
_timeScale(1),
_manualTrackEntryDisposal(false) {
}
AnimationState::~AnimationState() {
@ -666,6 +666,19 @@ void AnimationState::enableQueue() {
_queue->_drainDisabled = false;
}
void AnimationState::setManualTrackEntryDisposal(bool inValue) {
_manualTrackEntryDisposal = inValue;
}
bool AnimationState::getManualTrackEntryDisposal() {
return _manualTrackEntryDisposal;
}
void AnimationState::disposeTrackEntry(TrackEntry *entry) {
entry->reset();
_trackEntryPool.free(entry);
}
Animation *AnimationState::getEmptyAnimation() {
static Vector<Timeline *> timelines;
static Animation ret(String("<empty>"), timelines, 0);

View File

@ -64,6 +64,7 @@ class AnimationStateEvents extends StatelessWidget {
@override
Widget build(BuildContext context) {
reportLeaks();
final controller = SpineWidgetController((controller) {
for (final bone in controller.skeleton!.getBones()) {
print(bone);
@ -71,7 +72,12 @@ class AnimationStateEvents extends StatelessWidget {
controller.skeleton?.setScaleX(0.5);
controller.skeleton?.setScaleY(0.5);
controller.skeleton?.setColor(Color(1, 1, 0, 1));
final trackEntry = controller.animationState?.setAnimation(0, "walk", true);
controller.animationState?.setAnimation(0, "walk", true)?.setListener((event) {
print("Walk animation event ${event.type}");
});
controller.animationState?.addAnimation(0, "run", true, 2)?.setListener((event) {
print("Run animation event ${event.type}");
});
});
return Scaffold(

View File

@ -708,15 +708,48 @@ class TrackEntry {
double getTrackComplete() {
return _bindings.spine_track_entry_get_track_complete(_entry);
}
void setListener(AnimationStateListener listener) {
_state._setTrackEntryListener(_entry, listener);
}
}
enum EventType {
Start,
Interrupt,
End,
Complete,
Dispose,
Event
}
class Event {
final spine_event _event;
Event(this._event);
}
class AnimationStateEvent {
final EventType type;
final TrackEntry entry;
final Event? event;
AnimationStateEvent(this.type, this.entry, this.event);
}
typedef AnimationStateListener = void Function(AnimationStateEvent event);
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);
AnimationState(this._state, this._events): _trackEntryListeners = {};
// FIXME add listener methods
void _setTrackEntryListener(spine_track_entry entry, AnimationStateListener listener) {
_trackEntryListeners[entry] = listener;
}
/// Increments the track entry times, setting queued animations as current if needed
/// @param delta delta time
@ -724,7 +757,43 @@ class AnimationState {
_bindings.spine_animation_state_update(_state, delta);
final numEvents = _bindings.spine_animation_state_events_get_num_events(_events);
print("events: $numEvents");
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 entry = _bindings.spine_animation_state_events_get_track_entry(_events, i);
final nativeEvent = _bindings.spine_animation_state_events_get_event(_events, i);
final event = AnimationStateEvent(type, TrackEntry(entry, this), nativeEvent.address == nullptr.address ? null : Event(nativeEvent));
if (_trackEntryListeners.containsKey(entry)) {
_trackEntryListeners[entry]?.call(event);
}
if (_stateListener != null) {
_stateListener?.call(event);
}
if (type == EventType.Dispose) {
_bindings.spine_animation_state_dispose_track_entry(_state, entry);
}
}
}
_bindings.spine_animation_state_events_reset(_events);
}

View File

@ -205,6 +205,24 @@ class SpineFlutterBindings {
late final _spine_animation_state_update = _spine_animation_state_updatePtr
.asFunction<void Function(spine_animation_state, double)>();
void spine_animation_state_dispose_track_entry(
spine_animation_state state,
spine_track_entry entry,
) {
return _spine_animation_state_dispose_track_entry(
state,
entry,
);
}
late final _spine_animation_state_dispose_track_entryPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(spine_animation_state,
spine_track_entry)>>('spine_animation_state_dispose_track_entry');
late final _spine_animation_state_dispose_track_entry =
_spine_animation_state_dispose_track_entryPtr.asFunction<
void Function(spine_animation_state, spine_track_entry)>();
void spine_animation_state_apply(
spine_animation_state state,
spine_skeleton skeleton,

View File

@ -125,6 +125,7 @@ FFI_PLUGIN_EXPORT spine_skeleton_drawable *spine_skeleton_drawable_create(spine_
drawable->skeleton = new Skeleton((SkeletonData*)skeletonData);
AnimationState *state = new AnimationState(new AnimationStateData((SkeletonData*)skeletonData));
drawable->animationState = state;
state->setManualTrackEntryDisposal(true);
EventListener *listener = new EventListener();
drawable->animationStateEvents = listener;
state->setListener(listener);
@ -276,6 +277,13 @@ FFI_PLUGIN_EXPORT void spine_animation_state_update(spine_animation_state state,
_state->update(delta);
}
FFI_PLUGIN_EXPORT void spine_animation_state_dispose_track_entry(spine_animation_state state, spine_track_entry entry) {
if (state == nullptr) return;
if (entry == nullptr) return;
AnimationState *_state = (AnimationState*)state;
_state->disposeTrackEntry((TrackEntry*)entry);
}
FFI_PLUGIN_EXPORT void spine_animation_state_apply(spine_animation_state state, spine_skeleton skeleton) {
if (state == nullptr) return;
AnimationState *_state = (AnimationState*)state;
@ -352,21 +360,21 @@ FFI_PLUGIN_EXPORT spine_event_type spine_animation_state_events_get_event_type(s
if (events == nullptr) return SPINE_EVENT_TYPE_DISPOSE;
if (index < 0) return SPINE_EVENT_TYPE_DISPOSE;
EventListener *_events = (EventListener*)events;
if (_events->events.size() >= index) return SPINE_EVENT_TYPE_DISPOSE;
if (index >= _events->events.size()) return SPINE_EVENT_TYPE_DISPOSE;
return (spine_event_type)_events->events[index].type;
}
FFI_PLUGIN_EXPORT spine_track_entry spine_animation_state_events_get_track_entry(spine_animation_state_events events, int index) {
if (events == nullptr) return nullptr;
EventListener *_events = (EventListener*)events;
if (_events->events.size() >= index) return nullptr;
if (index >= _events->events.size()) return nullptr;
return (spine_track_entry)_events->events[index].entry;
}
FFI_PLUGIN_EXPORT spine_event spine_animation_state_events_get_event(spine_animation_state_events events, int index) {
if (events == nullptr) return nullptr;
EventListener *_events = (EventListener*)events;
if (_events->events.size() >= index) return nullptr;
if (index >= _events->events.size()) return nullptr;
return (spine_track_entry)_events->events[index].entry;
}

View File

@ -123,6 +123,7 @@ FFI_PLUGIN_EXPORT spine_render_command *spine_skeleton_drawable_render(spine_ske
FFI_PLUGIN_EXPORT void spine_skeleton_drawable_dispose(spine_skeleton_drawable *drawable);
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);
FFI_PLUGIN_EXPORT void spine_animation_state_clear_tracks(spine_animation_state state);
FFI_PLUGIN_EXPORT void spine_animation_state_clear_track(spine_animation_state state, int trackIndex);