mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-22 02:06:03 +08:00
[ts] Fixed AssetManager dispose invalidating textures too early. Close #2905.
This commit is contained in:
parent
aded292be3
commit
e899a99cbb
@ -176,7 +176,7 @@ export class AssetManagerBase implements Disposable {
|
|||||||
return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null;
|
return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null;
|
||||||
}).then((bitmap) => {
|
}).then((bitmap) => {
|
||||||
if (bitmap) {
|
if (bitmap) {
|
||||||
const texture = this.textureLoader(bitmap);
|
const texture = this.createTexture(path, bitmap);
|
||||||
this.success(success, path, texture);
|
this.success(success, path, texture);
|
||||||
resolve(texture);
|
resolve(texture);
|
||||||
};
|
};
|
||||||
@ -185,7 +185,7 @@ export class AssetManagerBase implements Disposable {
|
|||||||
let image = new Image();
|
let image = new Image();
|
||||||
image.crossOrigin = "anonymous";
|
image.crossOrigin = "anonymous";
|
||||||
image.onload = () => {
|
image.onload = () => {
|
||||||
const texture = this.textureLoader(image);
|
const texture = this.createTexture(path, image);
|
||||||
this.success(success, path, texture);
|
this.success(success, path, texture);
|
||||||
resolve(texture);
|
resolve(texture);
|
||||||
};
|
};
|
||||||
@ -214,7 +214,7 @@ export class AssetManagerBase implements Disposable {
|
|||||||
this.cache.assetsLoaded[path] = new Promise<any>((resolve, reject) => {
|
this.cache.assetsLoaded[path] = new Promise<any>((resolve, reject) => {
|
||||||
this.downloader.downloadText(path, (atlasText: string): void => {
|
this.downloader.downloadText(path, (atlasText: string): void => {
|
||||||
try {
|
try {
|
||||||
let atlas = new TextureAtlas(atlasText);
|
const atlas = this.createTextureAtlas(path, atlasText);
|
||||||
let toLoad = atlas.pages.length, abort = false;
|
let toLoad = atlas.pages.length, abort = false;
|
||||||
for (let page of atlas.pages) {
|
for (let page of atlas.pages) {
|
||||||
this.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name!],
|
this.loadTexture(!fileAlias ? parent + page.name : fileAlias[page.name!],
|
||||||
@ -262,7 +262,7 @@ export class AssetManagerBase implements Disposable {
|
|||||||
this.cache.assetsLoaded[path] = new Promise<any>((resolve, reject) => {
|
this.cache.assetsLoaded[path] = new Promise<any>((resolve, reject) => {
|
||||||
this.downloader.downloadText(path, (atlasText: string): void => {
|
this.downloader.downloadText(path, (atlasText: string): void => {
|
||||||
try {
|
try {
|
||||||
const atlas = new TextureAtlas(atlasText);
|
const atlas = this.createTextureAtlas(path, atlasText);
|
||||||
this.success(success, path, atlas);
|
this.success(success, path, atlas);
|
||||||
resolve(atlas);
|
resolve(atlas);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -378,9 +378,12 @@ export class AssetManagerBase implements Disposable {
|
|||||||
|
|
||||||
// dispose asset only if it's not used by others
|
// dispose asset only if it's not used by others
|
||||||
disposeAsset (path: string) {
|
disposeAsset (path: string) {
|
||||||
if (--this.cache.assetsRefCount[path] === 0) {
|
const asset = this.cache.assets[path];
|
||||||
this.remove(path)
|
if (asset instanceof TextureAtlas) {
|
||||||
|
asset.dispose();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
this.disposeAssetInternal(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasErrors () {
|
hasErrors () {
|
||||||
@ -390,6 +393,33 @@ export class AssetManagerBase implements Disposable {
|
|||||||
getErrors () {
|
getErrors () {
|
||||||
return this.errors;
|
return this.errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private disposeAssetInternal (path: string) {
|
||||||
|
if (this.cache.assetsRefCount[path] > 0 && --this.cache.assetsRefCount[path] === 0) {
|
||||||
|
return this.remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private createTextureAtlas (path: string, atlasText: string): TextureAtlas {
|
||||||
|
const atlas = new TextureAtlas(atlasText);
|
||||||
|
atlas.dispose = () => {
|
||||||
|
if (this.cache.assetsRefCount[path] <= 0) return;
|
||||||
|
this.disposeAssetInternal(path);
|
||||||
|
for (const page of atlas.pages) {
|
||||||
|
page.texture?.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return atlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
private createTexture (path: string, image: HTMLImageElement | ImageBitmap): Texture {
|
||||||
|
const texture = this.textureLoader(image);
|
||||||
|
const textureDispose = texture.dispose.bind(texture);
|
||||||
|
texture.dispose = () => {
|
||||||
|
if (this.disposeAssetInternal(path)) textureDispose();
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AssetCache {
|
export class AssetCache {
|
||||||
|
|||||||
@ -32,27 +32,27 @@ import {
|
|||||||
AnimationState,
|
AnimationState,
|
||||||
AnimationStateData,
|
AnimationStateData,
|
||||||
AtlasAttachmentLoader,
|
AtlasAttachmentLoader,
|
||||||
|
Bone,
|
||||||
Disposable,
|
Disposable,
|
||||||
LoadingScreen,
|
LoadingScreen,
|
||||||
|
MeshAttachment,
|
||||||
MixBlend,
|
MixBlend,
|
||||||
MixDirection,
|
MixDirection,
|
||||||
|
NumberArrayLike,
|
||||||
Physics,
|
Physics,
|
||||||
|
RegionAttachment,
|
||||||
|
Skeleton,
|
||||||
SkeletonBinary,
|
SkeletonBinary,
|
||||||
SkeletonData,
|
SkeletonData,
|
||||||
SkeletonJson,
|
SkeletonJson,
|
||||||
Skeleton,
|
|
||||||
TextureAtlas,
|
|
||||||
Vector2,
|
|
||||||
Utils,
|
|
||||||
NumberArrayLike,
|
|
||||||
Slot,
|
|
||||||
RegionAttachment,
|
|
||||||
MeshAttachment,
|
|
||||||
Bone,
|
|
||||||
Skin,
|
Skin,
|
||||||
|
Slot,
|
||||||
|
TextureAtlas,
|
||||||
|
Utils,
|
||||||
|
Vector2,
|
||||||
} from "@esotericsoftware/spine-webgl";
|
} from "@esotericsoftware/spine-webgl";
|
||||||
import { AttributeTypes, castValue, isBase64, Rectangle } from "./wcUtils.js";
|
|
||||||
import { SpineWebComponentOverlay } from "./SpineWebComponentOverlay.js";
|
import { SpineWebComponentOverlay } from "./SpineWebComponentOverlay.js";
|
||||||
|
import { AttributeTypes, castValue, isBase64, Rectangle } from "./wcUtils.js";
|
||||||
|
|
||||||
type UpdateSpineWidgetFunction = (delta: number, skeleton: Skeleton, state: AnimationState) => void;
|
type UpdateSpineWidgetFunction = (delta: number, skeleton: Skeleton, state: AnimationState) => void;
|
||||||
|
|
||||||
@ -1318,7 +1318,6 @@ export class SpineWebComponentSkeleton extends HTMLElement implements Disposable
|
|||||||
const { assetManager } = this.overlay;
|
const { assetManager } = this.overlay;
|
||||||
if (this.lastAtlasPath) assetManager.disposeAsset(this.lastAtlasPath);
|
if (this.lastAtlasPath) assetManager.disposeAsset(this.lastAtlasPath);
|
||||||
if (this.lastSkelPath) assetManager.disposeAsset(this.lastSkelPath);
|
if (this.lastSkelPath) assetManager.disposeAsset(this.lastSkelPath);
|
||||||
for (const texturePath of this.lastTexturePaths) assetManager.disposeAsset(texturePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user