Files
esengine/src/ECS/Utils/Matcher.ts

169 lines
4.7 KiB
TypeScript
Raw Normal View History

import { Entity } from '../Entity';
import { Component } from '../Component';
import { Bits } from './Bits';
import { ComponentTypeManager } from './ComponentTypeManager';
/**
*
*
*/
export class Matcher {
protected allSet: (new (...args: any[]) => Component)[] = [];
protected exclusionSet: (new (...args: any[]) => Component)[] = [];
protected oneSet: (new (...args: any[]) => Component)[] = [];
// 缓存的位掩码,避免重复计算
private _allBits?: Bits;
private _exclusionBits?: Bits;
private _oneBits?: Bits;
private _isDirty = true;
public static empty(): Matcher {
return new Matcher();
}
public getAllSet(): (new (...args: any[]) => Component)[] {
return this.allSet;
}
public getExclusionSet(): (new (...args: any[]) => Component)[] {
return this.exclusionSet;
}
public getOneSet(): (new (...args: any[]) => Component)[] {
return this.oneSet;
}
/**
*
* @param entity
* @returns
*/
public isInterestedEntity(entity: Entity): boolean {
const entityBits = this.getEntityBits(entity);
return this.isInterested(entityBits);
}
/**
*
* @param componentBits
* @returns
*/
public isInterested(componentBits: Bits): boolean {
this.updateBitsIfDirty();
// 检查必须包含的组件
if (this._allBits && !componentBits.containsAll(this._allBits)) {
return false;
}
// 检查排除的组件
if (this._exclusionBits && componentBits.intersects(this._exclusionBits)) {
return false;
}
// 检查至少包含其中之一的组件
if (this._oneBits && !componentBits.intersects(this._oneBits)) {
return false;
}
return true;
}
/**
*
* @param types
*/
public all(...types: (new (...args: any[]) => Component)[]): Matcher {
this.allSet.push(...types);
this._isDirty = true;
return this;
}
/**
*
* @param types
*/
public exclude(...types: (new (...args: any[]) => Component)[]): Matcher {
this.exclusionSet.push(...types);
this._isDirty = true;
return this;
}
/**
*
* @param types
*/
public one(...types: (new (...args: any[]) => Component)[]): Matcher {
this.oneSet.push(...types);
this._isDirty = true;
return this;
}
/**
*
* @param entity
* @returns
*/
private getEntityBits(entity: Entity): Bits {
const components = entity.components;
return ComponentTypeManager.instance.getEntityBits(components);
}
/**
*
*/
private updateBitsIfDirty(): void {
if (!this._isDirty) {
return;
}
const typeManager = ComponentTypeManager.instance;
// 更新必须包含的组件位掩码
if (this.allSet.length > 0) {
this._allBits = typeManager.createBits(...this.allSet);
} else {
this._allBits = undefined;
}
// 更新排除的组件位掩码
if (this.exclusionSet.length > 0) {
this._exclusionBits = typeManager.createBits(...this.exclusionSet);
} else {
this._exclusionBits = undefined;
}
// 更新至少包含其中之一的组件位掩码
if (this.oneSet.length > 0) {
this._oneBits = typeManager.createBits(...this.oneSet);
} else {
this._oneBits = undefined;
}
this._isDirty = false;
}
/**
*
* @returns
*/
public toString(): string {
const parts: string[] = [];
if (this.allSet.length > 0) {
parts.push(`all: [${this.allSet.map(t => t.name).join(', ')}]`);
}
if (this.exclusionSet.length > 0) {
parts.push(`exclude: [${this.exclusionSet.map(t => t.name).join(', ')}]`);
}
if (this.oneSet.length > 0) {
parts.push(`one: [${this.oneSet.map(t => t.name).join(', ')}]`);
}
return `Matcher(${parts.join(', ')})`;
}
}