pinball/assets/_Game/Scripts/Pool/ObjectPool.ts

130 lines
4.0 KiB
TypeScript
Raw Normal View History

2024-03-06 07:10:31 -08:00
import { Component, Node, Prefab, director, instantiate } from 'cc';
import IPoolable from './IPoolable';
2024-03-28 20:35:44 -07:00
import { error } from 'cc';
2024-03-06 01:28:01 -08:00
2024-03-06 03:09:17 -08:00
export default class ObjectPool {
2024-03-11 04:12:22 -07:00
private _inactive: Node[] = [];
2024-03-06 01:28:01 -08:00
private _actives: Node[] = [];
private _prefab: Prefab;
private _expandable;
2024-03-06 07:10:31 -08:00
private _poolHandlerComp: new () => any;
2024-03-06 01:28:01 -08:00
2024-04-01 19:26:53 -07:00
public get actives() {
return [...this._actives];
}
public get inActives() {
return [...this._inactive];
}
public get all() {
2024-03-11 04:12:22 -07:00
return [...this._actives, ...this._inactive];
}
2024-03-06 01:28:01 -08:00
public get countInactive() {
2024-03-11 04:12:22 -07:00
return this._inactive.length;
2024-03-06 01:28:01 -08:00
}
public get countActive() {
return this._actives.length;
}
public get countAll() {
return this.countInactive + this.countActive;
}
2024-03-06 07:10:31 -08:00
constructor(prefab: Prefab, size: number, expandable = true, poolHandlerComp?: new () => any | string) {
2024-03-28 20:35:44 -07:00
if (!!!prefab) {
console.error('prefab cant be null or undefine');
return;
}
2024-03-06 01:28:01 -08:00
this._prefab = prefab;
2024-03-06 07:10:31 -08:00
this._expandable = expandable;
this._poolHandlerComp = poolHandlerComp;
2024-03-06 01:28:01 -08:00
for (let i = 0; i < size; ++i) {
let obj = instantiate(this._prefab); // create node instance
2024-03-06 07:10:31 -08:00
obj.removeFromParent();
2024-03-11 04:12:22 -07:00
this._inactive.push(obj);
2024-03-07 09:45:13 -08:00
ObjectPool._poolLookUp[obj.uuid] = this;
2024-03-06 01:28:01 -08:00
}
}
2024-03-07 09:45:13 -08:00
//#region Static
private static _poolLookUp: { [key: string]: ObjectPool } = {};
public static release(obj: Node) {
ObjectPool._poolLookUp[obj.uuid].release(obj);
}
//#endregion
2024-03-06 03:09:17 -08:00
public get(parent?: Node): Node;
2024-03-06 07:10:31 -08:00
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T;
public get<T extends Component>(parent?: Node, classConstructor?: new () => T): T | Node {
2024-03-28 20:35:44 -07:00
if (!!!this._prefab) {
console.error('prefab cant be null or undefine');
return;
}
2024-03-06 01:28:01 -08:00
let obj: Node = null;
let p = parent || director.getScene();
2024-03-11 04:12:22 -07:00
if (this._inactive.length > 0) {
2024-03-06 07:10:31 -08:00
// Pop the last object in pool
2024-03-11 04:12:22 -07:00
obj = this._inactive.pop();
2024-03-06 01:28:01 -08:00
} else if (this._expandable) {
// if not enough node in the pool, we call cc.instantiate to create node
obj = instantiate(this._prefab);
2024-03-07 09:45:13 -08:00
ObjectPool._poolLookUp[obj.uuid] = this;
2024-03-06 01:28:01 -08:00
} else {
2024-03-06 03:09:17 -08:00
obj = this._actives.shift();
2024-03-28 20:35:44 -07:00
obj.removeFromParent();
2024-03-06 01:28:01 -08:00
}
2024-03-06 07:10:31 -08:00
obj.setParent(p);
this._actives.push(obj);
// Invoke pool handler
const handler = this._poolHandlerComp ? obj.getComponent(this._poolHandlerComp) : null;
if (handler) {
2024-03-10 03:12:55 -07:00
(handler as unknown as IPoolable)?.onGet();
2024-03-06 07:10:31 -08:00
}
2024-03-06 03:09:17 -08:00
if (classConstructor) {
2024-03-06 07:10:31 -08:00
return handler == classConstructor ? handler : obj.getComponent(classConstructor);
2024-03-06 03:09:17 -08:00
}
return obj;
2024-03-06 01:28:01 -08:00
}
2024-03-06 07:10:31 -08:00
public release(obj: Node): void;
public release<T extends Component>(obj: T): void;
public release<T extends Component>(obj: T | Node): void {
let node = obj instanceof Node ? obj : obj.node;
const index = this._actives.indexOf(node);
2024-03-11 04:12:22 -07:00
2024-03-06 07:10:31 -08:00
//check obj is belongs to pool
if (index === -1) return;
this._actives.splice(index, 1);
2024-03-11 04:12:22 -07:00
this._inactive.push(node);
2024-03-06 07:10:31 -08:00
// Invoke pool handler
const handler = this._poolHandlerComp ? node.getComponent(this._poolHandlerComp) : null;
if (handler) {
2024-03-10 03:12:55 -07:00
(handler as unknown as IPoolable)?.onRelease();
2024-03-06 03:09:17 -08:00
}
2024-03-06 07:10:31 -08:00
// Remove from parent, but don't cleanup
node.removeFromParent();
2024-03-06 01:28:01 -08:00
}
public clear() {
2024-03-11 04:12:22 -07:00
this.all.forEach((obj) => obj.destroy());
this._inactive = [];
2024-03-06 01:28:01 -08:00
this._actives = [];
2024-03-07 09:45:13 -08:00
Object.keys(ObjectPool._poolLookUp).forEach((key) => {
if (ObjectPool._poolLookUp[key] === this) {
delete ObjectPool._poolLookUp[key];
}
});
2024-03-06 01:28:01 -08:00
}
2024-03-11 04:12:22 -07:00
public releaseAll() {
this.all.forEach((obj) => this.release(obj));
}
2024-03-06 01:28:01 -08:00
}