diff --git a/cocos/spine/lib/spine-core.d.ts b/cocos/spine/lib/spine-core.d.ts index 8211706e3be..721a3908397 100644 --- a/cocos/spine/lib/spine-core.d.ts +++ b/cocos/spine/lib/spine-core.d.ts @@ -1191,6 +1191,7 @@ declare namespace spine { isDelete: boolean; enable: boolean; setTrackEntryListener: any; + destroy(); initSkeleton(data: SkeletonData); getAnimationState(); setAnimation(trackIndex: number, name: string, loop: boolean): spine.TrackEntry | null; diff --git a/cocos/spine/skeleton-cache.ts b/cocos/spine/skeleton-cache.ts index 4fd1b219b55..869137a5eaa 100644 --- a/cocos/spine/skeleton-cache.ts +++ b/cocos/spine/skeleton-cache.ts @@ -76,7 +76,7 @@ export interface AnimationFrame { } export class AnimationCache { - protected _instance: spine.SkeletonInstance = null!; + protected _instance: spine.SkeletonInstance | null = null; protected _state: spine.AnimationState = null!; protected _skeletonData: spine.SkeletonData = null!; protected _skeleton: spine.Skeleton = null!; @@ -117,7 +117,7 @@ export class AnimationCache { public setSkin (skinName: string): void { if (this._skeleton) this._skeleton.setSkinByName(skinName); - this._instance.setSkin(skinName); + this._instance!.setSkin(skinName); } public setAnimation (animationName: string): void { @@ -134,7 +134,7 @@ export class AnimationCache { } this._maxFrameIdex = Math.floor((animation as any).duration / FrameTime); if (this._maxFrameIdex <= 0) this._maxFrameIdex = 1; - this._instance.setAnimation(0, animationName, false); + this._instance!.setAnimation(0, animationName, false); } public updateToFrame (frameIdx: number): void { @@ -145,8 +145,8 @@ export class AnimationCache { // Solid update frame rate 1/60. this._frameIdx++; this.totalTime += FrameTime; - this._instance.updateAnimation(FrameTime); - const model = this._instance.updateRenderData(); + this._instance!.updateAnimation(FrameTime); + const model = this._instance!.updateRenderData(); this.updateRenderData(this._frameIdx, model); if (this._frameIdx >= this._maxFrameIdex) { this.isCompleted = true; @@ -234,7 +234,7 @@ export class AnimationCache { } } const listener = skeletonInfo?.listener; - this._instance.setAnimation(0, this._animationName!, false); + this._instance!.setAnimation(0, this._animationName!, false); this.bind(listener!); // record cur animation cache @@ -302,7 +302,10 @@ export class AnimationCache { } public destroy (): void { - spine.SkeletonSystem.destroySpineInstance(this._instance); + if (this._instance) { + this._instance.destroy(); + this._instance = null; + } } } diff --git a/cocos/spine/skeleton-system.ts b/cocos/spine/skeleton-system.ts index 3d4a1e40606..109f6b7b3cd 100644 --- a/cocos/spine/skeleton-system.ts +++ b/cocos/spine/skeleton-system.ts @@ -78,7 +78,6 @@ export class SkeletonSystem extends System { if (!this._skeletons) { return; } - if (!EDITOR_NOT_IN_PREVIEW && !JSB) spine.SkeletonSystem.updateAnimation(dt); this._skeletons.forEach((skeleton) => { skeleton.updateAnimation(dt); }); diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 5f47a2cdee9..52ca9bd1f01 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -237,7 +237,7 @@ export class Skeleton extends UIRenderer { protected _runtimeData: spine.SkeletonData | null = null; public _skeleton: spine.Skeleton = null!; - protected _instance: spine.SkeletonInstance = null!; + protected _instance: spine.SkeletonInstance | null = null; protected _state: spine.AnimationState = null!; protected _textures: Texture2D[] = []; private _skeletonInfo: SkeletonCacheItemInfo | null = null; @@ -491,7 +491,7 @@ export class Skeleton extends UIRenderer { set premultipliedAlpha (v: boolean) { if (v !== this._premultipliedAlpha) { this._premultipliedAlpha = v; - this._instance.setPremultipliedAlpha(v); + this._instance!.setPremultipliedAlpha(v); this.markForUpdateRenderData(); } } @@ -710,8 +710,9 @@ export class Skeleton extends UIRenderer { //if (this._cacheMode == AnimationCacheMode.PRIVATE_CACHE) this._animCache?.destroy(); this._animCache = null; SkeletonSystem.getInstance().remove(this); - if (!JSB) { - spine.SkeletonSystem.destroySpineInstance(this._instance); + if (!JSB && this._instance) { + this._instance.destroy(); + this._instance = null; } this._destroySkeletonInfo(this._skeletonCache); this._skeletonCache = null; @@ -812,9 +813,9 @@ export class Skeleton extends UIRenderer { this._skeleton = this._skeletonInfo.skeleton!; } } else { - this._skeleton = this._instance.initSkeleton(skeletonData); - this._state = this._instance.getAnimationState(); - this._instance.setPremultipliedAlpha(this._premultipliedAlpha); + this._skeleton = this._instance!.initSkeleton(skeletonData); + this._state = this._instance!.getAnimationState(); + this._instance!.setPremultipliedAlpha(this._premultipliedAlpha); } // Recreate render data and mark dirty this._flushAssembler(); @@ -929,7 +930,7 @@ export class Skeleton extends UIRenderer { } } else { this._animationName = name; - trackEntry = this._instance.setAnimation(trackIndex, name, loop); + trackEntry = this._instance!.setAnimation(trackIndex, name, loop); } this.markForUpdateRenderData(); return trackEntry; @@ -1007,7 +1008,7 @@ export class Skeleton extends UIRenderer { */ public setSkin (name: string): void { if (this._skeleton) this._skeleton.setSkinByName(name); - this._instance.setSkin(name); + this._instance!.setSkin(name); if (this.isAnimationCached()) { if (this._animCache) { this._animCache.setSkin(name); @@ -1050,6 +1051,8 @@ export class Skeleton extends UIRenderer { return; } this._updateCache(dt); + } else { + this._instance!.updateAnimation(dt); } } @@ -1112,7 +1115,7 @@ export class Skeleton extends UIRenderer { const model = this._curFrame.model; return model; } else { - const model = this._instance.updateRenderData(); + const model = this._instance!.updateRenderData(); return model; } } @@ -1444,7 +1447,7 @@ export class Skeleton extends UIRenderer { return; } if (this._state) { - this._instance.setMix(fromAnimation, toAnimation, duration); + this._instance!.setMix(fromAnimation, toAnimation, duration); //this._state.data.setMix(fromAnimation, toAnimation, duration); } } @@ -1577,7 +1580,7 @@ export class Skeleton extends UIRenderer { this.destroyRenderData(); if (!JSB) { if (!this.isAnimationCached()) { - this._instance.setUseTint(this._useTint); + this._instance!.setUseTint(this._useTint); } } if (this._assembler && this._skeleton) { @@ -1607,7 +1610,7 @@ export class Skeleton extends UIRenderer { if (this.isAnimationCached()) { warn('Debug bones or slots is invalid in cached mode'); } else if (!JSB) { - this._instance.setDebugMode(true); + this._instance!.setDebugMode(true); } } else if (this._debugRenderer) { this._debugRenderer.node.destroy(); @@ -1655,7 +1658,7 @@ export class Skeleton extends UIRenderer { const r = this._color.r / 255.0; const g = this._color.g / 255.0; const b = this._color.b / 255.0; - this._instance.setColor(r, g, b, a); + this._instance!.setColor(r, g, b, a); } /** @@ -1664,6 +1667,9 @@ export class Skeleton extends UIRenderer { * @param effectDelegate @en Vertex effect delegate. @zh 顶点特效代理。 */ public setVertexEffectDelegate (effectDelegate: VertexEffectDelegate | null | undefined): void { + if (!this._instance) { + return; + } if (!effectDelegate) { this._instance.clearEffect(); return; @@ -1692,7 +1698,7 @@ export class Skeleton extends UIRenderer { public setStartListener (listener: TrackListener): void { this._ensureListener(); const listenerID = TrackEntryListeners.addListener(listener); - this._instance.setListener(listenerID, spine.EventType.start); + this._instance!.setListener(listenerID, spine.EventType.start); this._listener!.start = listener; } @@ -1704,7 +1710,7 @@ export class Skeleton extends UIRenderer { public setInterruptListener (listener: TrackListener): void { this._ensureListener(); const listenerID = TrackEntryListeners.addListener(listener); - this._instance.setListener(listenerID, spine.EventType.interrupt); + this._instance!.setListener(listenerID, spine.EventType.interrupt); this._listener!.interrupt = listener; } @@ -1716,7 +1722,7 @@ export class Skeleton extends UIRenderer { public setEndListener (listener: TrackListener): void { this._ensureListener(); const listenerID = TrackEntryListeners.addListener(listener); - this._instance.setListener(listenerID, spine.EventType.end); + this._instance!.setListener(listenerID, spine.EventType.end); this._listener!.end = listener; } @@ -1728,7 +1734,7 @@ export class Skeleton extends UIRenderer { public setDisposeListener (listener: TrackListener): void { this._ensureListener(); const listenerID = TrackEntryListeners.addListener(listener); - this._instance.setListener(listenerID, spine.EventType.dispose); + this._instance!.setListener(listenerID, spine.EventType.dispose); this._listener!.dispose = listener; } @@ -1740,7 +1746,7 @@ export class Skeleton extends UIRenderer { public setCompleteListener (listener: TrackListener): void { this._ensureListener(); const listenerID = TrackEntryListeners.addListener(listener); - this._instance.setListener(listenerID, spine.EventType.complete); + this._instance!.setListener(listenerID, spine.EventType.complete); this._listener!.complete = listener; } @@ -1752,7 +1758,7 @@ export class Skeleton extends UIRenderer { public setEventListener (listener: TrackListener2): void { this._ensureListener(); const listenerID = TrackEntryListeners.addListener(listener); - this._instance.setListener(listenerID, spine.EventType.event); + this._instance!.setListener(listenerID, spine.EventType.event); this._listener!.event = listener; } @@ -1763,7 +1769,7 @@ export class Skeleton extends UIRenderer { * @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。 */ public setTrackStartListener (entry: spine.TrackEntry, listener: TrackListener): void { - TrackEntryListeners.getListeners(entry, this._instance).start = listener; + TrackEntryListeners.getListeners(entry, this._instance!).start = listener; } /** @@ -1773,7 +1779,7 @@ export class Skeleton extends UIRenderer { * @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。 */ public setTrackInterruptListener (entry: spine.TrackEntry, listener: TrackListener): void { - TrackEntryListeners.getListeners(entry, this._instance).interrupt = listener; + TrackEntryListeners.getListeners(entry, this._instance!).interrupt = listener; } /** @@ -1783,7 +1789,7 @@ export class Skeleton extends UIRenderer { * @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。 */ public setTrackEndListener (entry: spine.TrackEntry, listener: TrackListener): void { - TrackEntryListeners.getListeners(entry, this._instance).end = listener; + TrackEntryListeners.getListeners(entry, this._instance!).end = listener; } /** @@ -1793,7 +1799,7 @@ export class Skeleton extends UIRenderer { * @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。 */ public setTrackDisposeListener (entry: spine.TrackEntry, listener: TrackListener): void { - TrackEntryListeners.getListeners(entry, this._instance).dispose = listener; + TrackEntryListeners.getListeners(entry, this._instance!).dispose = listener; } /** @@ -1810,7 +1816,7 @@ export class Skeleton extends UIRenderer { // this._instance.setListener(listenerID, spine.EventType.event); // this._listener!.event = listener; }; - TrackEntryListeners.getListeners(entry, this._instance).complete = onComplete; + TrackEntryListeners.getListeners(entry, this._instance!).complete = onComplete; } /** @@ -1820,14 +1826,14 @@ export class Skeleton extends UIRenderer { * @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。 */ public setTrackEventListener (entry: spine.TrackEntry, listener: TrackListener|TrackListener2): void { - TrackEntryListeners.getListeners(entry, this._instance).event = listener; + TrackEntryListeners.getListeners(entry, this._instance!).event = listener; } /** * @engineInternal */ public getDebugShapes (): any { - return this._instance.getDebugShapes(); + return this._instance!.getDebugShapes(); } /** @@ -1852,7 +1858,7 @@ export class Skeleton extends UIRenderer { const width = tex2d.width; const height = tex2d.height; const createNewAttachment = createNew || false; - this._instance.resizeSlotRegion(slotName, width, height, createNewAttachment); + this._instance!.resizeSlotRegion(slotName, width, height, createNewAttachment); if (!this._slotTextures) this._slotTextures = new Map(); let textureID = 0; this._slotTextures.forEach((value, key) => { @@ -1862,7 +1868,7 @@ export class Skeleton extends UIRenderer { textureID = ++_slotTextureID; this._slotTextures.set(textureID, tex2d); } - this._instance.setSlotTexture(slotName, textureID); + this._instance!.setSlotTexture(slotName, textureID); } private _destroySkeletonInfo (skeletonCache: SkeletonCache | null): void { diff --git a/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp b/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp index 08192bf0aea..8b171a4c750 100644 --- a/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp +++ b/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp @@ -5,7 +5,6 @@ #include "spine-mesh-data.h" #include "spine-wasm.h" #include "util-function.h" -#include "spine-skeleton-system.h" SlotMesh globalMesh(nullptr, nullptr, 0, 0); @@ -34,7 +33,6 @@ static void trackEntryCallback(AnimationState *state, EventType type, TrackEntry SpineSkeletonInstance::SpineSkeletonInstance() { _model = new SpineModel(); - SpineSkeletonSystem::addSpineInstance(this); } SpineSkeletonInstance::~SpineSkeletonInstance() { @@ -46,6 +44,10 @@ SpineSkeletonInstance::~SpineSkeletonInstance() { if (_model) delete _model; } +void SpineSkeletonInstance::destroy() { + delete this; +} + Skeleton *SpineSkeletonInstance::initSkeleton(SkeletonData *data) { if (_clipper) delete _clipper; if (_animState) delete _animState; diff --git a/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.h b/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.h index cb8190cbf1c..c1b53149ebf 100644 --- a/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.h +++ b/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.h @@ -58,6 +58,7 @@ class SpineSkeletonInstance { std::vector &getDebugShapes(); void resizeSlotRegion(const std::string &slotName, uint32_t width, uint32_t height, bool createNew = false); void setSlotTexture(const std::string &slotName, uint32_t index); + void destroy(); bool isCache{false}; bool enable{true}; float dtRate{1.0F}; diff --git a/native/cocos/editor-support/spine-wasm/spine-skeleton-system.cpp b/native/cocos/editor-support/spine-wasm/spine-skeleton-system.cpp deleted file mode 100644 index 5c2ead7f4a1..00000000000 --- a/native/cocos/editor-support/spine-wasm/spine-skeleton-system.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "spine-skeleton-system.h" -#include "spine-skeleton-instance.h" -#include "spine-mesh-data.h" - -using namespace spine; - -std::vector SpineSkeletonSystem::vectorSpines; - -void SpineSkeletonSystem::updateAnimation(float deltaTime) { - auto count = static_cast(vectorSpines.size()); - for (int i = count - 1; i >= 0; --i) { - SpineSkeletonInstance* spineInstance = vectorSpines[i]; - if(!spineInstance->enable) continue; - if (!spineInstance->isCache) { - spineInstance->updateAnimation(deltaTime); - } - } -} - -int SpineSkeletonSystem::getCount() { - auto count = vectorSpines.size(); - return count; -} - -void SpineSkeletonSystem::updateRenderData() { - SpineMeshData::reset(); -} - -void SpineSkeletonSystem::addSpineInstance(SpineSkeletonInstance* instance) { - if(vectorSpines.size() == vectorSpines.capacity()){ - vectorSpines.reserve(vectorSpines.size() + 20); - } - vectorSpines.push_back(instance); -} - -void SpineSkeletonSystem::destroySpineInstance(SpineSkeletonInstance* instance) { - auto it = std::find(vectorSpines.begin(), vectorSpines.end(), instance); - if (it != vectorSpines.end()) { - vectorSpines.erase(it); - delete instance; - } -} \ No newline at end of file diff --git a/native/cocos/editor-support/spine-wasm/spine-skeleton-system.h b/native/cocos/editor-support/spine-wasm/spine-skeleton-system.h deleted file mode 100644 index 6be9cd9e860..00000000000 --- a/native/cocos/editor-support/spine-wasm/spine-skeleton-system.h +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include "spine-skeleton-instance.h" - -using namespace spine; -class SpineSkeletonSystem -{ -public: - static void updateAnimation(float deltaTime); - static void updateRenderData(); - static int getCount(); - static void addSpineInstance(SpineSkeletonInstance* instance); - static void destroySpineInstance(SpineSkeletonInstance* instance); -private: - static std::vector vectorSpines; -}; \ No newline at end of file diff --git a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp index 83133336b98..4fc0eac3c8d 100644 --- a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp +++ b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp @@ -3,7 +3,6 @@ #include #include #include -#include "spine-skeleton-system.h" #include "spine-skeleton-instance.h" #include "spine-wasm.h" #include "Vector2.h" @@ -1607,13 +1606,8 @@ EMSCRIPTEN_BINDINGS(spine) { .function("setDebugMode", &SpineSkeletonInstance::setDebugMode) .function("getDebugShapes", &SpineSkeletonInstance::getDebugShapes) .function("resizeSlotRegion", &SpineSkeletonInstance::resizeSlotRegion) + .function("destroy", &SpineSkeletonInstance::destroy) .function("setSlotTexture", &SpineSkeletonInstance::setSlotTexture); - - class_("SkeletonSystem") - .class_function("getCount", &SpineSkeletonSystem::getCount) - .class_function("updateAnimation", &SpineSkeletonSystem::updateAnimation) - .class_function("updateRenderData", &SpineSkeletonSystem::updateRenderData) - .class_function("destroySpineInstance", &SpineSkeletonSystem::destroySpineInstance, allow_raw_pointers()); } EMSCRIPTEN_BINDINGS(cocos_spine) { diff --git a/native/external-config.json b/native/external-config.json index 89a1e20ef94..78ca7978643 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.2-22" + "checkout": "v3.8.2-23" } } \ No newline at end of file