-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Fix spine callback issues #18672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix spine callback issues #18672
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,14 @@ static void animationCallback(AnimationState *state, EventType type, TrackEntry | |
| info.eventType = type; | ||
| info.event = event; | ||
| instance->animationEvents.add(info); | ||
|
|
||
| if (type == spine::EventType::EventType_Dispose) { | ||
| /** | ||
| * In the official implementation of Spine's AnimationState class, the animationCallback is invoked after the trackEntryCallback. | ||
| * After the AnimationState completes the EventType_Dispose callback, the TrackEntry will be reclaimed, so this event must be dispatched immediately. | ||
| */ | ||
| instance->dispatchEvents(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -37,12 +45,6 @@ static void trackEntryCallback(AnimationState *state, EventType type, TrackEntry | |
| info.eventType = type; | ||
| info.event = event; | ||
| instance->trackEvents.add(info); | ||
|
|
||
| if (type == EventType_Dispose) { | ||
| if (entry->getRendererObject()) { | ||
| entry->setRendererObject(nullptr); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -135,20 +137,7 @@ void SpineSkeletonInstance::updateAnimation(float dltTime) { | |
| _skeleton->update(dltTime); | ||
| _animState->update(dltTime); | ||
| _animState->apply(*_skeleton); | ||
| //Cache animation events then call back to JS. | ||
| auto vecAnimationEvents = animationEvents; | ||
| animationEvents.clear(); | ||
| //Cache track events then call back to JS. | ||
| auto vecTrackEvents = trackEvents; | ||
| trackEvents.clear(); | ||
| for (int i = 0; i < vecAnimationEvents.size(); i++) { | ||
| auto& info = vecAnimationEvents[i]; | ||
| onAnimationStateEvent(info.entry, info.eventType, info.event); | ||
| } | ||
| for (int i = 0; i < vecTrackEvents.size(); i++) { | ||
| auto& info = vecTrackEvents[i]; | ||
| onTrackEntryEvent(info.entry, info.eventType, info.event); | ||
| } | ||
| dispatchEvents(); | ||
| } | ||
|
|
||
| SpineModel *SpineSkeletonInstance::updateRenderData() { | ||
|
|
@@ -522,6 +511,7 @@ void SpineSkeletonInstance::onTrackEntryEvent(TrackEntry *entry, EventType type, | |
| SpineWasmUtil::s_currentEvent = event; | ||
| spineTrackListenerCallback(); | ||
| if (type == EventType_Dispose) { | ||
| entry->setRendererObject(nullptr); | ||
| _trackListenerSet.remove(entry); | ||
| } | ||
| } | ||
|
|
@@ -678,4 +668,27 @@ void SpineSkeletonInstance::setSlotTexture(const spine::String &slotName, const | |
| attachmentVertices->_textureUUID = textureUuid; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void SpineSkeletonInstance::dispatchEvents() { | ||
| spine::Vector<SpineEventInfo> vecAnimationEvents; | ||
| spine::Vector<SpineEventInfo> vecTrackEvents; | ||
| if (animationEvents.size() > 0) { | ||
| //Cache animation events then call back to JS. | ||
| vecAnimationEvents.addAll(animationEvents); | ||
| animationEvents.clear(); | ||
| } | ||
| if (trackEvents.size() > 0) { | ||
| //Cache track events then call back to JS. | ||
| vecTrackEvents.addAll(trackEvents); | ||
| trackEvents.clear(); | ||
| } | ||
| for (int i = 0; i < vecAnimationEvents.size(); i++) { | ||
| auto& info = vecAnimationEvents[i]; | ||
| onAnimationStateEvent(info.entry, info.eventType, info.event); | ||
| } | ||
| for (int i = 0; i < vecTrackEvents.size(); i++) { | ||
| auto& info = vecTrackEvents[i]; | ||
| onTrackEntryEvent(info.entry, info.eventType, info.event); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimize the code by checking whether the original vector is emtpy to avoid creating an empty vector and copying the empty vector. if (animationEvents.size() > 0) {
// Cache animation events then call back to JS.
auto vecAnimationEvents = animationEvents;
animationEvents.clear();
for (int i = 0; i < vecAnimationEvents.size(); i++) {
auto& info = vecAnimationEvents[i];
onAnimationStateEvent(info.entry, info.eventType, info.event);
}
}
if (trackEvents.size() > 0) {
// Cache track events then call back to JS.
auto vecTrackEvents = trackEvents;
trackEvents.clear();
for (int i = 0; i < vecTrackEvents.size(); i++) {
auto& info = vecTrackEvents[i];
onTrackEntryEvent(info.entry, info.eventType, info.event);
}
}
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please notice that So the copy assignment will use a default one which only assigns the buffer pointer and size. If so, we need to fix that for spine::Vector.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It seems to be fine that the assignment
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wrote a test case that could reproduce the issue I said, but yes, it's not relevant to this PR. {
spine::Vector<int> arr;
arr.add(1);
arr.add(2);
arr.add(3);
spine::Vector<int> arr2;
arr2 = arr; // --> call the default assignment operator
arr2[0] = 100;
printf("arr --------\n");
for (size_t i = 0; i < arr.size(); ++i) {
printf("%d, ", arr[i]);
}
printf("\n");
printf("arr2 --------\n");
for (size_t i = 0; i < arr2.size(); ++i) {
printf("%d, ", arr2[i]);
}
printf("\n");
printf("\n");
}The output is wrong:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I sent a PR to spine runtime official repo ( EsotericSoftware/spine-runtimes#2828 ) to fix the copy assignment issue.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, the assignment type of 'operator =' is not used by spine's module |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this cause other issues if something is done in the
disposecallback?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I Think that EventType_End disposeTrackEntry as same as EventType_Dispose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EventType_end event is cached by cacheAnimationEvent, while EventType_Dispose is dispatched it will dispatch EventType_end firstly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trackEntry will be enter _trackEntryPool only after EventType_dispose is dispatched. So, it should not cause other issues.