import { Thing } from "./thing"; import { IComponent, Component } from './component'; import { Undefinable, Nullable } from '../utils/types'; import { ITimer } from ".."; export interface IObjectAdapter { createHostObject: Function; } export interface IEntityOptions { objectAdapter?: IObjectAdapter; [key: string]: any; } export interface IRunEvent { init: Function; beforeupdate: Function; afterupdate: Function; } /** * 场景的编译,当改变属性的时候应该实时的更新模型的属性状态,最终编译的时候已经转换到THREE * entity下的object是固定的Object3D,当他的组件形成构成新的模型都是放在object3d * Component下的renderObject是变动的模型,大部分和ctype相关 */ export class Entity extends Thing implements IRunEvent { _components: IComponent[] = []; _componentMap: Map = new Map(); objectAdapter: Undefinable; object: any; _compileCache: any = {}; //是否需要更新 constructor(options: IEntityOptions = {}) { super(options); this.objectAdapter = options.objectAdapter; if (this.objectAdapter) this.object = this.objectAdapter.createHostObject() this.init(); } init() { //TODO 接口 } get components() { return this._components; } /** * 添加组件 * @param com 组件 * @returns 是否添加成功 */ addComponent(com: IComponent | Component): boolean { com.entity = this; const i = this._components.indexOf(com); if (i < 0 || (i >= 0 && !com.isSingle)) { this._components.push(com); com.ioe = this._components.length - 1; if (com.isSingle) this._componentMap.set((com as Component).className, com) else { if (!this._componentMap.has((com as Component).className)) this._componentMap.set((com as Component).className, [com]) else (this._componentMap.get((com).className) as Array).push(com) } (com as Component).fire('addToEntity', this); return true; } return false; } removeComponent(com: IComponent): Nullable { const i = this._components.indexOf(com); let removeObj = null; if (i >= 0) { if (com.isSingle) this._componentMap.delete((com as Component).name); else { const coms: Array = this._componentMap.get((com as Component)) as Component[] if (coms.length > 1) { const ci = coms.indexOf(com); if (ci !== -1) removeObj = coms.splice(ci, 1)[0]; } else { removeObj = (this._componentMap.get((com as Component)) as any)[0] this._componentMap.delete((com as Component).className) } } removeObj = this._components.splice(i, 1)[0]; (com as Component).fire('removeToEntity', this); } return removeObj; } updateComponents() { for (let i = 0; i < this._components.length; i++) { const component: IComponent = this._components[i]; component.nextStep(this); } } //三个接口 beforeupdate() { } afterupdate() { } update(timer: ITimer) { } nextStep(timer: ITimer) { if (!this.needsUpdate) return; this.beforeupdate(); this.update(timer) this.updateComponents(); this.beforeupdate() this.needsUpdate = false; } }