Quellcode durchsuchen

[ts][pixi-v8] Clean up SpinePipe after Spine object is destroyed. Closes #2678.

Davide Tantillo vor 10 Monaten
Ursprung
Commit
fb3855ad65
1 geänderte Dateien mit 22 neuen und 7 gelöschten Zeilen
  1. 22 7
      spine-ts/spine-pixi-v8/src/SpinePipe.ts

+ 22 - 7
spine-ts/spine-pixi-v8/src/SpinePipe.ts

@@ -31,20 +31,24 @@ import {
 	collectAllRenderables,
 	extensions, ExtensionType,
 	InstructionSet,
+	type BLEND_MODES,
+	type Container,
 	type Renderer,
 	type RenderPipe,
 } from 'pixi.js';
 import { BatchableSpineSlot } from './BatchableSpineSlot';
 import { Spine } from './Spine';
-import { MeshAttachment, RegionAttachment, SkeletonClipping } from '@esotericsoftware/spine-core';
+import { MeshAttachment, RegionAttachment } from '@esotericsoftware/spine-core';
 
-const spineBlendModeMap = {
+const spineBlendModeMap : Record<number, BLEND_MODES> = {
 	0: 'normal',
 	1: 'add',
 	2: 'multiply',
 	3: 'screen'
 };
 
+type GpuSpineDataElement = { slotBatches: Record<string, BatchableSpineSlot> };
+
 // eslint-disable-next-line max-len
 export class SpinePipe implements RenderPipe<Spine> {
 	/** @ignore */
@@ -59,7 +63,8 @@ export class SpinePipe implements RenderPipe<Spine> {
 
 	renderer: Renderer;
 
-	private gpuSpineData: Record<string, any> = {};
+	private gpuSpineData: Record<string, GpuSpineDataElement> = {};
+	private readonly _destroyRenderableBound = this.destroyRenderable.bind(this) as (renderable: Container) => void;
 
 	constructor (renderer: Renderer) {
 		this.renderer = renderer;
@@ -68,10 +73,11 @@ export class SpinePipe implements RenderPipe<Spine> {
 	validateRenderable (spine: Spine): boolean {
 		spine._validateAndTransformAttachments();
 
-		// if pine attachments have changed, we need to rebuild the batch!
+		// if spine attachments have changed or destroyed, we need to rebuild the batch!
 		if (spine.spineAttachmentsDirty) {
 			return true;
 		}
+
 		// if the textures have changed, we need to rebuild the batch, but only if the texture is not already in the batch
 		else if (spine.spineTexturesDirty) {
 			// loop through and see if the textures have changed..
@@ -101,7 +107,7 @@ export class SpinePipe implements RenderPipe<Spine> {
 	}
 
 	addRenderable (spine: Spine, instructionSet: InstructionSet) {
-		const gpuSpine = this.gpuSpineData[spine.uid] ||= { slotBatches: { } };
+		const gpuSpine = this._getSpineData(spine);
 
 		const batcher = this.renderer.renderPipes.batch;
 
@@ -145,7 +151,6 @@ export class SpinePipe implements RenderPipe<Spine> {
 	}
 
 	updateRenderable (spine: Spine) {
-		// we assume that spine will always change its verts size..
 		const gpuSpine = this.gpuSpineData[spine.uid];
 
 		spine._validateAndTransformAttachments();
@@ -169,14 +174,24 @@ export class SpinePipe implements RenderPipe<Spine> {
 	}
 
 	destroyRenderable (spine: Spine) {
-		// TODO remove the renderable from the batcher
 		this.gpuSpineData[spine.uid] = null as any;
+		spine.off('destroyed', this._destroyRenderableBound);
 	}
 
 	destroy () {
 		this.gpuSpineData = null as any;
 		this.renderer = null as any;
 	}
+
+	private _getSpineData(spine: Spine): GpuSpineDataElement {
+		return this.gpuSpineData[spine.uid] || this._initMeshData(spine);
+    }
+
+	private _initMeshData(spine: Spine): GpuSpineDataElement {
+        this.gpuSpineData[spine.uid] = { slotBatches: { } };
+        spine.on('destroyed', this._destroyRenderableBound);
+        return this.gpuSpineData[spine.uid];
+    }
 }
 
 extensions.add(SpinePipe);