移除Bitset更改为Bits
This commit is contained in:
185
source/bin/framework.d.ts
vendored
185
source/bin/framework.d.ts
vendored
@@ -260,11 +260,7 @@ declare module es {
|
|||||||
* 指定应该调用这个entity update方法的频率。1表示每一帧,2表示每一帧,以此类推
|
* 指定应该调用这个entity update方法的频率。1表示每一帧,2表示每一帧,以此类推
|
||||||
*/
|
*/
|
||||||
updateInterval: number;
|
updateInterval: number;
|
||||||
/**
|
componentBits: Bits;
|
||||||
* 返回一个BitSet实例,包含实体拥有的组件的位
|
|
||||||
*/
|
|
||||||
componentBits: BitSet;
|
|
||||||
private systemBits_;
|
|
||||||
constructor(name: string);
|
constructor(name: string);
|
||||||
_isDestroyed: boolean;
|
_isDestroyed: boolean;
|
||||||
/**
|
/**
|
||||||
@@ -298,7 +294,6 @@ declare module es {
|
|||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
updateOrder: number;
|
updateOrder: number;
|
||||||
getSystemBits(): BitSet;
|
|
||||||
parent: Transform;
|
parent: Transform;
|
||||||
readonly childCount: number;
|
readonly childCount: number;
|
||||||
position: Vector2;
|
position: Vector2;
|
||||||
@@ -1324,17 +1319,11 @@ declare module es {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class SystemIndexManager {
|
|
||||||
static INDEX: number;
|
|
||||||
private static indices;
|
|
||||||
static getIndexFor(es: Class): number;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 追踪实体的子集,但不实现任何排序或迭代。
|
* 追踪实体的子集,但不实现任何排序或迭代。
|
||||||
*/
|
*/
|
||||||
abstract class EntitySystem {
|
abstract class EntitySystem {
|
||||||
private _entities;
|
private _entities;
|
||||||
private systemIndex_;
|
|
||||||
constructor(matcher?: Matcher);
|
constructor(matcher?: Matcher);
|
||||||
private _scene;
|
private _scene;
|
||||||
/**
|
/**
|
||||||
@@ -1562,145 +1551,10 @@ declare module es {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
/**
|
class Bits {
|
||||||
* 这个类可以从两方面来考虑。你可以把它看成一个位向量或者一组非负整数。这个名字有点误导人。
|
private _bit;
|
||||||
*
|
set(index: number, value: number): void;
|
||||||
* 它是由一个位向量实现的,但同样可以把它看成是一个非负整数的集合;集合中的每个整数由对应索引处的集合位表示。该结构的大小由集合中的最大整数决定。
|
get(index: number): number;
|
||||||
*/
|
|
||||||
class BitSet {
|
|
||||||
private static ADDRESS_BITS_PER_WORD;
|
|
||||||
private static BITS_PER_WORD;
|
|
||||||
private static WORD_MASK;
|
|
||||||
private words_;
|
|
||||||
constructor(nbits?: number);
|
|
||||||
clear(bitIndex?: number): void;
|
|
||||||
get(bitIndex: number): boolean;
|
|
||||||
intersects(set: BitSet): boolean;
|
|
||||||
isEmpty(): boolean;
|
|
||||||
nextSetBit(fromIndex: number): number;
|
|
||||||
private numberOfTrailingZeros;
|
|
||||||
set(bitIndex: number, value?: boolean): number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module es {
|
|
||||||
/**
|
|
||||||
* 性能优化的位组实现。某些操作是以不安全为前缀的, 这些方法不执行验证,主要是在内部利用来优化实体ID位集的访问
|
|
||||||
*/
|
|
||||||
class BitVector {
|
|
||||||
private words;
|
|
||||||
/**
|
|
||||||
* 创建一个初始大小足够大的bitset,以明确表示0到nbits-1范围内指数的bit
|
|
||||||
* @param nbits nbits 位集的初始大小
|
|
||||||
*/
|
|
||||||
constructor(nbits?: number | BitVector);
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 位的索引
|
|
||||||
* @returns 该位是否被设置
|
|
||||||
*/
|
|
||||||
get(index: number): boolean;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 位的索引
|
|
||||||
*/
|
|
||||||
set(index: number, value?: boolean): void;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 位的索引
|
|
||||||
* @returns 该位是否被设置
|
|
||||||
*/
|
|
||||||
unsafeGet(index: number): boolean;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 要设置的位的索引
|
|
||||||
*/
|
|
||||||
unsafeSet(index: number): void;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 要翻转的位的索引
|
|
||||||
*/
|
|
||||||
flip(index: number): void;
|
|
||||||
/**
|
|
||||||
* 要清除的位的索引
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
clear(index?: number): void;
|
|
||||||
/**
|
|
||||||
* 返回该位组的 "逻辑大小":位组中最高设置位的索引加1。如果比特集不包含集合位,则返回0
|
|
||||||
*/
|
|
||||||
length(): number;
|
|
||||||
/**
|
|
||||||
* @returns 如果这个位组中没有设置为true的位,则为true
|
|
||||||
*/
|
|
||||||
isEmpty(): boolean;
|
|
||||||
/**
|
|
||||||
* 返回在指定的起始索引上或之后出现的第一个被设置为真的位的索引。
|
|
||||||
* 如果不存在这样的位,则返回-1
|
|
||||||
* @param fromIndex
|
|
||||||
*/
|
|
||||||
nextSetBit(fromIndex: number): number;
|
|
||||||
/**
|
|
||||||
* 返回在指定的起始索引上或之后发生的第一个被设置为false的位的索引
|
|
||||||
* @param fromIndex
|
|
||||||
*/
|
|
||||||
nextClearBit(fromIndex: number): number;
|
|
||||||
/**
|
|
||||||
* 对这个目标位集和参数位集进行逻辑AND。
|
|
||||||
* 这个位集被修改,使它的每一个位都有值为真,如果且仅当它最初的值为真,并且位集参数中的相应位也有值为真
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
and(other: BitVector): void;
|
|
||||||
/**
|
|
||||||
* 清除该位集的所有位,其对应的位被设置在指定的位集中
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
andNot(other: BitVector): void;
|
|
||||||
/**
|
|
||||||
* 用位集参数执行这个位集的逻辑OR。
|
|
||||||
* 如果且仅当位集参数中的位已经有值为真或位集参数中的对应位有值为真时,该位集才会被修改,从而使位集中的位有值为真
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
or(other: BitVector): void;
|
|
||||||
/**
|
|
||||||
* 用位集参数对这个位集进行逻辑XOR。
|
|
||||||
* 这个位集被修改了,所以如果且仅当以下语句之一成立时,位集中的一个位的值为真
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
xor(other: BitVector): void;
|
|
||||||
/**
|
|
||||||
* 如果指定的BitVector有任何位被设置为true,并且在这个BitVector中也被设置为true,则返回true
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
intersects(other: BitVector): boolean;
|
|
||||||
/**
|
|
||||||
* 如果这个位集是指定位集的超级集,即它的所有位都被设置为真,那么返回true
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
containsAll(other: BitVector): boolean;
|
|
||||||
cardinality(): number;
|
|
||||||
hashCode(): number;
|
|
||||||
private bitCount;
|
|
||||||
/**
|
|
||||||
* 返回二进制补码二进制表示形式中最高位(“最左端”)一位之前的零位数量
|
|
||||||
* @param i
|
|
||||||
*/
|
|
||||||
private numberOfLeadingZeros;
|
|
||||||
/**
|
|
||||||
* 返回指定二进制数的补码二进制表示形式中最低序(“最右”)一位之后的零位数量
|
|
||||||
* @param i
|
|
||||||
*/
|
|
||||||
numberOfTrailingZeros(i: number): number;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 要清除的位的索引
|
|
||||||
*/
|
|
||||||
unsafeClear(index: number): void;
|
|
||||||
/**
|
|
||||||
* 增长支持数组,使其能够容纳所请求的位
|
|
||||||
* @param bits 位数
|
|
||||||
*/
|
|
||||||
ensureCapacity(bits: number): void;
|
|
||||||
private checkCapacity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
@@ -1714,9 +1568,6 @@ declare module es {
|
|||||||
* 添加到实体的组件列表
|
* 添加到实体的组件列表
|
||||||
*/
|
*/
|
||||||
_components: Component[];
|
_components: Component[];
|
||||||
/** 记录component的快速读取列表 */
|
|
||||||
fastComponentsMap: Map<new (...args: any[]) => Component, Component[]>;
|
|
||||||
fastComponentsToAddMap: Map<new (...args: any[]) => Component, Component[]>;
|
|
||||||
/**
|
/**
|
||||||
* 所有需要更新的组件列表
|
* 所有需要更新的组件列表
|
||||||
*/
|
*/
|
||||||
@@ -1738,6 +1589,8 @@ declare module es {
|
|||||||
* 用于确定是否需要对该框架中的组件进行排序的标志
|
* 用于确定是否需要对该框架中的组件进行排序的标志
|
||||||
*/
|
*/
|
||||||
_isComponentListUnsorted: boolean;
|
_isComponentListUnsorted: boolean;
|
||||||
|
private componentsByType;
|
||||||
|
private componentsToAddByType;
|
||||||
constructor(entity: Entity);
|
constructor(entity: Entity);
|
||||||
readonly count: number;
|
readonly count: number;
|
||||||
readonly buffer: Component[];
|
readonly buffer: Component[];
|
||||||
@@ -1750,15 +1603,17 @@ declare module es {
|
|||||||
removeAllComponents(): void;
|
removeAllComponents(): void;
|
||||||
deregisterAllComponents(): void;
|
deregisterAllComponents(): void;
|
||||||
registerAllComponents(): void;
|
registerAllComponents(): void;
|
||||||
|
private decreaseBits;
|
||||||
|
private addBits;
|
||||||
/**
|
/**
|
||||||
* 处理任何需要删除或添加的组件
|
* 处理任何需要删除或添加的组件
|
||||||
*/
|
*/
|
||||||
updateLists(): void;
|
updateLists(): void;
|
||||||
handleRemove(component: Component): void;
|
handleRemove(component: Component): void;
|
||||||
private removeFastComponent;
|
private removeComponentsByType;
|
||||||
private addFastComponent;
|
private addComponentsByType;
|
||||||
private removeFastComponentToAdd;
|
private removeComponentsToAddByType;
|
||||||
private addFastComponentToAdd;
|
private addComponentsToAddByType;
|
||||||
/**
|
/**
|
||||||
* 获取类型T的第一个组件并返回它
|
* 获取类型T的第一个组件并返回它
|
||||||
* 可以选择跳过检查未初始化的组件(尚未调用onAddedToEntity方法的组件)
|
* 可以选择跳过检查未初始化的组件(尚未调用onAddedToEntity方法的组件)
|
||||||
@@ -1943,15 +1798,15 @@ declare module es {
|
|||||||
}
|
}
|
||||||
declare module es {
|
declare module es {
|
||||||
class Matcher {
|
class Matcher {
|
||||||
protected allSet: BitSet;
|
protected allSet: (new (...args: any[]) => Component)[];
|
||||||
protected exclusionSet: BitSet;
|
protected exclusionSet: (new (...args: any[]) => Component)[];
|
||||||
protected oneSet: BitSet;
|
protected oneSet: (new (...args: any[]) => Component)[];
|
||||||
static empty(): Matcher;
|
static empty(): Matcher;
|
||||||
getAllSet(): BitSet;
|
getAllSet(): (new (...args: any[]) => Component)[];
|
||||||
getExclusionSet(): BitSet;
|
getExclusionSet(): (new (...args: any[]) => Component)[];
|
||||||
getOneSet(): BitSet;
|
getOneSet(): (new (...args: any[]) => Component)[];
|
||||||
isInterestedEntity(e: Entity): boolean;
|
isInterestedEntity(e: Entity): boolean;
|
||||||
isInterested(componentBits: BitSet): boolean;
|
isInterested(components: Bits): boolean;
|
||||||
all(...types: any[]): Matcher;
|
all(...types: any[]): Matcher;
|
||||||
exclude(...types: any[]): this;
|
exclude(...types: any[]): this;
|
||||||
one(...types: any[]): this;
|
one(...types: any[]): this;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -35,20 +35,14 @@ module es {
|
|||||||
* 指定应该调用这个entity update方法的频率。1表示每一帧,2表示每一帧,以此类推
|
* 指定应该调用这个entity update方法的频率。1表示每一帧,2表示每一帧,以此类推
|
||||||
*/
|
*/
|
||||||
public updateInterval: number = 1;
|
public updateInterval: number = 1;
|
||||||
/**
|
public componentBits: Bits;
|
||||||
* 返回一个BitSet实例,包含实体拥有的组件的位
|
|
||||||
*/
|
|
||||||
public componentBits: BitSet;
|
|
||||||
private systemBits_: BitSet;
|
|
||||||
|
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
this.components = new ComponentList(this);
|
this.components = new ComponentList(this);
|
||||||
this.transform = new Transform(this);
|
this.transform = new Transform(this);
|
||||||
|
this.componentBits = new Bits();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.id = Entity._idGenerator++;
|
this.id = Entity._idGenerator++;
|
||||||
|
|
||||||
this.systemBits_ = new BitSet();
|
|
||||||
this.componentBits = new BitSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public _isDestroyed: boolean;
|
public _isDestroyed: boolean;
|
||||||
@@ -111,10 +105,6 @@ module es {
|
|||||||
this.setUpdateOrder(value);
|
this.setUpdateOrder(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSystemBits(): BitSet {
|
|
||||||
return this.systemBits_;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get parent(): Transform {
|
public get parent(): Transform {
|
||||||
return this.transform.parent;
|
return this.transform.parent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,13 @@
|
|||||||
///<reference path="../../Utils/Collections/HashMap.ts"/>
|
///<reference path="../../Utils/Collections/HashMap.ts"/>
|
||||||
module es {
|
module es {
|
||||||
export class SystemIndexManager {
|
|
||||||
public static INDEX = 0;
|
|
||||||
private static indices: Map<Function, number> = new Map<Function, number>();
|
|
||||||
|
|
||||||
public static getIndexFor(es: Class): number {
|
|
||||||
let index: number = SystemIndexManager.indices.get(es);
|
|
||||||
if (!index) {
|
|
||||||
index = SystemIndexManager.INDEX++;
|
|
||||||
SystemIndexManager.indices.set(es, index);
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 追踪实体的子集,但不实现任何排序或迭代。
|
* 追踪实体的子集,但不实现任何排序或迭代。
|
||||||
*/
|
*/
|
||||||
export abstract class EntitySystem {
|
export abstract class EntitySystem {
|
||||||
private _entities: Entity[] = [];
|
private _entities: Entity[] = [];
|
||||||
private systemIndex_: number;
|
|
||||||
|
|
||||||
constructor(matcher?: Matcher) {
|
constructor(matcher?: Matcher) {
|
||||||
this._matcher = matcher ? matcher : Matcher.empty();
|
this._matcher = matcher ? matcher : Matcher.empty();
|
||||||
this.systemIndex_ = SystemIndexManager.getIndexFor(this.constructor);
|
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +44,7 @@ module es {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onChanged(entity: Entity) {
|
public onChanged(entity: Entity) {
|
||||||
let contains = entity.getSystemBits().get(this.systemIndex_);
|
let contains = !!this._entities.find(e => e.id == entity.id);
|
||||||
let interest = this._matcher.isInterestedEntity(entity);
|
let interest = this._matcher.isInterestedEntity(entity);
|
||||||
|
|
||||||
if (interest && !contains)
|
if (interest && !contains)
|
||||||
@@ -70,8 +54,8 @@ module es {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public add(entity: Entity) {
|
public add(entity: Entity) {
|
||||||
|
if (!this._entities.find(e => e.id == entity.id))
|
||||||
this._entities.push(entity);
|
this._entities.push(entity);
|
||||||
entity.getSystemBits().set(this.systemIndex_);
|
|
||||||
this.onAdded(entity);
|
this.onAdded(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +63,6 @@ module es {
|
|||||||
|
|
||||||
public remove(entity: Entity) {
|
public remove(entity: Entity) {
|
||||||
new es.List(this._entities).remove(entity);
|
new es.List(this._entities).remove(entity);
|
||||||
entity.getSystemBits().clear(this.systemIndex_);
|
|
||||||
this.onRemoved(entity);
|
this.onRemoved(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
module es {
|
|
||||||
/**
|
|
||||||
* 这个类可以从两方面来考虑。你可以把它看成一个位向量或者一组非负整数。这个名字有点误导人。
|
|
||||||
*
|
|
||||||
* 它是由一个位向量实现的,但同样可以把它看成是一个非负整数的集合;集合中的每个整数由对应索引处的集合位表示。该结构的大小由集合中的最大整数决定。
|
|
||||||
*/
|
|
||||||
export class BitSet {
|
|
||||||
private static ADDRESS_BITS_PER_WORD = 5;
|
|
||||||
private static BITS_PER_WORD = 1 << BitSet.ADDRESS_BITS_PER_WORD; // 32
|
|
||||||
private static WORD_MASK : number = 0xffffffff;
|
|
||||||
private words_: number[];
|
|
||||||
|
|
||||||
constructor(nbits: number = 0) {
|
|
||||||
this.words_ = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public clear(bitIndex?: number) {
|
|
||||||
if (bitIndex === null) {
|
|
||||||
const words = this.words_;
|
|
||||||
let wordsInUse = words.length;
|
|
||||||
while (wordsInUse > 0) {
|
|
||||||
words[--wordsInUse] = 0;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wordIndex = bitIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
|
||||||
this.words_[wordIndex] &= ~(1 << bitIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get(bitIndex: number): boolean {
|
|
||||||
const wordIndex = bitIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
|
||||||
const words = this.words_;
|
|
||||||
const wordsInUse = words.length;
|
|
||||||
|
|
||||||
return wordIndex < wordsInUse && (words[wordIndex] & (1 << bitIndex)) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public intersects(set: BitSet) {
|
|
||||||
const words = this.words_;
|
|
||||||
const wordsInUse = words.length;
|
|
||||||
|
|
||||||
for (let i = Math.min(wordsInUse, set.words_.length) - 1; i >= 0; i--)
|
|
||||||
if ((words[i] & set.words_[i]) != 0) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isEmpty(): boolean {
|
|
||||||
return this.words_.length === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public nextSetBit(fromIndex: number) {
|
|
||||||
let u = fromIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
|
||||||
const words = this.words_;
|
|
||||||
const wordsInUse = words.length;
|
|
||||||
|
|
||||||
let word = words[u] & (BitSet.WORD_MASK << fromIndex);
|
|
||||||
while (true) {
|
|
||||||
if (word !== 0) return u * BitSet.BITS_PER_WORD + this.numberOfTrailingZeros(word);
|
|
||||||
if (++u === wordsInUse) return -1;
|
|
||||||
word = words[u];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private numberOfTrailingZeros(i: number): number {
|
|
||||||
if (i == 0) return 64;
|
|
||||||
let x: number = i;
|
|
||||||
let y: number;
|
|
||||||
let n = 63;
|
|
||||||
y = x << 32;
|
|
||||||
if (y != 0) {
|
|
||||||
n -= 32;
|
|
||||||
x = y;
|
|
||||||
}
|
|
||||||
y = x << 16;
|
|
||||||
if (y != 0) {
|
|
||||||
n -= 16;
|
|
||||||
x = y;
|
|
||||||
}
|
|
||||||
y = x << 8;
|
|
||||||
if (y != 0) {
|
|
||||||
n -= 8;
|
|
||||||
x = y;
|
|
||||||
}
|
|
||||||
y = x << 4;
|
|
||||||
if (y != 0) {
|
|
||||||
n -= 4;
|
|
||||||
x = y;
|
|
||||||
}
|
|
||||||
y = x << 2;
|
|
||||||
if (y != 0) {
|
|
||||||
n -= 2;
|
|
||||||
x = y;
|
|
||||||
}
|
|
||||||
return n - ((x << 1) >>> 63);
|
|
||||||
}
|
|
||||||
|
|
||||||
public set(bitIndex: number, value: boolean = true) {
|
|
||||||
const wordIndex = bitIndex >> BitSet.ADDRESS_BITS_PER_WORD;
|
|
||||||
const words = this.words_;
|
|
||||||
const wordsInUse = words.length;
|
|
||||||
const wordsRequired = wordIndex + 1;
|
|
||||||
|
|
||||||
if (wordsInUse < wordsRequired) {
|
|
||||||
words.length = Math.max(2 * wordsInUse, wordsRequired);
|
|
||||||
for (let i = wordsInUse, l = words.length; i < l; i++) {
|
|
||||||
words[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
return (words[wordIndex] |= 1 << bitIndex);
|
|
||||||
} else {
|
|
||||||
return (words[wordIndex] &= ~(1 << bitIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,353 +0,0 @@
|
|||||||
module es {
|
|
||||||
/**
|
|
||||||
* 性能优化的位组实现。某些操作是以不安全为前缀的, 这些方法不执行验证,主要是在内部利用来优化实体ID位集的访问
|
|
||||||
*/
|
|
||||||
export class BitVector {
|
|
||||||
private words: number[] = [0];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个初始大小足够大的bitset,以明确表示0到nbits-1范围内指数的bit
|
|
||||||
* @param nbits nbits 位集的初始大小
|
|
||||||
*/
|
|
||||||
constructor(nbits?: number | BitVector) {
|
|
||||||
if (nbits) {
|
|
||||||
if (typeof nbits == 'number')
|
|
||||||
this.checkCapacity(nbits >>> 6);
|
|
||||||
else {
|
|
||||||
// 基于另一个位向量创建一个位集
|
|
||||||
this.words = nbits.words.slice(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 位的索引
|
|
||||||
* @returns 该位是否被设置
|
|
||||||
*/
|
|
||||||
public get(index: number): boolean {
|
|
||||||
const word = index >>> 6;
|
|
||||||
return word < this.words.length &&
|
|
||||||
(this.words[word] & (1 << index)) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 位的索引
|
|
||||||
*/
|
|
||||||
public set(index: number, value: boolean = true) {
|
|
||||||
if (value) {
|
|
||||||
const word = index >>> 6;
|
|
||||||
this.checkCapacity(word);
|
|
||||||
this.words[word] |= 1 << index;
|
|
||||||
} else {
|
|
||||||
this.clear(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 位的索引
|
|
||||||
* @returns 该位是否被设置
|
|
||||||
*/
|
|
||||||
public unsafeGet(index: number): boolean {
|
|
||||||
return (this.words[index >>> 6] & (1 << index)) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 要设置的位的索引
|
|
||||||
*/
|
|
||||||
public unsafeSet(index: number) {
|
|
||||||
this.words[index >>> 6] |= 1 << index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 要翻转的位的索引
|
|
||||||
*/
|
|
||||||
public flip(index: number) {
|
|
||||||
const word = index >>> 6;
|
|
||||||
this.checkCapacity(word);
|
|
||||||
this.words[word] ^= 1 << index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 要清除的位的索引
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
public clear(index?: number) {
|
|
||||||
if (index != null) {
|
|
||||||
const word = index >>> 6;
|
|
||||||
if (word >= this.words.length) return;
|
|
||||||
this.words[word] &= ~(1 << index);
|
|
||||||
} else {
|
|
||||||
this.words.fill(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回该位组的 "逻辑大小":位组中最高设置位的索引加1。如果比特集不包含集合位,则返回0
|
|
||||||
*/
|
|
||||||
public length(): number {
|
|
||||||
let bits = this.words.slice(0);
|
|
||||||
for (let word = bits.length - 1; word >= 0; --word) {
|
|
||||||
let bitsAtWord = bits[word];
|
|
||||||
if (bitsAtWord != 0)
|
|
||||||
return (word << 6) + 64 - this.numberOfLeadingZeros(bitsAtWord);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns 如果这个位组中没有设置为true的位,则为true
|
|
||||||
*/
|
|
||||||
public isEmpty(): boolean {
|
|
||||||
let bits = this.words.slice(0);
|
|
||||||
let length = bits.length;
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
if (bits[i] != 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回在指定的起始索引上或之后出现的第一个被设置为真的位的索引。
|
|
||||||
* 如果不存在这样的位,则返回-1
|
|
||||||
* @param fromIndex
|
|
||||||
*/
|
|
||||||
public nextSetBit(fromIndex: number): number {
|
|
||||||
let word = fromIndex >>> 6;
|
|
||||||
if (word >= this.words.length)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
let bitmap = this.words[word] >>> fromIndex;
|
|
||||||
if (bitmap != 0)
|
|
||||||
return fromIndex + this.numberOfTrailingZeros(bitmap);
|
|
||||||
|
|
||||||
for (let i = 1 + word; i < this.words.length; i++) {
|
|
||||||
bitmap = this.words[i];
|
|
||||||
if (bitmap != 0) {
|
|
||||||
return i * 64 + this.numberOfTrailingZeros(bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回在指定的起始索引上或之后发生的第一个被设置为false的位的索引
|
|
||||||
* @param fromIndex
|
|
||||||
*/
|
|
||||||
public nextClearBit(fromIndex: number): number {
|
|
||||||
let word = fromIndex >>> 6;
|
|
||||||
if (word >= this.words.length)
|
|
||||||
return Math.min(fromIndex, this.words.length << 6);
|
|
||||||
|
|
||||||
let bitmap = ~(this.words[word] >>> fromIndex);
|
|
||||||
if (bitmap != 0)
|
|
||||||
return fromIndex + this.numberOfTrailingZeros(bitmap);
|
|
||||||
|
|
||||||
for (let i = 1 + word; i < this.words.length; i++) {
|
|
||||||
bitmap = ~this.words[i];
|
|
||||||
if (bitmap != 0) {
|
|
||||||
return i * 64 + this.numberOfTrailingZeros(bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.min(fromIndex, this.words.length << 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对这个目标位集和参数位集进行逻辑AND。
|
|
||||||
* 这个位集被修改,使它的每一个位都有值为真,如果且仅当它最初的值为真,并且位集参数中的相应位也有值为真
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
public and(other: BitVector) {
|
|
||||||
let commonWords = Math.min(this.words.length, other.words.length);
|
|
||||||
for (let i = 0; commonWords > i; i++) {
|
|
||||||
this.words[i] &= other.words[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.words.length > commonWords) {
|
|
||||||
for (let i = commonWords, s = this.words.length; s > i; i++) {
|
|
||||||
this.words[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除该位集的所有位,其对应的位被设置在指定的位集中
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
public andNot(other: BitVector) {
|
|
||||||
let commonWords = Math.min(this.words.length, other.words.length);
|
|
||||||
for (let i = 0; commonWords > i; i++)
|
|
||||||
this.words[i] &= ~other.words[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用位集参数执行这个位集的逻辑OR。
|
|
||||||
* 如果且仅当位集参数中的位已经有值为真或位集参数中的对应位有值为真时,该位集才会被修改,从而使位集中的位有值为真
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
public or(other: BitVector) {
|
|
||||||
let commonWords = Math.min(this.words.length, other.words.length);
|
|
||||||
for (let i = 0; commonWords > i; i++)
|
|
||||||
this.words[i] |= other.words[i];
|
|
||||||
|
|
||||||
if (commonWords < other.words.length) {
|
|
||||||
this.checkCapacity(other.words.length);
|
|
||||||
for (let i = commonWords, s = other.words.length; s > i; i++) {
|
|
||||||
this.words[i] = other.words[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用位集参数对这个位集进行逻辑XOR。
|
|
||||||
* 这个位集被修改了,所以如果且仅当以下语句之一成立时,位集中的一个位的值为真
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
public xor(other: BitVector) {
|
|
||||||
let commonWords = Math.min(this.words.length, other.words.length);
|
|
||||||
|
|
||||||
for (let i = 0; commonWords > i; i++)
|
|
||||||
this.words[i] ^= other.words[i];
|
|
||||||
|
|
||||||
if (commonWords < other.words.length) {
|
|
||||||
this.checkCapacity(other.words.length);
|
|
||||||
for (let i = commonWords, s = other.words.length; s > i; i++) {
|
|
||||||
this.words[i] = other.words[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果指定的BitVector有任何位被设置为true,并且在这个BitVector中也被设置为true,则返回true
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
public intersects(other: BitVector): boolean {
|
|
||||||
let bits = this.words.slice(0);
|
|
||||||
let otherBits = other.words;
|
|
||||||
for (let i = 0, s = Math.min(bits.length, otherBits.length); s > i; i++) {
|
|
||||||
if ((bits[i] & otherBits[i]) != 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果这个位集是指定位集的超级集,即它的所有位都被设置为真,那么返回true
|
|
||||||
* @param other
|
|
||||||
*/
|
|
||||||
public containsAll(other: BitVector): boolean {
|
|
||||||
let bits = this.words.slice(0);
|
|
||||||
let otherBits = other.words;
|
|
||||||
let otherBitsLength = otherBits.length;
|
|
||||||
let bitsLength = bits.length;
|
|
||||||
|
|
||||||
|
|
||||||
for (let i = bitsLength; i < otherBitsLength; i++) {
|
|
||||||
if (otherBits[i] != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0, s = Math.min(bitsLength, otherBitsLength); s > i; i++) {
|
|
||||||
if ((bits[i] & otherBits[i]) != otherBits[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public cardinality() {
|
|
||||||
let count = 0;
|
|
||||||
for (let i = 0; i < this.words.length; i++)
|
|
||||||
count += this.bitCount(this.words[i]);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public hashCode() {
|
|
||||||
const word = this.length() >>> 6;
|
|
||||||
let hash = 0;
|
|
||||||
for (let i = 0; word >= i; i++)
|
|
||||||
hash = 127 * hash + (this.words[i] ^ (this.words[i] >>> 32));
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bitCount(i: number) {
|
|
||||||
i = i - ((i >>> 1) & 0x55555555);
|
|
||||||
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
|
|
||||||
i = (i + (i >>> 4)) & 0x0f0f0f0f;
|
|
||||||
i = i + (i >>> 8);
|
|
||||||
i = i + (i >>> 16);
|
|
||||||
return i & 0x3f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回二进制补码二进制表示形式中最高位(“最左端”)一位之前的零位数量
|
|
||||||
* @param i
|
|
||||||
*/
|
|
||||||
private numberOfLeadingZeros(i: number) {
|
|
||||||
if (i == 0) return 64;
|
|
||||||
let n = 1;
|
|
||||||
let x = i >>> 32;
|
|
||||||
if (x == 0) { n += 32; x = i; }
|
|
||||||
if (x >>> 16 == 0) { n += 16; x <<= 16; }
|
|
||||||
if (x >>> 24 == 0) { n += 8; x <<= 8; }
|
|
||||||
if (x >>> 28 == 0) { n += 4; x <<= 4; }
|
|
||||||
if (x >>> 30 == 0) { n += 2; x <<= 2; }
|
|
||||||
n -= x >>> 31;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回指定二进制数的补码二进制表示形式中最低序(“最右”)一位之后的零位数量
|
|
||||||
* @param i
|
|
||||||
*/
|
|
||||||
public numberOfTrailingZeros(i: number) {
|
|
||||||
let x: number = 0, y: number = 0;
|
|
||||||
if (i == 0) return 64;
|
|
||||||
let n = 63;
|
|
||||||
y = i; if (y != 0) { n = n - 32; x = y; } else x = (i >>> 32);
|
|
||||||
y = x << 16; if (y != 0) { n = n - 16; x = y; }
|
|
||||||
y = x << 8; if (y != 0) { n = n - 8; x = y; }
|
|
||||||
y = x << 4; if (y != 0) { n = n - 4; x = y; }
|
|
||||||
y = x << 2; if (y != 0) { n = n - 2; x = y; }
|
|
||||||
return n - ((x << 1) >>> 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param index 要清除的位的索引
|
|
||||||
*/
|
|
||||||
public unsafeClear(index: number) {
|
|
||||||
this.words[index >>> 6] &= ~(1 << index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 增长支持数组,使其能够容纳所请求的位
|
|
||||||
* @param bits 位数
|
|
||||||
*/
|
|
||||||
public ensureCapacity(bits: number) {
|
|
||||||
this.checkCapacity(bits >>> 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
private checkCapacity(len: number) {
|
|
||||||
if (len >= this.words.length) {
|
|
||||||
let newBits: number[] = new Array(len + 1);
|
|
||||||
for (let i = 0; i < this.words.length; i++) {
|
|
||||||
newBits[i] = this.words[i];
|
|
||||||
}
|
|
||||||
this.words = newBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
source/src/ECS/Utils/Bits.ts
Normal file
14
source/src/ECS/Utils/Bits.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
module es {
|
||||||
|
export class Bits {
|
||||||
|
private _bit: {[index: number]: number} = {};
|
||||||
|
|
||||||
|
public set(index: number, value: number) {
|
||||||
|
this._bit[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(index: number): number {
|
||||||
|
let v = this._bit[index];
|
||||||
|
return v == null ? 0 : v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,6 @@ module es {
|
|||||||
* 添加到实体的组件列表
|
* 添加到实体的组件列表
|
||||||
*/
|
*/
|
||||||
public _components: Component[] = [];
|
public _components: Component[] = [];
|
||||||
/** 记录component的快速读取列表 */
|
|
||||||
public fastComponentsMap = new Map<new (...args: any[]) => Component, es.Component[]>();
|
|
||||||
public fastComponentsToAddMap = new Map<new (...args: any[]) => Component, es.Component[]>();
|
|
||||||
/**
|
/**
|
||||||
* 所有需要更新的组件列表
|
* 所有需要更新的组件列表
|
||||||
*/
|
*/
|
||||||
@@ -31,6 +28,8 @@ module es {
|
|||||||
* 用于确定是否需要对该框架中的组件进行排序的标志
|
* 用于确定是否需要对该框架中的组件进行排序的标志
|
||||||
*/
|
*/
|
||||||
public _isComponentListUnsorted: boolean;
|
public _isComponentListUnsorted: boolean;
|
||||||
|
private componentsByType = new Map<new (...args: any[]) => Component, es.Component[]>();
|
||||||
|
private componentsToAddByType = new Map<new (...args: any[]) => Component, es.Component[]>();
|
||||||
|
|
||||||
constructor(entity: Entity) {
|
constructor(entity: Entity) {
|
||||||
this._entity = entity;
|
this._entity = entity;
|
||||||
@@ -50,16 +49,13 @@ module es {
|
|||||||
|
|
||||||
public add(component: Component) {
|
public add(component: Component) {
|
||||||
this._componentsToAdd[component.id] = component;
|
this._componentsToAdd[component.id] = component;
|
||||||
this.addFastComponentToAdd(component);
|
this.addComponentsToAddByType(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public remove(component: Component) {
|
public remove(component: Component) {
|
||||||
Debug.warnIf(!!this._componentsToRemove[component.id], `您正在尝试删除一个您已经删除的组件(${component})`);
|
|
||||||
//
|
|
||||||
// 这可能不是一个活动的组件,所以我们必须注意它是否还没有被处理,它可能正在同一帧中被删除
|
|
||||||
if (this._componentsToAdd[component.id]) {
|
if (this._componentsToAdd[component.id]) {
|
||||||
delete this._componentsToAdd[component.id];
|
delete this._componentsToAdd[component.id];
|
||||||
this.removeFastComponentToAdd(component);
|
this.removeComponentsToAddByType(component);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,8 +70,8 @@ module es {
|
|||||||
this.handleRemove(this._components[i]);
|
this.handleRemove(this._components[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fastComponentsMap.clear();
|
this.componentsByType.clear();
|
||||||
this.fastComponentsToAddMap.clear();
|
this.componentsToAddByType.clear();
|
||||||
this._components.length = 0;
|
this._components.length = 0;
|
||||||
this._updatableComponents.length = 0;
|
this._updatableComponents.length = 0;
|
||||||
this._componentsToAdd = {};
|
this._componentsToAdd = {};
|
||||||
@@ -90,7 +86,7 @@ module es {
|
|||||||
if (isIUpdatable(component))
|
if (isIUpdatable(component))
|
||||||
new es.List(this._updatableComponents).remove(component);
|
new es.List(this._updatableComponents).remove(component);
|
||||||
|
|
||||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)), false);
|
this.decreaseBits(component);
|
||||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,11 +96,23 @@ module es {
|
|||||||
if (isIUpdatable(component))
|
if (isIUpdatable(component))
|
||||||
this._updatableComponents.push(component);
|
this._updatableComponents.push(component);
|
||||||
|
|
||||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)));
|
this.addBits(component);
|
||||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private decreaseBits(component: Component) {
|
||||||
|
let bits = this._entity.componentBits;
|
||||||
|
let typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
|
||||||
|
bits.set(typeIndex, bits.get(typeIndex) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addBits(component: Component) {
|
||||||
|
let bits = this._entity.componentBits;
|
||||||
|
let typeIndex = ComponentTypeManager.getIndexFor(TypeUtils.getType(component));
|
||||||
|
bits.set(typeIndex, bits.get(typeIndex) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理任何需要删除或添加的组件
|
* 处理任何需要删除或添加的组件
|
||||||
*/
|
*/
|
||||||
@@ -119,7 +127,7 @@ module es {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.removeFastComponent(component);
|
this.removeComponentsByType(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._componentsToRemove = {};
|
this._componentsToRemove = {};
|
||||||
@@ -130,17 +138,17 @@ module es {
|
|||||||
if (isIUpdatable(component))
|
if (isIUpdatable(component))
|
||||||
this._updatableComponents.push(component);
|
this._updatableComponents.push(component);
|
||||||
|
|
||||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)));
|
this.addBits(component);
|
||||||
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
this._entity.scene.entityProcessors.onComponentAdded(this._entity);
|
||||||
this.addFastComponent(component);
|
|
||||||
|
|
||||||
|
this.addComponentsByType(component);
|
||||||
this._components.push(component);
|
this._components.push(component);
|
||||||
this._tempBufferList.push(component);
|
this._tempBufferList.push(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在调用onAddedToEntity之前清除,以防添加更多组件
|
// 在调用onAddedToEntity之前清除,以防添加更多组件
|
||||||
this._componentsToAdd = {};
|
this._componentsToAdd = {};
|
||||||
this.fastComponentsToAddMap.clear();
|
this.componentsToAddByType.clear();
|
||||||
this._isComponentListUnsorted = true;
|
this._isComponentListUnsorted = true;
|
||||||
|
|
||||||
// 现在所有的组件都添加到了场景中,我们再次循环并调用onAddedToEntity/onEnabled
|
// 现在所有的组件都添加到了场景中,我们再次循环并调用onAddedToEntity/onEnabled
|
||||||
@@ -161,41 +169,41 @@ module es {
|
|||||||
if (isIUpdatable(component))
|
if (isIUpdatable(component))
|
||||||
new es.List(this._updatableComponents).remove(component);
|
new es.List(this._updatableComponents).remove(component);
|
||||||
|
|
||||||
this._entity.componentBits.set(ComponentTypeManager.getIndexFor(TypeUtils.getType(component)), false);
|
this.decreaseBits(component);
|
||||||
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
this._entity.scene.entityProcessors.onComponentRemoved(this._entity);
|
||||||
|
|
||||||
component.onRemovedFromEntity();
|
component.onRemovedFromEntity();
|
||||||
component.entity = null;
|
component.entity = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeFastComponent(component: Component) {
|
private removeComponentsByType(component: Component) {
|
||||||
let fastList = this.fastComponentsMap.get(TypeUtils.getType(component));
|
let fastList = this.componentsByType.get(TypeUtils.getType(component));
|
||||||
let fastIndex = fastList.findIndex(c => c.id == component.id);
|
let fastIndex = fastList.findIndex(c => c.id == component.id);
|
||||||
if (fastIndex != -1)
|
if (fastIndex != -1) {
|
||||||
fastList.splice(fastIndex, 1);
|
fastList.splice(fastIndex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private addFastComponent(component: Component) {
|
|
||||||
let fastList = this.fastComponentsMap.get(TypeUtils.getType(component));
|
|
||||||
if (!fastList)
|
|
||||||
fastList = [];
|
|
||||||
fastList.push(component);
|
|
||||||
this.fastComponentsMap.set(TypeUtils.getType(component), fastList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeFastComponentToAdd(component: Component) {
|
private addComponentsByType(component: Component) {
|
||||||
let fastList = this.fastComponentsToAddMap.get(TypeUtils.getType(component));
|
let fastList = this.componentsByType.get(TypeUtils.getType(component));
|
||||||
|
if (!fastList) fastList = [];
|
||||||
|
fastList.push(component);
|
||||||
|
this.componentsByType.set(TypeUtils.getType(component), fastList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeComponentsToAddByType(component: Component) {
|
||||||
|
let fastList = this.componentsToAddByType.get(TypeUtils.getType(component));
|
||||||
let fastIndex = fastList.findIndex(c => c.id == component.id);
|
let fastIndex = fastList.findIndex(c => c.id == component.id);
|
||||||
if (fastIndex != -1)
|
if (fastIndex != -1) {
|
||||||
fastList.splice(fastIndex, 1);
|
fastList.splice(fastIndex, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private addFastComponentToAdd(component: Component) {
|
private addComponentsToAddByType(component: Component) {
|
||||||
let fastList = this.fastComponentsToAddMap.get(TypeUtils.getType(component));
|
let fastList = this.componentsToAddByType.get(TypeUtils.getType(component));
|
||||||
if (!fastList)
|
if (!fastList) fastList = [];
|
||||||
fastList = [];
|
|
||||||
fastList.push(component);
|
fastList.push(component);
|
||||||
this.fastComponentsToAddMap.set(TypeUtils.getType(component), fastList);
|
this.componentsToAddByType.set(TypeUtils.getType(component), fastList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,13 +214,13 @@ module es {
|
|||||||
* @param onlyReturnInitializedComponents
|
* @param onlyReturnInitializedComponents
|
||||||
*/
|
*/
|
||||||
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T {
|
public getComponent<T extends Component>(type, onlyReturnInitializedComponents: boolean): T {
|
||||||
let fastList = this.fastComponentsMap.get(type);
|
let fastList = this.componentsByType.get(type);
|
||||||
if (fastList && fastList.length > 0)
|
if (fastList && fastList.length > 0)
|
||||||
return fastList[0] as T;
|
return fastList[0] as T;
|
||||||
|
|
||||||
// 我们可以选择检查挂起的组件,以防addComponent和getComponent在同一个框架中被调用
|
// 我们可以选择检查挂起的组件,以防addComponent和getComponent在同一个框架中被调用
|
||||||
if (!onlyReturnInitializedComponents) {
|
if (!onlyReturnInitializedComponents) {
|
||||||
let fastToAddList = this.fastComponentsToAddMap.get(type);
|
let fastToAddList = this.componentsToAddByType.get(type);
|
||||||
if (fastToAddList && fastToAddList.length > 0)
|
if (fastToAddList && fastToAddList.length > 0)
|
||||||
return fastToAddList[0] as T;
|
return fastToAddList[0] as T;
|
||||||
}
|
}
|
||||||
@@ -229,11 +237,11 @@ module es {
|
|||||||
if (!components)
|
if (!components)
|
||||||
components = [];
|
components = [];
|
||||||
|
|
||||||
let fastList = this.fastComponentsMap.get(typeName);
|
let fastList = this.componentsByType.get(typeName);
|
||||||
if (fastList)
|
if (fastList)
|
||||||
components = components.concat(fastList);
|
components = components.concat(fastList);
|
||||||
|
|
||||||
let fastToAddList = this.fastComponentsToAddMap.get(typeName);
|
let fastToAddList = this.componentsToAddByType.get(typeName);
|
||||||
if (fastToAddList)
|
if (fastToAddList)
|
||||||
components = components.concat(fastToAddList);
|
components = components.concat(fastToAddList);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
module es {
|
module es {
|
||||||
export class Matcher {
|
export class Matcher {
|
||||||
protected allSet = new BitSet();
|
protected allSet: (new (...args: any[]) => Component)[] = [];
|
||||||
protected exclusionSet = new BitSet();
|
protected exclusionSet: (new (...args: any[]) => Component)[] = [];
|
||||||
protected oneSet = new BitSet();
|
protected oneSet: (new (...args: any[]) => Component)[] = [];
|
||||||
|
|
||||||
public static empty() {
|
public static empty() {
|
||||||
return new Matcher();
|
return new Matcher();
|
||||||
@@ -24,46 +24,53 @@ module es {
|
|||||||
return this.isInterested(e.componentBits);
|
return this.isInterested(e.componentBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isInterested(componentBits: BitSet) {
|
public isInterested(components: Bits) {
|
||||||
// 检查实体是否拥有该方面中定义的所有组件
|
if (this.allSet.length != 0) {
|
||||||
if (!this.allSet.isEmpty()) {
|
for (let s of this.allSet) {
|
||||||
for (let i = this.allSet.nextSetBit(0); i >= 0; i = this.allSet.nextSetBit(i + 1)) {
|
if (!components.get(ComponentTypeManager.getIndexFor(s)))
|
||||||
if (!componentBits.get(i))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果我们仍然感兴趣,检查该实体是否拥有任何一个排除组件,如果有,那么系统就不感兴趣
|
if (this.exclusionSet.length != 0) {
|
||||||
if (!this.exclusionSet.isEmpty() && this.exclusionSet.intersects(componentBits))
|
for (let s of this.exclusionSet) {
|
||||||
|
if (components.get(ComponentTypeManager.getIndexFor(s)))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 如果我们仍然感兴趣,检查该实体是否拥有oneSet中的任何一个组件。如果是,系统就会感兴趣
|
if (this.oneSet.length != 0) {
|
||||||
if (!this.oneSet.isEmpty() && !this.oneSet.intersects(componentBits))
|
for (let s of this.oneSet) {
|
||||||
return false;
|
if (components.get(ComponentTypeManager.getIndexFor(s)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public all(...types: any[]): Matcher {
|
public all(...types: any[]): Matcher {
|
||||||
types.forEach(type => {
|
let t;
|
||||||
this.allSet.set(ComponentTypeManager.getIndexFor(type));
|
for (t of types) {
|
||||||
});
|
this.allSet.push(t);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public exclude(...types: any[]) {
|
public exclude(...types: any[]) {
|
||||||
types.forEach(type => {
|
let t;
|
||||||
this.exclusionSet.set(ComponentTypeManager.getIndexFor(type));
|
for (t of types) {
|
||||||
});
|
this.exclusionSet.push(t);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public one(...types: any[]) {
|
public one(...types: any[]) {
|
||||||
types.forEach(type => {
|
for (const t of types) {
|
||||||
this.oneSet.set(ComponentTypeManager.getIndexFor(type));
|
this.oneSet.push(t);
|
||||||
});
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user