Compare commits
6 Commits
55c4fcd9ae
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a6620cf8f | ||
|
|
4288798723 | ||
|
|
438aea779e | ||
| a542863dba | |||
| a8e54179a2 | |||
|
|
41d7fe125c |
5
extensions/max-studio/assets/max-studio/core/max.d.ts
vendored
Normal file
5
extensions/max-studio/assets/max-studio/core/max.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
declare module "cc" {
|
||||||
|
interface SpriteFrame {
|
||||||
|
remoteUrl?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "22f3e111-a4f8-4e05-aa61-cbea5c1b9cc1",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
import { nsStringUtils } from "@taqu/Util/StringUtils";
|
||||||
|
import { isValid } from "cc";
|
||||||
|
import { assetManager, ImageAsset, Texture2D } from "cc";
|
||||||
|
import { SpriteFrame } from "cc";
|
||||||
|
import { UITransform } from "cc";
|
||||||
|
import { Sprite } from "cc";
|
||||||
|
import { _decorator } from "cc";
|
||||||
|
import { EDITOR } from "cc/env";
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
@ccclass("CCRemoteSprite")
|
||||||
|
export class CCRemoteSprite extends Sprite {
|
||||||
|
private static _remoteSpriteCache: Map<string, SpriteFrame> = new Map();
|
||||||
|
private static _loadingSpriteCache: Map<string, Promise<SpriteFrame>> = new Map();
|
||||||
|
private static _checkTimer: NodeJS.Timeout;
|
||||||
|
/**
|
||||||
|
* 远程图片URL
|
||||||
|
*/
|
||||||
|
@property({
|
||||||
|
displayName: "远程图片URL",
|
||||||
|
tooltip: "远程图片的URL地址",
|
||||||
|
visible: true
|
||||||
|
})
|
||||||
|
private _remoteUrl: string = "";
|
||||||
|
|
||||||
|
public get remoteUrl(): string {
|
||||||
|
return this._remoteUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set remoteUrl(value: string) {
|
||||||
|
const newValue = value || "";
|
||||||
|
if (this._remoteUrl !== newValue) {
|
||||||
|
this._remoteUrl = newValue;
|
||||||
|
if (nsStringUtils.isEmpty(this._remoteUrl)) {
|
||||||
|
this.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.spriteFrame == null || this._remoteUrl !== this.spriteFrame.remoteUrl) {
|
||||||
|
this.loadRemoteSprite(this._remoteUrl).catch(err => {
|
||||||
|
app.log.error("RemoteSprite", `加载远程图片失败: ${this._remoteUrl}`, err);
|
||||||
|
// 可以添加默认图片或错误状态处理
|
||||||
|
if (this.isValid) {
|
||||||
|
this.spriteFrame = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public onLoad(): void {
|
||||||
|
super.onLoad();
|
||||||
|
if (EDITOR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!CCRemoteSprite._checkTimer) {
|
||||||
|
CCRemoteSprite._checkTimer = setInterval(() => {
|
||||||
|
CCRemoteSprite.checkCache();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nsStringUtils.isEmpty(this.spriteFrame?.remoteUrl)) {
|
||||||
|
this.spriteFrame.addRef();
|
||||||
|
}
|
||||||
|
if (!nsStringUtils.isEmpty(this._remoteUrl) && this.spriteFrame?.remoteUrl !== this._remoteUrl) {
|
||||||
|
this.loadRemoteSprite(this._remoteUrl).catch(err => {
|
||||||
|
app.log.error("RemoteSprite", `onLoad加载远程图片失败: ${this._remoteUrl}`, err);
|
||||||
|
});
|
||||||
|
} else if (nsStringUtils.isEmpty(this._remoteUrl) && !nsStringUtils.isEmpty(this.spriteFrame?.remoteUrl)) {
|
||||||
|
this.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async loadRemoteSprite(url: string): Promise<void> {
|
||||||
|
if (nsStringUtils.isEmpty(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// URL 相同,且已经加载完成,直接返回
|
||||||
|
if (this.spriteFrame && this.spriteFrame.remoteUrl == url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.release();
|
||||||
|
|
||||||
|
if (CCRemoteSprite._remoteSpriteCache.has(url)) {
|
||||||
|
const sp = CCRemoteSprite._remoteSpriteCache.get(url);
|
||||||
|
sp.addRef();
|
||||||
|
this.spriteFrame = sp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let loadingPromise: Promise<SpriteFrame> = null;
|
||||||
|
if (CCRemoteSprite._loadingSpriteCache.has(url)) {
|
||||||
|
loadingPromise = CCRemoteSprite._loadingSpriteCache.get(url);
|
||||||
|
} else {
|
||||||
|
loadingPromise = new Promise<SpriteFrame>((resolve, reject) => {
|
||||||
|
assetManager.loadRemote(url, (err, asset: ImageAsset) => {
|
||||||
|
if (err) {
|
||||||
|
app.log.error(`loadRemote error: ${url}`, err);
|
||||||
|
CCRemoteSprite._loadingSpriteCache.delete(url);
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
asset.addRef();
|
||||||
|
const texture = new Texture2D();
|
||||||
|
texture.image = asset;
|
||||||
|
const spriteFrame = new SpriteFrame();
|
||||||
|
spriteFrame.texture = texture;
|
||||||
|
spriteFrame.remoteUrl = url;
|
||||||
|
CCRemoteSprite._remoteSpriteCache.set(url, spriteFrame);
|
||||||
|
CCRemoteSprite._loadingSpriteCache.delete(url);
|
||||||
|
resolve(spriteFrame);
|
||||||
|
} catch (createErr) {
|
||||||
|
CCRemoteSprite._loadingSpriteCache.delete(url);
|
||||||
|
reject(createErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
CCRemoteSprite._loadingSpriteCache.set(url, loadingPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sp = await loadingPromise;
|
||||||
|
sp.addRef();
|
||||||
|
// // 检查是否在加载过程中URL发生了变化
|
||||||
|
if (sp && (!isValid(this.node, true) || this._remoteUrl !== url || this.spriteFrame?.remoteUrl === url)) {
|
||||||
|
sp.decRef();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("loadSpriteFrame:", url);
|
||||||
|
this.spriteFrame = sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSize(widthOrHeight: number, height?: number): void {
|
||||||
|
height ??= widthOrHeight;
|
||||||
|
this.sizeMode = Sprite.SizeMode.CUSTOM;
|
||||||
|
this.getComponent(UITransform).setContentSize(widthOrHeight, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public release(): void {
|
||||||
|
if (!nsStringUtils.isEmpty(this.spriteFrame?.remoteUrl)) {
|
||||||
|
this.spriteFrame.decRef();
|
||||||
|
}
|
||||||
|
this.spriteFrame = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onDestroy(): void {
|
||||||
|
this.release();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static checkCache() {
|
||||||
|
// 检查缓存中是否有已加载的SpriteFrame
|
||||||
|
let clearUrls = [];
|
||||||
|
|
||||||
|
for (const [url, spriteFrame] of CCRemoteSprite._remoteSpriteCache) {
|
||||||
|
if (spriteFrame.refCount <= 0) {
|
||||||
|
let texture = spriteFrame.texture as Texture2D;
|
||||||
|
let imageAsset: ImageAsset = null;
|
||||||
|
|
||||||
|
// 如果已加入动态合图,必须取原始的Texture2D
|
||||||
|
if (spriteFrame.packable && spriteFrame.original) {
|
||||||
|
texture = spriteFrame.original._texture as Texture2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取ImageAsset引用
|
||||||
|
if (texture?.image) {
|
||||||
|
imageAsset = texture.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先销毁spriteFrame(这会自动处理对texture的引用)
|
||||||
|
if (spriteFrame.isValid) {
|
||||||
|
spriteFrame.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再销毁texture
|
||||||
|
if (texture?.isValid) {
|
||||||
|
texture.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后减少ImageAsset的引用计数
|
||||||
|
if (imageAsset?.isValid) {
|
||||||
|
imageAsset.decRef();
|
||||||
|
}
|
||||||
|
clearUrls.push(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app.log.log("清理缓存:", clearUrls.length);
|
||||||
|
clearUrls.forEach(url => {
|
||||||
|
CCRemoteSprite._remoteSpriteCache.delete(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,22 @@
|
|||||||
import { _decorator, Sprite } from "cc";
|
import { isValid } from "cc";
|
||||||
import { EDITOR } from "cc/env";
|
import { assetManager, ImageAsset, Texture2D } from "cc";
|
||||||
|
import { SpriteFrame } from "cc";
|
||||||
import { UITransform } from "cc";
|
import { UITransform } from "cc";
|
||||||
|
import { Sprite } from "cc";
|
||||||
|
import { _decorator } from "cc";
|
||||||
|
import { EDITOR } from "cc/env";
|
||||||
import { StringUtils } from "../utils/StringUtils";
|
import { StringUtils } from "../utils/StringUtils";
|
||||||
import { RemoteSpriteCache } from "./RemoteSpriteCache";
|
|
||||||
import LogUtils from "../utils/LogUtils";
|
import LogUtils from "../utils/LogUtils";
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
const CACHE_EXPIRE_TIME = 30000; // 30s 缓存30s
|
||||||
|
const CACHE_CHECK_INTERVAL = 5000; // 5秒检查一次
|
||||||
|
|
||||||
@ccclass("RemoteSprite")
|
@ccclass("RemoteSprite")
|
||||||
export default class RemoteSprite extends Sprite {
|
export class RemoteSprite extends Sprite {
|
||||||
|
private static _remoteSpriteCache: Map<string, SpriteFrame> = new Map();
|
||||||
|
private static _loadingSpriteCache: Map<string, Promise<SpriteFrame>> = new Map();
|
||||||
|
private static _checkTimer: NodeJS.Timeout;
|
||||||
/**
|
/**
|
||||||
* 远程图片URL
|
* 远程图片URL
|
||||||
*/
|
*/
|
||||||
@@ -26,13 +35,13 @@ export default class RemoteSprite extends Sprite {
|
|||||||
const newValue = value || "";
|
const newValue = value || "";
|
||||||
if (this._remoteUrl !== newValue) {
|
if (this._remoteUrl !== newValue) {
|
||||||
this._remoteUrl = newValue;
|
this._remoteUrl = newValue;
|
||||||
if (this._remoteUrl !== this._currentUrl) {
|
if (StringUtils.isEmpty(this._remoteUrl)) {
|
||||||
|
this.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.spriteFrame == null || this._remoteUrl !== this.spriteFrame.remoteUrl) {
|
||||||
this.loadRemoteSprite(this._remoteUrl).catch((err) => {
|
this.loadRemoteSprite(this._remoteUrl).catch((err) => {
|
||||||
LogUtils.error(
|
LogUtils.error("RemoteSprite", `加载远程图片失败: ${this._remoteUrl}`, err);
|
||||||
"RemoteSprite",
|
|
||||||
`加载远程图片失败: ${this._remoteUrl}`,
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
// 可以添加默认图片或错误状态处理
|
// 可以添加默认图片或错误状态处理
|
||||||
if (this.isValid) {
|
if (this.isValid) {
|
||||||
this.spriteFrame = null;
|
this.spriteFrame = null;
|
||||||
@@ -42,29 +51,31 @@ export default class RemoteSprite extends Sprite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 私有属性
|
// override set spriteFrame(value: SpriteFrame) {
|
||||||
private _currentUrl: string = "";
|
// super.spriteFrame = value;
|
||||||
|
// }
|
||||||
|
|
||||||
public onLoad(): void {
|
public onLoad(): void {
|
||||||
super.onLoad();
|
super.onLoad();
|
||||||
if (EDITOR) {
|
if (EDITOR) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RemoteSpriteCache.getInstance().checkAndRegisterSprite(
|
if (!RemoteSprite._checkTimer) {
|
||||||
this._currentUrl,
|
RemoteSprite._checkTimer = setInterval(() => {
|
||||||
this.spriteFrame,
|
RemoteSprite.checkCache();
|
||||||
);
|
}, CACHE_CHECK_INTERVAL);
|
||||||
if (
|
}
|
||||||
!StringUtils.isEmpty(this._remoteUrl) &&
|
|
||||||
StringUtils.isEmpty(this._currentUrl)
|
if (!StringUtils.isEmpty(this.spriteFrame?.remoteUrl)) {
|
||||||
) {
|
this.spriteFrame.addRef();
|
||||||
|
this.spriteFrame.lastAccessTime = Date.now();
|
||||||
|
}
|
||||||
|
if (!StringUtils.isEmpty(this._remoteUrl) && this.spriteFrame?.remoteUrl !== this._remoteUrl) {
|
||||||
this.loadRemoteSprite(this._remoteUrl).catch((err) => {
|
this.loadRemoteSprite(this._remoteUrl).catch((err) => {
|
||||||
LogUtils.error(
|
LogUtils.error("RemoteSprite", `onLoad加载远程图片失败: ${this._remoteUrl}`, err);
|
||||||
"RemoteSprite",
|
|
||||||
`onLoad加载远程图片失败: ${this._remoteUrl}`,
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
} else if (StringUtils.isEmpty(this._remoteUrl) && !StringUtils.isEmpty(this.spriteFrame?.remoteUrl)) {
|
||||||
|
this.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,21 +85,61 @@ export default class RemoteSprite extends Sprite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// URL 相同,且已经加载完成,直接返回
|
// URL 相同,且已经加载完成,直接返回
|
||||||
if (this._currentUrl === url && this.spriteFrame) {
|
if (this.spriteFrame && this.spriteFrame.remoteUrl == url) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RemoteSprite._remoteSpriteCache.has(url)) {
|
||||||
|
const sp = RemoteSprite._remoteSpriteCache.get(url);
|
||||||
|
sp.lastAccessTime = Date.now();
|
||||||
|
sp.addRef();
|
||||||
|
this.release();
|
||||||
|
this.spriteFrame = sp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let loadingPromise: Promise<SpriteFrame> = null;
|
||||||
|
if (RemoteSprite._loadingSpriteCache.has(url)) {
|
||||||
|
loadingPromise = RemoteSprite._loadingSpriteCache.get(url);
|
||||||
|
} else {
|
||||||
|
loadingPromise = new Promise<SpriteFrame>((resolve, reject) => {
|
||||||
|
LogUtils.log("RemoteSprite", `loadRemoteSprite: ${url}`);
|
||||||
|
assetManager.loadRemote(url, (err, asset: ImageAsset) => {
|
||||||
|
if (err) {
|
||||||
|
LogUtils.error(`loadRemote error: ${url}`, err);
|
||||||
|
RemoteSprite._loadingSpriteCache.delete(url);
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
asset.addRef();
|
||||||
|
const texture = new Texture2D();
|
||||||
|
texture.image = asset;
|
||||||
|
const spriteFrame = new SpriteFrame();
|
||||||
|
spriteFrame.texture = texture;
|
||||||
|
spriteFrame.remoteUrl = url;
|
||||||
|
RemoteSprite._remoteSpriteCache.set(url, spriteFrame);
|
||||||
|
RemoteSprite._loadingSpriteCache.delete(url);
|
||||||
|
resolve(spriteFrame);
|
||||||
|
} catch (createErr) {
|
||||||
|
RemoteSprite._loadingSpriteCache.delete(url);
|
||||||
|
reject(createErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
RemoteSprite._loadingSpriteCache.set(url, loadingPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sp = await loadingPromise;
|
||||||
|
sp.addRef();
|
||||||
|
sp.lastAccessTime = Date.now();
|
||||||
|
// // 检查是否在加载过程中URL发生了变化
|
||||||
|
if (sp && (!isValid(this.node, true) || this._remoteUrl !== url || this.spriteFrame?.remoteUrl === url)) {
|
||||||
|
sp.decRef(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("loadSpriteFrame:", url);
|
||||||
this.release();
|
this.release();
|
||||||
const sp = await RemoteSpriteCache.getInstance().loadSpriteFrame(url);
|
|
||||||
|
|
||||||
// 检查是否在加载过程中URL发生了变化
|
|
||||||
if (this._remoteUrl !== url || this._currentUrl === url) {
|
|
||||||
RemoteSpriteCache.getInstance().releaseResource(url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.spriteFrame = sp;
|
this.spriteFrame = sp;
|
||||||
this._currentUrl = url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSize(widthOrHeight: number, height?: number): void {
|
public setSize(widthOrHeight: number, height?: number): void {
|
||||||
@@ -98,10 +149,9 @@ export default class RemoteSprite extends Sprite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public release(): void {
|
public release(): void {
|
||||||
if (!StringUtils.isEmpty(this._currentUrl)) {
|
if (!StringUtils.isEmpty(this.spriteFrame?.remoteUrl)) {
|
||||||
RemoteSpriteCache.getInstance()?.releaseResource(this._currentUrl);
|
this.spriteFrame.decRef(false);
|
||||||
}
|
}
|
||||||
this._currentUrl = "";
|
|
||||||
this.spriteFrame = null;
|
this.spriteFrame = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,4 +159,48 @@ export default class RemoteSprite extends Sprite {
|
|||||||
this.release();
|
this.release();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static checkCache() {
|
||||||
|
// 检查缓存中是否有已加载的SpriteFrame
|
||||||
|
let clearUrls = [];
|
||||||
|
|
||||||
|
let now = Date.now();
|
||||||
|
for (const [url, spriteFrame] of RemoteSprite._remoteSpriteCache) {
|
||||||
|
if (spriteFrame.refCount <= 0 && spriteFrame.lastAccessTime < now - CACHE_EXPIRE_TIME) {
|
||||||
|
let texture = spriteFrame.texture as Texture2D;
|
||||||
|
let imageAsset: ImageAsset = null;
|
||||||
|
|
||||||
|
// 如果已加入动态合图,必须取原始的Texture2D
|
||||||
|
if (spriteFrame.packable && spriteFrame.original) {
|
||||||
|
texture = spriteFrame.original._texture as Texture2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取ImageAsset引用
|
||||||
|
if (texture?.image) {
|
||||||
|
imageAsset = texture.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先销毁spriteFrame(这会自动处理对texture的引用)
|
||||||
|
if (spriteFrame.isValid) {
|
||||||
|
spriteFrame.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再销毁texture
|
||||||
|
if (texture?.isValid) {
|
||||||
|
texture.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后减少ImageAsset的引用计数
|
||||||
|
if (imageAsset?.isValid) {
|
||||||
|
imageAsset.decRef();
|
||||||
|
}
|
||||||
|
clearUrls.push(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearUrls.forEach((url) => {
|
||||||
|
RemoteSprite._remoteSpriteCache.delete(url);
|
||||||
|
});
|
||||||
|
LogUtils.log("清理缓存:", clearUrls.length, RemoteSprite._remoteSpriteCache.size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,4 @@
|
|||||||
import {
|
import { _decorator, SpriteFrame, ImageAsset, Texture2D, assetManager } from "cc";
|
||||||
_decorator,
|
|
||||||
SpriteFrame,
|
|
||||||
ImageAsset,
|
|
||||||
Texture2D,
|
|
||||||
assetManager,
|
|
||||||
} from "cc";
|
|
||||||
import NodeSingleton from "../NodeSingleton";
|
import NodeSingleton from "../NodeSingleton";
|
||||||
import LogUtils from "../utils/LogUtils";
|
import LogUtils from "../utils/LogUtils";
|
||||||
import { StringUtils } from "../utils/StringUtils";
|
import { StringUtils } from "../utils/StringUtils";
|
||||||
@@ -71,7 +65,7 @@ class CacheItem {
|
|||||||
|
|
||||||
const TAG = "RemoteSpriteCache";
|
const TAG = "RemoteSpriteCache";
|
||||||
const CLEANUP_CHECK_INTERVAL = 10; // 10秒检查一次
|
const CLEANUP_CHECK_INTERVAL = 10; // 10秒检查一次
|
||||||
const CACHE_EXPIRE_TIME = 1 * 60 * 1000; // 1分钟
|
const CACHE_EXPIRE_TIME = 1 * 30 * 1000; // 1分钟
|
||||||
|
|
||||||
// 添加最大缓存数量限制
|
// 添加最大缓存数量限制
|
||||||
const MAX_CACHE_SIZE = 100; // 最大缓存数量
|
const MAX_CACHE_SIZE = 100; // 最大缓存数量
|
||||||
@@ -98,13 +92,10 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
/**
|
/**
|
||||||
* 检查并注册精灵
|
* 检查并注册精灵
|
||||||
*/
|
*/
|
||||||
public checkAndRegisterSprite(
|
public checkAndRegisterSprite(spriteFrame: SpriteFrame): boolean {
|
||||||
url: string,
|
if (spriteFrame && !StringUtils.isEmpty(spriteFrame.remoteUrl)) {
|
||||||
spriteFrame: SpriteFrame,
|
const cacheItem = this._cache.get(spriteFrame.remoteUrl);
|
||||||
): boolean {
|
if (cacheItem) {
|
||||||
if (spriteFrame && !StringUtils.isEmpty(url)) {
|
|
||||||
const cacheItem = this._cache.get(url);
|
|
||||||
if (cacheItem && cacheItem.spriteFrame === spriteFrame) {
|
|
||||||
cacheItem.refCount++;
|
cacheItem.refCount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -115,10 +106,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
protected update(dt: number): void {
|
protected update(dt: number): void {
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
// 每隔指定时间检查一次过期资源
|
// 每隔指定时间检查一次过期资源
|
||||||
if (
|
if (currentTime - this._lastCleanupTime >= CLEANUP_CHECK_INTERVAL * 1000) {
|
||||||
currentTime - this._lastCleanupTime >=
|
|
||||||
CLEANUP_CHECK_INTERVAL * 1000
|
|
||||||
) {
|
|
||||||
this.cleanupUnusedResources();
|
this.cleanupUnusedResources();
|
||||||
this._lastCleanupTime = currentTime;
|
this._lastCleanupTime = currentTime;
|
||||||
}
|
}
|
||||||
@@ -130,16 +118,10 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
public async loadSpriteFrame(url: string): Promise<SpriteFrame> {
|
public async loadSpriteFrame(url: string): Promise<SpriteFrame> {
|
||||||
let cacheItem = this._cache.get(url);
|
let cacheItem = this._cache.get(url);
|
||||||
if (cacheItem) {
|
if (cacheItem) {
|
||||||
if (
|
if (cacheItem.loadState === LoadState.LOADED && cacheItem.spriteFrame) {
|
||||||
cacheItem.loadState === LoadState.LOADED &&
|
|
||||||
cacheItem.spriteFrame
|
|
||||||
) {
|
|
||||||
cacheItem.refCount++;
|
cacheItem.refCount++;
|
||||||
return cacheItem.spriteFrame;
|
return cacheItem.spriteFrame;
|
||||||
} else if (
|
} else if (cacheItem.loadState === LoadState.LOADING && cacheItem.loadPromise) {
|
||||||
cacheItem.loadState === LoadState.LOADING &&
|
|
||||||
cacheItem.loadPromise
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
const spriteFrame = await cacheItem.loadPromise;
|
const spriteFrame = await cacheItem.loadPromise;
|
||||||
if (spriteFrame) {
|
if (spriteFrame) {
|
||||||
@@ -155,14 +137,8 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果加载失败且重试次数未达到上限,重新尝试
|
// 如果加载失败且重试次数未达到上限,重新尝试
|
||||||
if (
|
if (cacheItem.loadState === LoadState.FAILED && cacheItem.retryCount < MAX_RETRY_COUNT) {
|
||||||
cacheItem.loadState === LoadState.FAILED &&
|
LogUtils.warn(TAG, `重试加载: ${url}, 第${cacheItem.retryCount + 1}次`);
|
||||||
cacheItem.retryCount < MAX_RETRY_COUNT
|
|
||||||
) {
|
|
||||||
LogUtils.warn(
|
|
||||||
TAG,
|
|
||||||
`重试加载: ${url}, 第${cacheItem.retryCount + 1}次`,
|
|
||||||
);
|
|
||||||
cacheItem.incrementRetry();
|
cacheItem.incrementRetry();
|
||||||
return this.doLoadSpriteFrame(url, cacheItem);
|
return this.doLoadSpriteFrame(url, cacheItem);
|
||||||
}
|
}
|
||||||
@@ -178,10 +154,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
return this.doLoadSpriteFrame(url, cacheItem);
|
return this.doLoadSpriteFrame(url, cacheItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async doLoadSpriteFrame(
|
private async doLoadSpriteFrame(url: string, cacheItem: CacheItem): Promise<SpriteFrame> {
|
||||||
url: string,
|
|
||||||
cacheItem: CacheItem,
|
|
||||||
): Promise<SpriteFrame> {
|
|
||||||
cacheItem.loadState = LoadState.LOADING;
|
cacheItem.loadState = LoadState.LOADING;
|
||||||
cacheItem.setLoadStartTime();
|
cacheItem.setLoadStartTime();
|
||||||
|
|
||||||
@@ -193,6 +166,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
reject(new Error(`加载超时: ${url}`));
|
reject(new Error(`加载超时: ${url}`));
|
||||||
}, LOAD_TIMEOUT);
|
}, LOAD_TIMEOUT);
|
||||||
|
|
||||||
|
console.log(`开始加载资源: ${url}`);
|
||||||
assetManager.loadRemote(url, (err, asset: ImageAsset) => {
|
assetManager.loadRemote(url, (err, asset: ImageAsset) => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
@@ -209,6 +183,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
const spriteFrame = new SpriteFrame();
|
const spriteFrame = new SpriteFrame();
|
||||||
spriteFrame.texture = texture;
|
spriteFrame.texture = texture;
|
||||||
spriteFrame.addRef();
|
spriteFrame.addRef();
|
||||||
|
spriteFrame.remoteUrl = url;
|
||||||
|
|
||||||
cacheItem.refCount++;
|
cacheItem.refCount++;
|
||||||
cacheItem.spriteFrame = spriteFrame;
|
cacheItem.spriteFrame = spriteFrame;
|
||||||
@@ -218,11 +193,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
|
|
||||||
resolve(spriteFrame);
|
resolve(spriteFrame);
|
||||||
} catch (createErr) {
|
} catch (createErr) {
|
||||||
LogUtils.error(
|
LogUtils.error(TAG, `创建SpriteFrame失败: ${url}`, createErr);
|
||||||
TAG,
|
|
||||||
`创建SpriteFrame失败: ${url}`,
|
|
||||||
createErr,
|
|
||||||
);
|
|
||||||
cacheItem.loadState = LoadState.FAILED;
|
cacheItem.loadState = LoadState.FAILED;
|
||||||
cacheItem.loadPromise = null;
|
cacheItem.loadPromise = null;
|
||||||
reject(createErr);
|
reject(createErr);
|
||||||
@@ -242,6 +213,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
const cacheItem = this._cache.get(url);
|
const cacheItem = this._cache.get(url);
|
||||||
if (cacheItem) {
|
if (cacheItem) {
|
||||||
cacheItem.refCount--;
|
cacheItem.refCount--;
|
||||||
|
console.log(`释放资源引用: ${url}, 引用计数: ${cacheItem.refCount}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,11 +272,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
private cleanupByUsageTime(targetSize: number): void {
|
private cleanupByUsageTime(targetSize: number): void {
|
||||||
// 直接筛选并排序需要清理的资源
|
// 直接筛选并排序需要清理的资源
|
||||||
const entriesToClean = Array.from(this._cache.entries())
|
const entriesToClean = Array.from(this._cache.entries())
|
||||||
.filter(
|
.filter(([_, cacheItem]) => cacheItem.refCount <= 0 && cacheItem.loadState === LoadState.LOADED)
|
||||||
([_, cacheItem]) =>
|
|
||||||
cacheItem.refCount <= 0 &&
|
|
||||||
cacheItem.loadState === LoadState.LOADED,
|
|
||||||
)
|
|
||||||
.sort((a, b) => a[1].lastAccessTime - b[1].lastAccessTime);
|
.sort((a, b) => a[1].lastAccessTime - b[1].lastAccessTime);
|
||||||
|
|
||||||
let cleanedCount = 0;
|
let cleanedCount = 0;
|
||||||
@@ -343,10 +311,7 @@ export class RemoteSpriteCache extends NodeSingleton {
|
|||||||
let imageAsset: ImageAsset = null;
|
let imageAsset: ImageAsset = null;
|
||||||
|
|
||||||
// 如果已加入动态合图,必须取原始的Texture2D
|
// 如果已加入动态合图,必须取原始的Texture2D
|
||||||
if (
|
if (cacheItem.spriteFrame.packable && cacheItem.spriteFrame.original) {
|
||||||
cacheItem.spriteFrame.packable &&
|
|
||||||
cacheItem.spriteFrame.original
|
|
||||||
) {
|
|
||||||
texture = cacheItem.spriteFrame.original._texture as Texture2D;
|
texture = cacheItem.spriteFrame.original._texture as Texture2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user