157 lines
4.8 KiB
TypeScript
157 lines
4.8 KiB
TypeScript
import { _decorator, Component, Node, Prefab, instantiate, v3, Vec3 } from 'cc';
|
|
import { Icon } from './Icon';
|
|
import { ICON_STATE } from './Define';
|
|
import { NodePoolManager } from '../../../Loading/scripts/manager/NodePoolManager';
|
|
|
|
const { ccclass, property, executeInEditMode } = _decorator;
|
|
|
|
@ccclass('IconFactory')
|
|
@executeInEditMode
|
|
export class IconFactory extends Component {
|
|
@property({ type: [Prefab] })
|
|
prefabs: Prefab[] = [];
|
|
|
|
// 性能优化相关常量
|
|
private static readonly INIT_POOL_SIZE = 6; // 每种图标初始池大小
|
|
private static readonly BATCH_CREATE_SIZE = 5; // 批量创建数量
|
|
|
|
// 活跃图标追踪
|
|
private activeIcons: Set<Node> = new Set();
|
|
// 创建计数
|
|
private createCounter: number[] = [];
|
|
// 初始化标记
|
|
private isInitialized: boolean = false;
|
|
// 初始化坐标
|
|
private initPos: Vec3 = v3(0, 0, 0);
|
|
|
|
// 初始化
|
|
init() {
|
|
if (this.isInitialized) return;
|
|
|
|
// 初始化计数器
|
|
this.createCounter = new Array(this.prefabs.length).fill(0);
|
|
|
|
// 预热对象池
|
|
this.warmupPools();
|
|
|
|
this.isInitialized = true;
|
|
}
|
|
|
|
// 预热对象池
|
|
private warmupPools() {
|
|
// 为每种图标预创建一定数量的节点
|
|
for (let i = 0; i < this.prefabs.length; i++) {
|
|
const poolName = `Icon_${i}`;
|
|
|
|
// 批量创建节点到对象池
|
|
for (let j = 0; j < IconFactory.INIT_POOL_SIZE; j++) {
|
|
const node = instantiate(this.prefabs[i]);
|
|
const iconComp = node.getComponent(Icon) || node.addComponent(Icon);
|
|
iconComp.index = i;
|
|
// 确保第一次初始化
|
|
iconComp.initIcon(i);
|
|
NodePoolManager.instance.putNodeToPool(poolName, node);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 创建图标
|
|
icfactoryCreateIcon(index: number): Node {
|
|
// 参数检查
|
|
if (index == null || index == undefined || index < 0) {
|
|
console.error(`IconFactory createIcon Error: ${index}`);
|
|
index = 0;
|
|
}
|
|
|
|
// 确保已初始化
|
|
if (!this.isInitialized) {
|
|
this.init();
|
|
}
|
|
|
|
// 从对象池获取或创建节点
|
|
const iconNode = NodePoolManager.instance.getNodeFromPoolStatic(
|
|
`Icon_${index}`,
|
|
this.prefabs[index]
|
|
);
|
|
|
|
// 获取或添加Icon组件
|
|
const iconComp = iconNode.getComponent(Icon) || iconNode.addComponent(Icon);
|
|
iconComp.index = index;
|
|
// 确保初始化
|
|
iconComp.initIcon(index);
|
|
iconNode.setPosition(this.initPos);
|
|
|
|
// 更新计数和跟踪
|
|
this.createCounter[index]++;
|
|
this.activeIcons.add(iconNode);
|
|
|
|
// 检查是否需要补充对象池
|
|
this.checkAndReplenishPool(index);
|
|
|
|
return iconNode;
|
|
}
|
|
|
|
// 检查并补充对象池
|
|
private checkAndReplenishPool(index: number) {
|
|
const poolName = `Icon_${index}`;
|
|
const pool = NodePoolManager.instance.getNodePoolByName(poolName);
|
|
|
|
// 如果池中节点较少,补充新节点
|
|
if (pool && pool.size() < IconFactory.INIT_POOL_SIZE / 2) {
|
|
for (let i = 0; i < IconFactory.BATCH_CREATE_SIZE; i++) {
|
|
const node = instantiate(this.prefabs[index]);
|
|
const iconComp = node.getComponent(Icon) || node.addComponent(Icon);
|
|
iconComp.index = index;
|
|
iconComp.initIcon(index);
|
|
NodePoolManager.instance.putNodeToPool(poolName, node);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 回收图标
|
|
recycleIcon(icon: Node) {
|
|
if (!icon) {
|
|
console.error(`IconFactory.recycleIcon null`);
|
|
return;
|
|
}
|
|
|
|
const iconComp = icon.getComponent(Icon);
|
|
if (!iconComp) return;
|
|
|
|
const index = iconComp.index;
|
|
if (index >= 0) {
|
|
// 重置节点状态
|
|
this.resetNode(icon);
|
|
// 从活跃集合中移除
|
|
this.activeIcons.delete(icon);
|
|
// 放回对象池
|
|
NodePoolManager.instance.putNodeToPool(`Icon_${index}`, icon);
|
|
}
|
|
}
|
|
|
|
// 重置节点状态
|
|
resetNode(icon: Node) {
|
|
const iconComp = icon.getComponent(Icon);
|
|
if (iconComp) {
|
|
iconComp.changeIconState(ICON_STATE.IDLE);
|
|
iconComp.showFastIcon(false);
|
|
icon.setScale(1, 1, 1);
|
|
}
|
|
}
|
|
|
|
// 获取图标数量
|
|
getIconNum(): number {
|
|
return this.prefabs.length;
|
|
}
|
|
|
|
// 清理资源
|
|
onDestroy() {
|
|
// 回收所有活跃图标
|
|
this.activeIcons.forEach(icon => {
|
|
this.recycleIcon(icon);
|
|
});
|
|
this.activeIcons.clear();
|
|
this.createCounter = [];
|
|
this.isInitialized = false;
|
|
}
|
|
} |