Skip to content

Commit ddd45f9

Browse files
authored
Fix spine can not be paused while working at realTime mode (#16672)
* Fix spine can not be paused while running in realTime mode
1 parent 288a149 commit ddd45f9

10 files changed

Lines changed: 53 additions & 104 deletions

cocos/spine/lib/spine-core.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,7 @@ declare namespace spine {
11911191
isDelete: boolean;
11921192
enable: boolean;
11931193
setTrackEntryListener: any;
1194+
destroy();
11941195
initSkeleton(data: SkeletonData);
11951196
getAnimationState();
11961197
setAnimation(trackIndex: number, name: string, loop: boolean): spine.TrackEntry | null;

cocos/spine/skeleton-cache.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export interface AnimationFrame {
7676
}
7777

7878
export class AnimationCache {
79-
protected _instance: spine.SkeletonInstance = null!;
79+
protected _instance: spine.SkeletonInstance | null = null;
8080
protected _state: spine.AnimationState = null!;
8181
protected _skeletonData: spine.SkeletonData = null!;
8282
protected _skeleton: spine.Skeleton = null!;
@@ -117,7 +117,7 @@ export class AnimationCache {
117117

118118
public setSkin (skinName: string): void {
119119
if (this._skeleton) this._skeleton.setSkinByName(skinName);
120-
this._instance.setSkin(skinName);
120+
this._instance!.setSkin(skinName);
121121
}
122122

123123
public setAnimation (animationName: string): void {
@@ -134,7 +134,7 @@ export class AnimationCache {
134134
}
135135
this._maxFrameIdex = Math.floor((animation as any).duration / FrameTime);
136136
if (this._maxFrameIdex <= 0) this._maxFrameIdex = 1;
137-
this._instance.setAnimation(0, animationName, false);
137+
this._instance!.setAnimation(0, animationName, false);
138138
}
139139

140140
public updateToFrame (frameIdx: number): void {
@@ -145,8 +145,8 @@ export class AnimationCache {
145145
// Solid update frame rate 1/60.
146146
this._frameIdx++;
147147
this.totalTime += FrameTime;
148-
this._instance.updateAnimation(FrameTime);
149-
const model = this._instance.updateRenderData();
148+
this._instance!.updateAnimation(FrameTime);
149+
const model = this._instance!.updateRenderData();
150150
this.updateRenderData(this._frameIdx, model);
151151
if (this._frameIdx >= this._maxFrameIdex) {
152152
this.isCompleted = true;
@@ -234,7 +234,7 @@ export class AnimationCache {
234234
}
235235
}
236236
const listener = skeletonInfo?.listener;
237-
this._instance.setAnimation(0, this._animationName!, false);
237+
this._instance!.setAnimation(0, this._animationName!, false);
238238
this.bind(listener!);
239239

240240
// record cur animation cache
@@ -302,7 +302,10 @@ export class AnimationCache {
302302
}
303303

304304
public destroy (): void {
305-
spine.SkeletonSystem.destroySpineInstance(this._instance);
305+
if (this._instance) {
306+
this._instance.destroy();
307+
this._instance = null;
308+
}
306309
}
307310
}
308311

cocos/spine/skeleton-system.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ export class SkeletonSystem extends System {
7878
if (!this._skeletons) {
7979
return;
8080
}
81-
if (!EDITOR_NOT_IN_PREVIEW && !JSB) spine.SkeletonSystem.updateAnimation(dt);
8281
this._skeletons.forEach((skeleton) => {
8382
skeleton.updateAnimation(dt);
8483
});

cocos/spine/skeleton.ts

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ export class Skeleton extends UIRenderer {
237237

238238
protected _runtimeData: spine.SkeletonData | null = null;
239239
public _skeleton: spine.Skeleton = null!;
240-
protected _instance: spine.SkeletonInstance = null!;
240+
protected _instance: spine.SkeletonInstance | null = null;
241241
protected _state: spine.AnimationState = null!;
242242
protected _textures: Texture2D[] = [];
243243
private _skeletonInfo: SkeletonCacheItemInfo | null = null;
@@ -491,7 +491,7 @@ export class Skeleton extends UIRenderer {
491491
set premultipliedAlpha (v: boolean) {
492492
if (v !== this._premultipliedAlpha) {
493493
this._premultipliedAlpha = v;
494-
this._instance.setPremultipliedAlpha(v);
494+
this._instance!.setPremultipliedAlpha(v);
495495
this.markForUpdateRenderData();
496496
}
497497
}
@@ -710,8 +710,9 @@ export class Skeleton extends UIRenderer {
710710
//if (this._cacheMode == AnimationCacheMode.PRIVATE_CACHE) this._animCache?.destroy();
711711
this._animCache = null;
712712
SkeletonSystem.getInstance().remove(this);
713-
if (!JSB) {
714-
spine.SkeletonSystem.destroySpineInstance(this._instance);
713+
if (!JSB && this._instance) {
714+
this._instance.destroy();
715+
this._instance = null;
715716
}
716717
this._destroySkeletonInfo(this._skeletonCache);
717718
this._skeletonCache = null;
@@ -812,9 +813,9 @@ export class Skeleton extends UIRenderer {
812813
this._skeleton = this._skeletonInfo.skeleton!;
813814
}
814815
} else {
815-
this._skeleton = this._instance.initSkeleton(skeletonData);
816-
this._state = this._instance.getAnimationState();
817-
this._instance.setPremultipliedAlpha(this._premultipliedAlpha);
816+
this._skeleton = this._instance!.initSkeleton(skeletonData);
817+
this._state = this._instance!.getAnimationState();
818+
this._instance!.setPremultipliedAlpha(this._premultipliedAlpha);
818819
}
819820
// Recreate render data and mark dirty
820821
this._flushAssembler();
@@ -929,7 +930,7 @@ export class Skeleton extends UIRenderer {
929930
}
930931
} else {
931932
this._animationName = name;
932-
trackEntry = this._instance.setAnimation(trackIndex, name, loop);
933+
trackEntry = this._instance!.setAnimation(trackIndex, name, loop);
933934
}
934935
this.markForUpdateRenderData();
935936
return trackEntry;
@@ -1007,7 +1008,7 @@ export class Skeleton extends UIRenderer {
10071008
*/
10081009
public setSkin (name: string): void {
10091010
if (this._skeleton) this._skeleton.setSkinByName(name);
1010-
this._instance.setSkin(name);
1011+
this._instance!.setSkin(name);
10111012
if (this.isAnimationCached()) {
10121013
if (this._animCache) {
10131014
this._animCache.setSkin(name);
@@ -1050,6 +1051,8 @@ export class Skeleton extends UIRenderer {
10501051
return;
10511052
}
10521053
this._updateCache(dt);
1054+
} else {
1055+
this._instance!.updateAnimation(dt);
10531056
}
10541057
}
10551058

@@ -1112,7 +1115,7 @@ export class Skeleton extends UIRenderer {
11121115
const model = this._curFrame.model;
11131116
return model;
11141117
} else {
1115-
const model = this._instance.updateRenderData();
1118+
const model = this._instance!.updateRenderData();
11161119
return model;
11171120
}
11181121
}
@@ -1444,7 +1447,7 @@ export class Skeleton extends UIRenderer {
14441447
return;
14451448
}
14461449
if (this._state) {
1447-
this._instance.setMix(fromAnimation, toAnimation, duration);
1450+
this._instance!.setMix(fromAnimation, toAnimation, duration);
14481451
//this._state.data.setMix(fromAnimation, toAnimation, duration);
14491452
}
14501453
}
@@ -1577,7 +1580,7 @@ export class Skeleton extends UIRenderer {
15771580
this.destroyRenderData();
15781581
if (!JSB) {
15791582
if (!this.isAnimationCached()) {
1580-
this._instance.setUseTint(this._useTint);
1583+
this._instance!.setUseTint(this._useTint);
15811584
}
15821585
}
15831586
if (this._assembler && this._skeleton) {
@@ -1607,7 +1610,7 @@ export class Skeleton extends UIRenderer {
16071610
if (this.isAnimationCached()) {
16081611
warn('Debug bones or slots is invalid in cached mode');
16091612
} else if (!JSB) {
1610-
this._instance.setDebugMode(true);
1613+
this._instance!.setDebugMode(true);
16111614
}
16121615
} else if (this._debugRenderer) {
16131616
this._debugRenderer.node.destroy();
@@ -1655,7 +1658,7 @@ export class Skeleton extends UIRenderer {
16551658
const r = this._color.r / 255.0;
16561659
const g = this._color.g / 255.0;
16571660
const b = this._color.b / 255.0;
1658-
this._instance.setColor(r, g, b, a);
1661+
this._instance!.setColor(r, g, b, a);
16591662
}
16601663

16611664
/**
@@ -1664,6 +1667,9 @@ export class Skeleton extends UIRenderer {
16641667
* @param effectDelegate @en Vertex effect delegate. @zh 顶点特效代理。
16651668
*/
16661669
public setVertexEffectDelegate (effectDelegate: VertexEffectDelegate | null | undefined): void {
1670+
if (!this._instance) {
1671+
return;
1672+
}
16671673
if (!effectDelegate) {
16681674
this._instance.clearEffect();
16691675
return;
@@ -1692,7 +1698,7 @@ export class Skeleton extends UIRenderer {
16921698
public setStartListener (listener: TrackListener): void {
16931699
this._ensureListener();
16941700
const listenerID = TrackEntryListeners.addListener(listener);
1695-
this._instance.setListener(listenerID, spine.EventType.start);
1701+
this._instance!.setListener(listenerID, spine.EventType.start);
16961702
this._listener!.start = listener;
16971703
}
16981704

@@ -1704,7 +1710,7 @@ export class Skeleton extends UIRenderer {
17041710
public setInterruptListener (listener: TrackListener): void {
17051711
this._ensureListener();
17061712
const listenerID = TrackEntryListeners.addListener(listener);
1707-
this._instance.setListener(listenerID, spine.EventType.interrupt);
1713+
this._instance!.setListener(listenerID, spine.EventType.interrupt);
17081714
this._listener!.interrupt = listener;
17091715
}
17101716

@@ -1716,7 +1722,7 @@ export class Skeleton extends UIRenderer {
17161722
public setEndListener (listener: TrackListener): void {
17171723
this._ensureListener();
17181724
const listenerID = TrackEntryListeners.addListener(listener);
1719-
this._instance.setListener(listenerID, spine.EventType.end);
1725+
this._instance!.setListener(listenerID, spine.EventType.end);
17201726
this._listener!.end = listener;
17211727
}
17221728

@@ -1728,7 +1734,7 @@ export class Skeleton extends UIRenderer {
17281734
public setDisposeListener (listener: TrackListener): void {
17291735
this._ensureListener();
17301736
const listenerID = TrackEntryListeners.addListener(listener);
1731-
this._instance.setListener(listenerID, spine.EventType.dispose);
1737+
this._instance!.setListener(listenerID, spine.EventType.dispose);
17321738
this._listener!.dispose = listener;
17331739
}
17341740

@@ -1740,7 +1746,7 @@ export class Skeleton extends UIRenderer {
17401746
public setCompleteListener (listener: TrackListener): void {
17411747
this._ensureListener();
17421748
const listenerID = TrackEntryListeners.addListener(listener);
1743-
this._instance.setListener(listenerID, spine.EventType.complete);
1749+
this._instance!.setListener(listenerID, spine.EventType.complete);
17441750
this._listener!.complete = listener;
17451751
}
17461752

@@ -1752,7 +1758,7 @@ export class Skeleton extends UIRenderer {
17521758
public setEventListener (listener: TrackListener2): void {
17531759
this._ensureListener();
17541760
const listenerID = TrackEntryListeners.addListener(listener);
1755-
this._instance.setListener(listenerID, spine.EventType.event);
1761+
this._instance!.setListener(listenerID, spine.EventType.event);
17561762
this._listener!.event = listener;
17571763
}
17581764

@@ -1763,7 +1769,7 @@ export class Skeleton extends UIRenderer {
17631769
* @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。
17641770
*/
17651771
public setTrackStartListener (entry: spine.TrackEntry, listener: TrackListener): void {
1766-
TrackEntryListeners.getListeners(entry, this._instance).start = listener;
1772+
TrackEntryListeners.getListeners(entry, this._instance!).start = listener;
17671773
}
17681774

17691775
/**
@@ -1773,7 +1779,7 @@ export class Skeleton extends UIRenderer {
17731779
* @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。
17741780
*/
17751781
public setTrackInterruptListener (entry: spine.TrackEntry, listener: TrackListener): void {
1776-
TrackEntryListeners.getListeners(entry, this._instance).interrupt = listener;
1782+
TrackEntryListeners.getListeners(entry, this._instance!).interrupt = listener;
17771783
}
17781784

17791785
/**
@@ -1783,7 +1789,7 @@ export class Skeleton extends UIRenderer {
17831789
* @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。
17841790
*/
17851791
public setTrackEndListener (entry: spine.TrackEntry, listener: TrackListener): void {
1786-
TrackEntryListeners.getListeners(entry, this._instance).end = listener;
1792+
TrackEntryListeners.getListeners(entry, this._instance!).end = listener;
17871793
}
17881794

17891795
/**
@@ -1793,7 +1799,7 @@ export class Skeleton extends UIRenderer {
17931799
* @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。
17941800
*/
17951801
public setTrackDisposeListener (entry: spine.TrackEntry, listener: TrackListener): void {
1796-
TrackEntryListeners.getListeners(entry, this._instance).dispose = listener;
1802+
TrackEntryListeners.getListeners(entry, this._instance!).dispose = listener;
17971803
}
17981804

17991805
/**
@@ -1810,7 +1816,7 @@ export class Skeleton extends UIRenderer {
18101816
// this._instance.setListener(listenerID, spine.EventType.event);
18111817
// this._listener!.event = listener;
18121818
};
1813-
TrackEntryListeners.getListeners(entry, this._instance).complete = onComplete;
1819+
TrackEntryListeners.getListeners(entry, this._instance!).complete = onComplete;
18141820
}
18151821

18161822
/**
@@ -1820,14 +1826,14 @@ export class Skeleton extends UIRenderer {
18201826
* @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。
18211827
*/
18221828
public setTrackEventListener (entry: spine.TrackEntry, listener: TrackListener|TrackListener2): void {
1823-
TrackEntryListeners.getListeners(entry, this._instance).event = listener;
1829+
TrackEntryListeners.getListeners(entry, this._instance!).event = listener;
18241830
}
18251831

18261832
/**
18271833
* @engineInternal
18281834
*/
18291835
public getDebugShapes (): any {
1830-
return this._instance.getDebugShapes();
1836+
return this._instance!.getDebugShapes();
18311837
}
18321838

18331839
/**
@@ -1852,7 +1858,7 @@ export class Skeleton extends UIRenderer {
18521858
const width = tex2d.width;
18531859
const height = tex2d.height;
18541860
const createNewAttachment = createNew || false;
1855-
this._instance.resizeSlotRegion(slotName, width, height, createNewAttachment);
1861+
this._instance!.resizeSlotRegion(slotName, width, height, createNewAttachment);
18561862
if (!this._slotTextures) this._slotTextures = new Map<number, Texture2D>();
18571863
let textureID = 0;
18581864
this._slotTextures.forEach((value, key) => {
@@ -1862,7 +1868,7 @@ export class Skeleton extends UIRenderer {
18621868
textureID = ++_slotTextureID;
18631869
this._slotTextures.set(textureID, tex2d);
18641870
}
1865-
this._instance.setSlotTexture(slotName, textureID);
1871+
this._instance!.setSlotTexture(slotName, textureID);
18661872
}
18671873

18681874
private _destroySkeletonInfo (skeletonCache: SkeletonCache | null): void {

native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "spine-mesh-data.h"
66
#include "spine-wasm.h"
77
#include "util-function.h"
8-
#include "spine-skeleton-system.h"
98

109
SlotMesh globalMesh(nullptr, nullptr, 0, 0);
1110

@@ -34,7 +33,6 @@ static void trackEntryCallback(AnimationState *state, EventType type, TrackEntry
3433

3534
SpineSkeletonInstance::SpineSkeletonInstance() {
3635
_model = new SpineModel();
37-
SpineSkeletonSystem::addSpineInstance(this);
3836
}
3937

4038
SpineSkeletonInstance::~SpineSkeletonInstance() {
@@ -46,6 +44,10 @@ SpineSkeletonInstance::~SpineSkeletonInstance() {
4644
if (_model) delete _model;
4745
}
4846

47+
void SpineSkeletonInstance::destroy() {
48+
delete this;
49+
}
50+
4951
Skeleton *SpineSkeletonInstance::initSkeleton(SkeletonData *data) {
5052
if (_clipper) delete _clipper;
5153
if (_animState) delete _animState;

native/cocos/editor-support/spine-wasm/spine-skeleton-instance.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class SpineSkeletonInstance {
5858
std::vector<SpineDebugShape> &getDebugShapes();
5959
void resizeSlotRegion(const std::string &slotName, uint32_t width, uint32_t height, bool createNew = false);
6060
void setSlotTexture(const std::string &slotName, uint32_t index);
61+
void destroy();
6162
bool isCache{false};
6263
bool enable{true};
6364
float dtRate{1.0F};

0 commit comments

Comments
 (0)