对ECS系统进行注释、移除JobSystem
This commit is contained in:
@@ -1,79 +1,103 @@
|
||||
module es {
|
||||
/**
|
||||
* 用于池任何对象
|
||||
*/
|
||||
export class Pool {
|
||||
private static _objectQueue: Map<any, any[]> = new Map();
|
||||
private static _objectQueue = new Map<new () => any, any[]>();
|
||||
|
||||
/**
|
||||
* 预热缓存,使用最大的cacheCount对象填充缓存
|
||||
* @param type
|
||||
* @param cacheCount
|
||||
* @param type 要预热的类型
|
||||
* @param cacheCount 预热缓存数量
|
||||
*/
|
||||
public static warmCache<T>(type: new (...args) => T, cacheCount: number) {
|
||||
public static warmCache<T>(type: new (...args: any[]) => T, cacheCount: number) {
|
||||
this.checkCreate(type);
|
||||
cacheCount -= this._objectQueue.get(type).length;
|
||||
const queue = this._objectQueue.get(type);
|
||||
cacheCount -= queue.length;
|
||||
|
||||
// 如果需要预热更多的对象,则创建并添加到缓存
|
||||
if (cacheCount > 0) {
|
||||
for (let i = 0; i < cacheCount; i++) {
|
||||
this._objectQueue.get(type).push(new type());
|
||||
queue.push(new type());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将缓存修剪为cacheCount项目
|
||||
* @param cacheCount
|
||||
*/
|
||||
* 将缓存修剪为cacheCount项目
|
||||
* @param type 要修剪的类型
|
||||
* @param cacheCount 修剪后的缓存数量
|
||||
*/
|
||||
public static trimCache<T>(type: new (...args) => T, cacheCount: number) {
|
||||
this.checkCreate(type);
|
||||
while (cacheCount > this._objectQueue.get(type).length)
|
||||
this._objectQueue.get(type).splice(0, 1);
|
||||
const objectQueue = this._objectQueue.get(type);
|
||||
|
||||
// 如果需要修剪缓存,则弹出多余的对象
|
||||
while (cacheCount < objectQueue.length) {
|
||||
objectQueue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
* @param type 要清除缓存的类型
|
||||
*/
|
||||
public static clearCache<T>(type: new (...args) => T) {
|
||||
this.checkCreate(type);
|
||||
this._objectQueue.get(type).length = 0;
|
||||
const objectQueue = this._objectQueue.get(type);
|
||||
|
||||
// 清空缓存数组
|
||||
objectQueue.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果可以的话,从堆栈中弹出一个项
|
||||
* 如果可以的话,从缓存中获取一个对象
|
||||
* @param type 要获取的类型
|
||||
*/
|
||||
public static obtain<T>(type: new (...args) => T): T {
|
||||
this.checkCreate(type);
|
||||
if (this._objectQueue.get(type).length > 0)
|
||||
return this._objectQueue.get(type).shift();
|
||||
const objectQueue = this._objectQueue.get(type);
|
||||
|
||||
// 如果缓存中有对象,弹出一个并返回
|
||||
if (objectQueue.length > 0) {
|
||||
return objectQueue.pop();
|
||||
}
|
||||
|
||||
// 如果没有缓存对象,则创建一个新的对象并返回
|
||||
return new type() as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将项推回堆栈
|
||||
* @param obj
|
||||
* 将对象推回缓存
|
||||
* @param type 对象的类型
|
||||
* @param obj 要推回的对象
|
||||
*/
|
||||
public static free<T>(type: new (...args) => T, obj: T) {
|
||||
this.checkCreate(type);
|
||||
this._objectQueue.get(type).push(obj);
|
||||
const objectQueue = this._objectQueue.get(type);
|
||||
|
||||
// 将对象推回缓存
|
||||
objectQueue.push(obj);
|
||||
|
||||
// 如果对象实现了IPoolable接口,则调用reset方法重置对象
|
||||
if (isIPoolable(obj)) {
|
||||
obj["reset"]();
|
||||
obj.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private static checkCreate<T>(type: new (...args) => T) {
|
||||
if (!this._objectQueue.has(type))
|
||||
/**
|
||||
* 检查缓存中是否已存在给定类型的对象池,如果不存在则创建一个
|
||||
* @param type 要检查的类型
|
||||
*/
|
||||
private static checkCreate<T>(type: new (...args: any[]) => T) {
|
||||
if (!this._objectQueue.has(type)) {
|
||||
this._objectQueue.set(type, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface IPoolable {
|
||||
/**
|
||||
* 重置对象以供重用。对象引用应该为空,字段可以设置为默认值
|
||||
*/
|
||||
reset();
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
export var isIPoolable = (props: any): props is IPoolable => typeof (props as IPoolable)['reset'] !== 'undefined';
|
||||
export const isIPoolable = (props: any): props is IPoolable => {
|
||||
return typeof props.reset === 'function';
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,7 @@ module es {
|
||||
* CoroutineManager用于隐藏Coroutine所需数据的内部类
|
||||
*/
|
||||
export class CoroutineImpl implements ICoroutine, IPoolable {
|
||||
public enumerator: Generator;
|
||||
public enumerator;
|
||||
|
||||
/**
|
||||
* 每当产生一个延迟,它就会被添加到跟踪延迟的waitTimer中
|
||||
@@ -50,11 +50,11 @@ module es {
|
||||
* 立即停止并清除所有协程
|
||||
*/
|
||||
public clearAllCoroutines() {
|
||||
for (let i = 0; i < this._unblockedCoroutines.length; i ++) {
|
||||
for (let i = 0; i < this._unblockedCoroutines.length; i++) {
|
||||
Pool.free(CoroutineImpl, this._unblockedCoroutines[i]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._shouldRunNextFrame.length; i ++) {
|
||||
for (let i = 0; i < this._shouldRunNextFrame.length; i++) {
|
||||
Pool.free(CoroutineImpl, this._shouldRunNextFrame[i]);
|
||||
}
|
||||
|
||||
@@ -67,60 +67,72 @@ module es {
|
||||
* Coroutine在每一帧调用Update之前被执行
|
||||
* @param enumerator
|
||||
*/
|
||||
public startCoroutine(enumerator: any) {
|
||||
// 找到或创建一个CoroutineImpl
|
||||
let coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
|
||||
public startCoroutine<T>(enumerator: Iterator<T> | (() => Iterator<T>)): CoroutineImpl | null {
|
||||
const coroutine = this.getOrCreateCoroutine();
|
||||
coroutine.prepareForUse();
|
||||
coroutine.enumerator = typeof enumerator === 'function' ? enumerator() : enumerator;
|
||||
|
||||
// 设置coroutine并添加它
|
||||
coroutine.enumerator = enumerator;
|
||||
let shouldContinueCoroutine = this.tickCoroutine(coroutine);
|
||||
if (this.tickCoroutine(coroutine)) {
|
||||
this.addCoroutine(coroutine);
|
||||
return coroutine;
|
||||
}
|
||||
|
||||
if (!shouldContinueCoroutine)
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
private getOrCreateCoroutine(): CoroutineImpl {
|
||||
const coroutine = Pool.obtain<CoroutineImpl>(CoroutineImpl);
|
||||
coroutine.prepareForUse();
|
||||
return coroutine;
|
||||
}
|
||||
|
||||
private addCoroutine(coroutine: CoroutineImpl) {
|
||||
if (this._isInUpdate)
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
else
|
||||
this._unblockedCoroutines.push(coroutine);
|
||||
|
||||
return coroutine;
|
||||
}
|
||||
|
||||
public update() {
|
||||
this._isInUpdate = true;
|
||||
for (let i = 0; i < this._unblockedCoroutines.length; i++) {
|
||||
let coroutine = this._unblockedCoroutines[i];
|
||||
|
||||
const unblockedCoroutines = this._unblockedCoroutines;
|
||||
const shouldRunNextFrame = this._shouldRunNextFrame;
|
||||
|
||||
for (let i = unblockedCoroutines.length - 1; i >= 0; i--) {
|
||||
const coroutine = unblockedCoroutines[i];
|
||||
|
||||
if (coroutine.isDone) {
|
||||
Pool.free(CoroutineImpl, coroutine);
|
||||
unblockedCoroutines.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (coroutine.waitForCoroutine != null) {
|
||||
if (coroutine.waitForCoroutine.isDone) {
|
||||
const waitForCoroutine = coroutine.waitForCoroutine;
|
||||
if (waitForCoroutine != null) {
|
||||
if (waitForCoroutine.isDone) {
|
||||
coroutine.waitForCoroutine = null;
|
||||
} else {
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
shouldRunNextFrame.push(coroutine);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (coroutine.waitTimer > 0) {
|
||||
const waitTimer = coroutine.waitTimer;
|
||||
if (waitTimer > 0) {
|
||||
// 递减,然后再运行下一帧,确保用适当的deltaTime递减
|
||||
coroutine.waitTimer -= coroutine.useUnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
coroutine.waitTimer = waitTimer - (coroutine.useUnscaledDeltaTime ? Time.unscaledDeltaTime : Time.deltaTime);
|
||||
shouldRunNextFrame.push(coroutine);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.tickCoroutine(coroutine))
|
||||
this._shouldRunNextFrame.push(coroutine);
|
||||
if (this.tickCoroutine(coroutine)) {
|
||||
shouldRunNextFrame.push(coroutine);
|
||||
}
|
||||
}
|
||||
|
||||
let linqCoroutines = new es.List(this._unblockedCoroutines);
|
||||
linqCoroutines.clear();
|
||||
linqCoroutines.addRange(this._shouldRunNextFrame);
|
||||
this._shouldRunNextFrame.length = 0;
|
||||
unblockedCoroutines.push(...shouldRunNextFrame);
|
||||
shouldRunNextFrame.length = 0;
|
||||
|
||||
this._isInUpdate = false;
|
||||
}
|
||||
@@ -130,47 +142,57 @@ module es {
|
||||
* @param coroutine
|
||||
*/
|
||||
public tickCoroutine(coroutine: CoroutineImpl) {
|
||||
let chain = coroutine.enumerator.next();
|
||||
if (chain.done || coroutine.isDone) {
|
||||
const { enumerator } = coroutine;
|
||||
const { value, done } = enumerator.next();
|
||||
|
||||
if (done || coroutine.isDone) {
|
||||
// 当协程执行完或标记为结束时,回收协程实例并返回 false。
|
||||
Pool.free(CoroutineImpl, coroutine);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chain.value == null) {
|
||||
// 下一帧再运行
|
||||
if (!value) {
|
||||
// 如果下一帧没有指定任务,返回 true 让协程继续等待下一帧执行。
|
||||
return true;
|
||||
}
|
||||
|
||||
if (chain.value instanceof WaitForSeconds) {
|
||||
coroutine.waitTimer = chain.value.waitTime;
|
||||
if (value instanceof WaitForSeconds) {
|
||||
// 如果下一帧需要等待指定时间,则记录等待时间并返回 true。
|
||||
coroutine.waitTimer = value.waitTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof chain.value == 'number') {
|
||||
coroutine.waitTimer = chain.value;
|
||||
if (typeof value === 'number') {
|
||||
// 如果下一帧需要等待指定时间,则记录等待时间并返回 true。
|
||||
coroutine.waitTimer = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof chain.value == 'string') {
|
||||
if (chain.value == 'break') {
|
||||
if (typeof value === 'string') {
|
||||
// 如果下一帧返回 'break',标记协程为结束并返回 false。
|
||||
if (value === 'break') {
|
||||
Pool.free(CoroutineImpl, coroutine);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 否则返回 true 让协程继续等待下一帧执行。
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof chain.value == 'function') {
|
||||
coroutine.waitForCoroutine = this.startCoroutine(chain.value);
|
||||
if (typeof value === 'function') {
|
||||
// 如果下一帧需要等待另一个协程完成,启动并记录另一个协程实例,并返回 true。
|
||||
coroutine.waitForCoroutine = this.startCoroutine(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (chain.value instanceof CoroutineImpl) {
|
||||
coroutine.waitForCoroutine = chain.value;
|
||||
return true;
|
||||
} else {
|
||||
if (value instanceof CoroutineImpl) {
|
||||
// 如果下一帧需要等待另一个协程完成,记录另一个协程实例,并返回 true。
|
||||
coroutine.waitForCoroutine = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 否则返回 true 让协程继续等待下一帧执行。
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,11 @@ module es {
|
||||
*/
|
||||
export class Emitter<T> {
|
||||
private _messageTable: Map<T, FuncPack[]>;
|
||||
|
||||
|
||||
constructor() {
|
||||
this._messageTable = new Map<T, FuncPack[]>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始监听项
|
||||
* @param eventType 监听类型
|
||||
@@ -31,16 +31,17 @@ module es {
|
||||
* @param context 监听上下文
|
||||
*/
|
||||
public addObserver(eventType: T, handler: Function, context: any) {
|
||||
let list: FuncPack[] = this._messageTable.get(eventType);
|
||||
let list = this._messageTable.get(eventType);
|
||||
if (!list) {
|
||||
list = [];
|
||||
this._messageTable.set(eventType, list);
|
||||
}
|
||||
|
||||
Insist.isFalse(list.findIndex(funcPack => funcPack.func == handler) != -1, "您试图添加相同的观察者两次");
|
||||
list.push(new FuncPack(handler, context));
|
||||
|
||||
if (!this.hasObserver(eventType, handler)) {
|
||||
list.push(new FuncPack(handler, context));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 移除监听项
|
||||
* @param eventType 事件类型
|
||||
@@ -48,22 +49,35 @@ module es {
|
||||
*/
|
||||
public removeObserver(eventType: T, handler: Function) {
|
||||
let messageData = this._messageTable.get(eventType);
|
||||
let index = messageData.findIndex(data => data.func == handler);
|
||||
if (index != -1)
|
||||
messageData.splice(index, 1);
|
||||
if (messageData) {
|
||||
let index = messageData.findIndex(data => data.func == handler);
|
||||
if (index != -1)
|
||||
messageData.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 触发该事件
|
||||
* @param eventType 事件类型
|
||||
* @param data 事件数据
|
||||
*/
|
||||
public emit(eventType: T, ...data: any[]) {
|
||||
let list: FuncPack[] = this._messageTable.get(eventType);
|
||||
let list = this._messageTable.get(eventType);
|
||||
if (list) {
|
||||
for (let i = list.length - 1; i >= 0; i--)
|
||||
list[i].func.call(list[i].context, ...data);
|
||||
for (let observer of list) {
|
||||
observer.func.call(observer.context, ...data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在该类型的观察者
|
||||
* @param eventType 事件类型
|
||||
* @param handler 事件函数
|
||||
*/
|
||||
public hasObserver(eventType: T, handler: Function): boolean {
|
||||
let list = this._messageTable.get(eventType);
|
||||
return list ? list.some(observer => observer.func === handler) : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user