Skip to content

Commit

Permalink
Refine: make multi skeleton component shared one instance of spine.Sk…
Browse files Browse the repository at this point in the history
…eleton while spine working at sharedCache mode
  • Loading branch information
bofeng-song committed Dec 14, 2023
1 parent c44eb3d commit 1fa3760
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 11 deletions.
1 change: 1 addition & 0 deletions cocos/spine/lib/spine-core.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,7 @@ declare namespace spine {
static createSpineSkeletonDataWithBinary(byteSize: number, atlasText: string): SkeletonData;
static registerSpineSkeletonDataWithUUID(data: SkeletonData, uuid: string);
static destroySpineSkeletonDataWithUUID(uuid: string);
static destroySpineSkeleton(skeleton: Skeleton): void;
static getCurrentListenerID(): number;
static getCurrentEventType(): EventType;
static getCurrentTrackEntry(): TrackEntry;
Expand Down
54 changes: 49 additions & 5 deletions cocos/spine/skeleton-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { SPINE_WASM } from './lib/instantiated';
import spine from './lib/spine-core.js';
import { SkeletonData } from './skeleton-data';
import { warn } from '../core/platform/debug';
import { Skeleton } from './skeleton';

const MaxCacheTime = 30;
const FrameTime = 1 / 60;
Expand Down Expand Up @@ -310,7 +311,10 @@ class SkeletonCache {

protected _privateMode: boolean;
protected _skeletonCache: { [key: string]: SkeletonCacheItemInfo };

//for shared mode only
protected _animationPool: { [key: string]: AnimationCache };
private _sharedCacheMap: Map<string, Array<Skeleton>> = new Map<string, Array<Skeleton>>();
constructor () {
this._privateMode = false;
this._animationPool = {};
Expand Down Expand Up @@ -338,7 +342,35 @@ class SkeletonCache {
}
}

public removeSkeleton (uuid: string): void {
public removeSkeleton (uuid: string, skeletonComponent: Skeleton): void {
const sharedInstances = this._sharedCacheMap.get(uuid);
if (sharedInstances) {
const index = sharedInstances.indexOf(skeletonComponent);
if (index !== -1) {
console.log('bf test delete index=', index);
sharedInstances.splice(index, 1);
}
sharedInstances.forEach((skeleton) => {
if (skeleton === skeletonComponent) {
console.log('bf test 0000index=', skeleton);
}
});
console.log('bf test index=', index);
if (sharedInstances.length > 0) {
return;
}
this._sharedCacheMap.delete(uuid);
}

const sharedOperate = (aniKey: string, animationCache: AnimationCache): void => {
this._animationPool[`${uuid}#${aniKey}`] = animationCache;
animationCache.clear();
};
const privateOperate = (aniKey: string, animationCache: AnimationCache): void => {
animationCache.destroy();
};
const operate = sharedInstances ? sharedOperate : privateOperate;

const skeletonInfo = this._skeletonCache[uuid];
if (!skeletonInfo) return;
const animationsCache = skeletonInfo.animationsCache;
Expand All @@ -347,17 +379,29 @@ class SkeletonCache {
// No need to create TypedArray next time.
const animationCache = animationsCache[aniKey];
if (!animationCache) continue;
this._animationPool[`${uuid}#${aniKey}`] = animationCache;
animationCache.clear();
operate(aniKey, animationCache);
}

if (skeletonInfo.skeleton) {
spine.wasmUtil.destroySpineSkeleton(skeletonInfo.skeleton);
}
delete this._skeletonCache[uuid];
}

public getSkeletonCache (uuid: string, skeletonData: spine.SkeletonData): SkeletonCacheItemInfo {
public getSkeletonCache (uuid: string, skeletonData: spine.SkeletonData, skeletonComponent: Skeleton): SkeletonCacheItemInfo {
if (SkeletonCache.sharedCache === this) {
let sharedInstances = this._sharedCacheMap.get(uuid);
if (!sharedInstances) {
sharedInstances = new Array<Skeleton>();
this._sharedCacheMap.set(uuid, sharedInstances);
}
if (sharedInstances.indexOf(skeletonComponent) === -1) {
sharedInstances.push(skeletonComponent);
}
}
let skeletonInfo = this._skeletonCache[uuid];
if (!skeletonInfo) {
const skeleton = null;
const skeleton = new spine.Skeleton(skeletonData);
const clipper = null;
const state = null;
const listener = new TrackEntryListeners();
Expand Down
9 changes: 3 additions & 6 deletions cocos/spine/skeleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ export class Skeleton extends UIRenderer {
if (value) value.resetEnums();
if (this._skeletonData !== value) {
if (this._skeletonCache && this._skeletonData) {
this._skeletonCache.removeSkeleton(this._skeletonData.uuid);
this._skeletonCache.removeSkeleton(this._skeletonData.uuid, this);
}
this.destroyRenderData();
this._skeletonData = value as any;
Expand Down Expand Up @@ -716,7 +716,7 @@ export class Skeleton extends UIRenderer {
spine.SkeletonSystem.destroySpineInstance(this._instance);
}
if (this._skeletonCache && this._skeletonData) {
this._skeletonCache.removeSkeleton(this._skeletonData.uuid);
this._skeletonCache.removeSkeleton(this._skeletonData.uuid, this);
}
super.onDestroy();
}
Expand Down Expand Up @@ -789,10 +789,7 @@ export class Skeleton extends UIRenderer {
warn('Debug bones or slots is invalid in cached mode');
}
if (this.skeletonData) {
const skeletonInfo = this._skeletonCache!.getSkeletonCache(this.skeletonData.uuid, skeletonData);
if (!skeletonInfo.skeleton) {
skeletonInfo.skeleton = this._instance.initSkeleton(skeletonData);
}
const skeletonInfo = this._skeletonCache!.getSkeletonCache(this.skeletonData.uuid, skeletonData, this);
this._skeleton = skeletonInfo.skeleton!;
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,7 @@ EMSCRIPTEN_BINDINGS(cocos_spine) {
.class_function("createSpineSkeletonDataWithBinary", &SpineWasmUtil::createSpineSkeletonDataWithBinary, allow_raw_pointers())
.class_function("registerSpineSkeletonDataWithUUID", &SpineWasmUtil::registerSpineSkeletonDataWithUUID, allow_raw_pointers())
.class_function("destroySpineSkeletonDataWithUUID", &SpineWasmUtil::destroySpineSkeletonDataWithUUID)
.class_function("destroySpineSkeleton", &SpineWasmUtil::destroySpineSkeleton, allow_raw_pointers())
.class_function("getCurrentListenerID", &SpineWasmUtil::getCurrentListenerID)
.class_function("getCurrentEventType", &SpineWasmUtil::getCurrentEventType)
.class_function("getCurrentTrackEntry", &SpineWasmUtil::getCurrentTrackEntry, allow_raw_pointers())
Expand Down
6 changes: 6 additions & 0 deletions native/cocos/editor-support/spine-wasm/spine-wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ void SpineWasmUtil::destroySpineSkeletonDataWithUUID(const std::string& uuid) {
}
}

void SpineWasmUtil::destroySpineSkeleton(Skeleton* skeleton) {
if (skeleton) {
delete skeleton;
}
}

uint32_t SpineWasmUtil::queryStoreMemory(uint32_t size) {
if (s_mem) {
if (s_memSize < size) {
Expand Down
1 change: 1 addition & 0 deletions native/cocos/editor-support/spine-wasm/spine-wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SpineWasmUtil {
static SkeletonData* createSpineSkeletonDataWithBinary(uint32_t byteSize, const std::string& altasStr);
static void registerSpineSkeletonDataWithUUID(SkeletonData* data, const std::string& uuid);
static void destroySpineSkeletonDataWithUUID(const std::string& uuid);
static void destroySpineSkeleton(Skeleton* skeleton);

static uint32_t getCurrentListenerID();
static EventType getCurrentEventType();
Expand Down

0 comments on commit 1fa3760

Please sign in to comment.