UNPKG

12.7 kBSource Map (JSON)View Raw
1{"version":3,"file":"ComponentManager.js","names":["Component","data","ComponentManager","clazz","components","entities","lookup","entity","length","component","push","componentIndex","pop","entity2","i","srcIndex","destIndex","srcComponent","srcEntity","direction","next","index","componentIdx","Object","keys","entityInNum","Number","EMPTY","callback","getCount","getComponent","result"],"sources":["../src/ComponentManager.ts"],"sourcesContent":["import { Entity } from '.';\nimport { EMPTY } from './Entity';\n\ntype NonFunctionPropertyNames<T> = {\n [K in keyof T]: T[K] extends (args: unknown) => void ? never : K;\n}[keyof T];\nexport type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;\n\nexport type ComponentClassType<P> = new (\n data: Partial<NonFunctionProperties<P>>,\n) => Component<P> & P;\n\nexport abstract class Component<P> {\n constructor(data?: Partial<NonFunctionProperties<P>>) {\n //\n }\n}\n\n/**\n * 管理某一类 Component,尽可能做到 AoS 而非 SoA\n * @see https://wickedengine.net/2019/09/29/entity-component-system/\n * @see https://github.com/turanszkij/WickedEngine/blob/master/WickedEngine/wiECS.h\n */\n// tslint:disable-next-line:max-classes-per-file\nexport class ComponentManager<P> {\n private clazz: ComponentClassType<P>;\n private components: Array<Component<P> & P> = [];\n private entities: Entity[] = [];\n\n /**\n * 不在 Entity 中维护拥有的 Component 列表,反之亦然\n */\n private lookup: Record<Entity, number> = {};\n\n constructor(clazz: ComponentClassType<P>) {\n this.clazz = clazz;\n }\n\n public clear() {\n this.components = [];\n this.entities = [];\n this.lookup = {};\n }\n\n public contains(entity: Entity) {\n return this.lookup[entity] > -1;\n }\n\n public create(entity: Entity, data?: Partial<NonFunctionProperties<P>>) {\n this.lookup[entity] = this.components.length;\n const component = new this.clazz(data || {});\n this.components.push(component);\n this.entities.push(entity);\n return component;\n }\n\n public remove(entity: Entity) {\n const componentIndex = this.lookup[entity];\n if (componentIndex > -1) {\n if (componentIndex < this.components.length - 1) {\n // 将待删除元素和最后一个元素交换\n // C++ 中有 std::move 这样的操作,避免数据的拷贝\n // @see https://github.com/turanszkij/WickedEngine/blob/master/WickedEngine/wiECS.h#L169\n this.components[componentIndex] = this.components[\n this.components.length - 1\n ];\n this.entities[componentIndex] = this.entities[this.entities.length - 1];\n this.lookup[this.entities[componentIndex]] = componentIndex;\n }\n }\n\n // 待删除元素已经移动到了最后一个\n this.components.pop();\n this.entities.pop();\n delete this.lookup[entity];\n }\n\n public removeKeepSorted(entity: Entity) {\n const componentIndex = this.lookup[entity];\n if (componentIndex > -1) {\n const entity2 = this.entities[componentIndex];\n\n if (componentIndex < this.components.length - 1) {\n // Move every component left by one that is after this element:\n for (let i = componentIndex + 1; i < this.components.length; ++i) {\n this.components[i - 1] = this.components[i];\n }\n // Move every entity left by one that is after this element and update lut:\n for (let i = componentIndex + 1; i < this.entities.length; ++i) {\n this.entities[i - 1] = this.entities[i];\n this.lookup[this.entities[i - 1]] = i - 1;\n }\n }\n\n this.components.pop();\n this.entities.pop();\n delete this.lookup[entity2];\n }\n }\n\n public moveItem(srcIndex: number, destIndex: number) {\n if (srcIndex === destIndex) {\n return;\n }\n\n // Save the moved component and entity:\n const srcComponent = this.components[srcIndex];\n const srcEntity = this.entities[srcIndex];\n\n // Every other entity-component that's in the way gets moved by one and lut is kept updated:\n const direction = srcIndex < destIndex ? 1 : -1;\n for (let i = srcIndex; i !== destIndex; i += direction) {\n const next = i + direction;\n this.components[i] = this.components[next];\n this.entities[i] = this.entities[next];\n this.lookup[this.entities[i]] = i;\n }\n\n // Saved entity-component moved to the required position:\n this.components[destIndex] = srcComponent;\n this.entities[destIndex] = srcEntity;\n this.lookup[srcEntity] = destIndex;\n }\n\n public getEntity(index: number) {\n return this.entities[index];\n }\n\n /**\n * 由于缺少类似 C++ 的重载操作符,没法通过 [下标] 直接访问。因此只能增加该方法用于遍历。\n */\n public getComponent(index: number) {\n return this.components[index];\n }\n\n public getComponentByEntity(entity: Entity) {\n const componentIndex = this.lookup[entity];\n if (componentIndex > -1) {\n return this.components[componentIndex];\n }\n return null;\n }\n\n public getCount() {\n return this.components.length;\n }\n\n public getEntityByComponentIndex(componentIdx: number) {\n for (const entity of Object.keys(this.lookup)) {\n const entityInNum = Number(entity);\n if (this.lookup[entityInNum] === componentIdx) {\n return entityInNum;\n }\n }\n return EMPTY;\n }\n\n public find(callback: (component: Component<P> & P, i: number) => boolean) {\n for (let i = 0; i < this.getCount(); i++) {\n const component = this.getComponent(i);\n if (callback(component, i)) {\n return component;\n }\n }\n return null;\n }\n\n public findIndex(\n callback: (component: Component<P> & P, i: number) => boolean,\n ) {\n for (let i = 0; i < this.getCount(); i++) {\n const component = this.getComponent(i);\n if (callback(component, i)) {\n return i;\n }\n }\n return -1;\n }\n\n public forEach(\n callback: (entity: Entity, component: Component<P> & P) => void,\n ) {\n for (const entity of Object.keys(this.lookup)) {\n const entityInNum = Number(entity);\n const componentIndex = this.lookup[entityInNum];\n callback(entityInNum, this.getComponent(componentIndex));\n }\n }\n\n public async forEachAsync(\n callback: (entity: Entity, component: Component<P> & P) => Promise<void>,\n ) {\n for (const entity of Object.keys(this.lookup)) {\n const entityInNum = Number(entity);\n const componentIndex = this.lookup[entityInNum];\n await callback(entityInNum, this.getComponent(componentIndex));\n }\n }\n\n public map(callback: (entity: Entity, component: Component<P> & P) => void) {\n const result = [];\n for (const entity of Object.keys(this.lookup)) {\n const entityInNum = Number(entity);\n const componentIndex = this.lookup[entityInNum];\n result.push(callback(entityInNum, this.getComponent(componentIndex)));\n }\n return result;\n }\n}\n"],"mappings":"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"}
\No newline at end of file