From 4776cccdf9049463cf08609f50002172cea118af Mon Sep 17 00:00:00 2001 From: zrinthect Date: Thu, 16 Mar 2023 13:53:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B5=84=E6=BA=90=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E6=A8=A1=E5=9D=97AssetLoder=EF=BC=8C=E7=AE=80?= =?UTF-8?q?=E5=8D=95=E5=AE=9E=E7=8E=B0=E5=8A=A0=E8=BD=BD=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=B8=BB=E8=A6=81=E6=98=AF=E6=8F=90=E4=BE=9B=E7=BB=99?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E6=8E=A5=E7=AE=A1=E5=8A=A0=E8=BD=BD=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E7=9A=84=E9=80=94=E5=BE=84=EF=BC=9B=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9Image=E5=BC=95=E7=94=A8=E5=9B=BE=E7=89=87=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=97=B6=E4=BD=BF=E7=94=A8blobURL=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E5=8D=B3=E9=80=9A=E8=BF=87AssetLoader?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E8=B5=84=E6=BA=90=E5=86=8D=E7=94=9F=E6=88=90?= =?UTF-8?q?blob=E8=B7=AF=E5=BE=84=E5=BC=95=E7=94=A8=EF=BC=8C=E7=9B=AE?= =?UTF-8?q?=E7=9A=84=E6=98=AF=E5=B0=86=E5=9B=BE=E7=89=87=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E4=B9=9F=E9=80=9A=E8=BF=87AssetLoader=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E8=B5=B7=E6=9D=A5=EF=BC=9B=20=E4=BF=AE=E6=94=B9UIPackage.loadP?= =?UTF-8?q?ackage=E9=80=9A=E8=BF=87AssetLoader=E5=8A=A0=E8=BD=BD=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/FairyGUI.ts | 1 + src/core/Image.ts | 34 +++++++++++++++++---- src/ui/UIPackage.ts | 29 +++++------------- src/utils/AssetLoader.ts | 64 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 src/utils/AssetLoader.ts diff --git a/src/FairyGUI.ts b/src/FairyGUI.ts index 9a6b7be..9c9da8d 100644 --- a/src/FairyGUI.ts +++ b/src/FairyGUI.ts @@ -61,6 +61,7 @@ export { GTween } from "./tween/GTween"; export { GTweener } from "./tween/GTweener"; export { EaseType } from "./tween/EaseType"; +export { AssetLoader } from "./utils/AssetLoader"; export { UBBParser } from "./utils/UBBParser"; export { ByteBuffer } from "./utils/ByteBuffer";; export * from "./utils/ToolSet" diff --git a/src/core/Image.ts b/src/core/Image.ts index f3a72bb..d2b1b79 100644 --- a/src/core/Image.ts +++ b/src/core/Image.ts @@ -11,6 +11,8 @@ export class Image extends UIElement { protected _textureScale: Vec2; protected _tileGridIndice: number = 0; + private _blobURL: string; + private _timerID_1: number = 0; constructor() { @@ -139,19 +141,41 @@ export class Image extends UIElement { this.style.filter = filter; } + public dispose(): void { + super.dispose(); + this.returnBlobURL(); + } + + private returnBlobURL(){ + if(this._blobURL){ + AssetLoader.returnBlobURL(this._blobURL); + this._blobURL = null; + } + } + protected refresh(): void { if (this._timerID_1 != 0) return; - this._timerID_1 = window.requestAnimationFrame(() => { + this._timerID_1 = window.requestAnimationFrame(async () => { this._timerID_1 = 0; - + this.returnBlobURL(); if (!this._src) { this.style.backgroundImage = "none"; return; } + let data = await AssetLoader.load(this._src); + if(data == null){ + this.style.backgroundImage = "none"; + return; + } + let src = this._blobURL = AssetLoader.getBlobURL(this._src); + if(src == null){ + this.style.backgroundImage = "none"; + return; + } if (this._scaleByTile) { - this.style.backgroundImage = "url('" + this._src + "')"; + this.style.backgroundImage = "url('" + src + "')"; if (this._textureScale.x != 1 || this._textureScale.y != 1) this.style.backgroundSize = this._textureScale.x + "px " + this._textureScale.y + "px"; else @@ -161,7 +185,7 @@ export class Image extends UIElement { else if (this._scale9Grid) { this.style.boxSizing = "border-box"; this.style.backgroundImage = "none"; - this.style.borderImage = "url('" + this._src + "')"; + this.style.borderImage = "url('" + src + "')"; if (this._textureScale.x != 1 || this._textureScale.y != 1) this.style.borderImageWidth = Math.floor(this._scale9Grid.top / this._textureScale.y) + "px " + Math.floor(this._scale9Grid.right / this._textureScale.x) + "px " + Math.floor(this._scale9Grid.bottom / this._textureScale.y) + "px " + Math.floor(this._scale9Grid.left / this._textureScale.x) + "px" @@ -175,7 +199,7 @@ export class Image extends UIElement { this.style.borderImageRepeat = ""; } else { - this.style.backgroundImage = "url('" + this._src + "')"; + this.style.backgroundImage = "url('" + src + "')"; this.style.backgroundSize = "100% 100%"; this.style.backgroundRepeat = "no-repeat"; } diff --git a/src/ui/UIPackage.ts b/src/ui/UIPackage.ts index 478824e..1e2ab0c 100644 --- a/src/ui/UIPackage.ts +++ b/src/ui/UIPackage.ts @@ -61,29 +61,16 @@ export class UIPackage { return _instByName[name]; } - public static loadPackage(url: string): Promise { + public static async loadPackage(url: string): Promise { if (!url.endsWith("/")) url += "/"; - return new Promise(resolve => { - let pkg: UIPackage = _instById[url]; - if (pkg) { - resolve(pkg); - return; - } - - let request = new HttpRequest(); - request.send(url + "package.xml", null, "get", "arraybuffer"); - request.on("complete", (evt: Event) => { - let pkg: UIPackage = new UIPackage(); - pkg.loadPackage(new ByteBuffer(evt.data), url); - - _instById[pkg.id] = pkg; - _instByName[pkg.name] = pkg; - _instById[pkg.path] = pkg; - - resolve(pkg); - }); - }); + const data = await AssetLoader.load(url + "package.xml"); + let pkg: UIPackage = new UIPackage(); + pkg.loadPackage(new ByteBuffer(data), url); + _instById[pkg.id] = pkg; + _instByName[pkg.name] = pkg; + _instById[pkg.path] = pkg; + return pkg; } public static removePackage(packageIdOrName: string): void { diff --git a/src/utils/AssetLoader.ts b/src/utils/AssetLoader.ts new file mode 100644 index 0000000..14c92fc --- /dev/null +++ b/src/utils/AssetLoader.ts @@ -0,0 +1,64 @@ +import { Event } from "../event/Event"; +import { HttpRequest } from "./HttpRequest"; + +export interface IAssetLoaderStatic { + load(url: string): Promise; + getBlobURL(data:any):string; + returnBlobURL(url: string): void; +} + +declare global { + var AssetLoader: IAssetLoaderStatic; +} + +export class AssetLoader { + private static cache = new Map(); + private static blobURLCache = new Map(); + private static blobURLCnt = new Map(); + + static load(url: string): Promise { + let cacheContent = this.cache.get(url); + if(cacheContent){ + return cacheContent; + } + return new Promise((resolve, reject) => { + let request = new HttpRequest(); + request.send(url, null, "get", "arraybuffer"); + request.on("complete", (evt: Event) => { + this.cache.set(url, evt.data); + resolve(evt.data); + }); + }); + } + + static getBlobURL(dataURL: string): string { + let blobURL = this.blobURLCache.get(dataURL); + if (blobURL) { + return blobURL; + } + let data = this.cache.get(dataURL); + if(data == null){ + return null; + } + + let blob = new Blob([data], { type: 'application/octet-binary' }); + blobURL = URL.createObjectURL(blob); + + this.blobURLCache.set(dataURL, blobURL); + let cnt = this.blobURLCnt.get(blobURL) || 0; + this.blobURLCnt.set(blobURL, cnt + 1); + return blobURL; + } + + static returnBlobURL(blobURL: string): void { + let cnt = this.blobURLCnt.get(blobURL) || 0; + if(cnt == 0){ + URL.revokeObjectURL(blobURL); + this.blobURLCnt.delete(blobURL); + return; + } + this.blobURLCnt.set(blobURL, cnt - 1); + } +} + +globalThis.AssetLoader = AssetLoader; \ No newline at end of file