优化实体列表add/remove效率。性能大幅度提高

This commit is contained in:
yhh
2021-04-16 17:48:13 +08:00
parent 5a6d1c72fe
commit 17b36f01b0
14 changed files with 1494 additions and 211 deletions

View File

@@ -203,6 +203,17 @@ declare module es {
setUpdateOrder(updateOrder: number): this; setUpdateOrder(updateOrder: number): this;
} }
} }
declare module es {
class ComponentType {
static INDEX: number;
private index_;
private type_;
constructor(type: Class, index?: number);
getName(): string;
getIndex(): number;
toString(): string;
}
}
declare module es { declare module es {
enum CoreEvents { enum CoreEvents {
/** /**
@@ -250,6 +261,7 @@ declare module es {
* 返回一个BitSet实例包含实体拥有的组件的位 * 返回一个BitSet实例包含实体拥有的组件的位
*/ */
componentBits: BitSet; componentBits: BitSet;
private systemBits_;
constructor(name: string); constructor(name: string);
_isDestroyed: boolean; _isDestroyed: boolean;
/** /**
@@ -283,6 +295,7 @@ 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;
@@ -562,16 +575,6 @@ declare module es {
} }
} }
declare module es { declare module es {
enum SceneResolutionPolicy {
/**
* 默认情况下RenderTarget与屏幕大小匹配。RenderTarget与屏幕大小相匹配
*/
none = 0,
/**
* 该应用程序采用最适合设计分辨率的宽度和高度
*/
bestFit = 1
}
/** 场景 */ /** 场景 */
class Scene { class Scene {
/** /**
@@ -652,11 +655,6 @@ declare module es {
* @returns * @returns
*/ */
findEntityWithTag(tag: number): Entity; findEntityWithTag(tag: number): Entity;
/**
* 返回类型为T的所有实体
* @param type
*/
entitiesOfType<T extends Entity>(type: any): T[];
/** /**
* 返回第一个启用加载的类型为T的组件 * 返回第一个启用加载的类型为T的组件
* @param type * @param type
@@ -1290,11 +1288,49 @@ declare module es {
} }
} }
declare module es { declare module es {
interface Map<K, V> {
clear(): void;
containsKey(key: any): boolean;
containsValue(value: any): boolean;
get(key: any): V;
isEmpty(): boolean;
put(key: any, value: any): void;
remove(key: any): V;
size(): number;
values(): V[];
}
class HashMap<K, V> implements Map<K, V> {
private map_;
private keys_;
constructor();
clear(): void;
values(): V[];
contains(value: any): boolean;
containsKey(key: any): boolean;
containsValue(value: any): boolean;
get(key: K): V;
isEmpty(): boolean;
keys(): K[];
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
put(key: any, value: any): void;
remove(key: any): V;
size(): number;
}
}
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;
/** /**
@@ -1745,11 +1781,15 @@ declare module es {
/** /**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/ */
_entitiesToAdded: HashSet<Entity>; _entitiesToAdded: {
[index: number]: Entity;
};
/** /**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/ */
_entitiesToRemove: HashSet<Entity>; _entitiesToRemove: {
[index: number]: Entity;
};
/** /**
* 标志,用于确定我们是否需要在这一帧中对实体进行排序 * 标志,用于确定我们是否需要在这一帧中对实体进行排序
*/ */
@@ -1805,12 +1845,6 @@ declare module es {
* @returns * @returns
*/ */
entityWithTag(tag: number): Entity; entityWithTag(tag: number): Entity;
/**
* 返回一个T类型的所有实体的列表。
* 返回的List可以通过ListPool.free放回池中。
* @param type
*/
entitiesOfType<T extends Entity>(type: any): T[];
/** /**
* 返回在场景中找到的第一个T类型的组件。 * 返回在场景中找到的第一个T类型的组件。
* @param type * @param type
@@ -3577,6 +3611,16 @@ declare module es {
private initialize; private initialize;
} }
} }
declare module es {
class UUID {
static randomUUID(): string;
}
}
declare module es {
interface Class extends Function {
}
function getClassName(klass: any): string;
}
declare namespace es { declare namespace es {
/** /**
* 记录时间的持续时间,一些设计灵感来自物理秒表。 * 记录时间的持续时间,一些设计灵感来自物理秒表。
@@ -3690,6 +3734,31 @@ declare namespace es {
readonly duration: number; readonly duration: number;
} }
} }
declare module es {
class Bag<E> implements ImmutableBag<E> {
size_: number;
length: number;
private array;
constructor(capacity?: number);
removeAt(index: number): E;
remove(e: E): boolean;
removeLast(): E;
contains(e: E): boolean;
removeAll(bag: ImmutableBag<E>): boolean;
get(index: number): E;
safeGet(index: number): E;
size(): number;
getCapacity(): number;
isIndexWithinBounds(index: number): boolean;
isEmpty(): boolean;
add(e: E): void;
set(index: number, e: E): void;
grow(newCapacity?: number): void;
ensureCapacity(index: number): void;
clear(): void;
addAll(items: ImmutableBag<E>): void;
}
}
declare module es { declare module es {
/** /**
* 创建这个字典的原因只有一个: * 创建这个字典的原因只有一个:
@@ -3737,6 +3806,14 @@ declare module es {
constructor(key: any, hash: number, previousNode?: number); constructor(key: any, hash: number, previousNode?: number);
} }
} }
declare module es {
interface ImmutableBag<E> {
get(index: number): E;
size(): number;
isEmpty(): boolean;
contains(e: E): boolean;
}
}
declare module es { declare module es {
class Node<T> { class Node<T> {
element: T; element: T;

View File

@@ -543,6 +543,33 @@ var es;
es.Component = Component; es.Component = Component;
})(es || (es = {})); })(es || (es = {}));
var es; var es;
(function (es) {
var ComponentType = /** @class */ (function () {
function ComponentType(type, index) {
this.index_ = 0;
if (index !== undefined) {
this.index_ = ComponentType.INDEX++;
}
else {
this.index_ = index;
}
this.type_ = type;
}
ComponentType.prototype.getName = function () {
return es.getClassName(this.type_);
};
ComponentType.prototype.getIndex = function () {
return this.index_;
};
ComponentType.prototype.toString = function () {
return "ComponentType[" + es.getClassName(ComponentType) + "] (" + this.index_ + ")";
};
ComponentType.INDEX = 0;
return ComponentType;
}());
es.ComponentType = ComponentType;
})(es || (es = {}));
var es;
(function (es) { (function (es) {
var CoreEvents; var CoreEvents;
(function (CoreEvents) { (function (CoreEvents) {
@@ -583,6 +610,7 @@ var es;
this.transform = new es.Transform(this); this.transform = new es.Transform(this);
this.name = name; this.name = name;
this.id = Entity._idGenerator++; this.id = Entity._idGenerator++;
this.systemBits_ = new es.BitSet();
this.componentBits = new es.BitSet(); this.componentBits = new es.BitSet();
} }
Object.defineProperty(Entity.prototype, "isDestroyed", { Object.defineProperty(Entity.prototype, "isDestroyed", {
@@ -646,6 +674,9 @@ var es;
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
Entity.prototype.getSystemBits = function () {
return this.systemBits_;
};
Object.defineProperty(Entity.prototype, "parent", { Object.defineProperty(Entity.prototype, "parent", {
get: function () { get: function () {
return this.transform.parent; return this.transform.parent;
@@ -1300,17 +1331,6 @@ var es;
var es; var es;
///<reference path="../Math/Vector2.ts" /> ///<reference path="../Math/Vector2.ts" />
(function (es) { (function (es) {
var SceneResolutionPolicy;
(function (SceneResolutionPolicy) {
/**
* 默认情况下RenderTarget与屏幕大小匹配。RenderTarget与屏幕大小相匹配
*/
SceneResolutionPolicy[SceneResolutionPolicy["none"] = 0] = "none";
/**
* 该应用程序采用最适合设计分辨率的宽度和高度
*/
SceneResolutionPolicy[SceneResolutionPolicy["bestFit"] = 1] = "bestFit";
})(SceneResolutionPolicy = es.SceneResolutionPolicy || (es.SceneResolutionPolicy = {}));
/** 场景 */ /** 场景 */
var Scene = /** @class */ (function () { var Scene = /** @class */ (function () {
function Scene() { function Scene() {
@@ -1463,13 +1483,6 @@ var es;
Scene.prototype.findEntityWithTag = function (tag) { Scene.prototype.findEntityWithTag = function (tag) {
return this.entities.entityWithTag(tag); return this.entities.entityWithTag(tag);
}; };
/**
* 返回类型为T的所有实体
* @param type
*/
Scene.prototype.entitiesOfType = function (type) {
return this.entities.entitiesOfType(type);
};
/** /**
* 返回第一个启用加载的类型为T的组件 * 返回第一个启用加载的类型为T的组件
* @param type * @param type
@@ -2974,6 +2987,115 @@ var es;
})(es || (es = {})); })(es || (es = {}));
var es; var es;
(function (es) { (function (es) {
function decode(key) {
switch (typeof key) {
case "boolean":
return "" + key;
case "number":
return "" + key;
case "string":
return "" + key;
case "function":
return es.getClassName(key);
default:
key.uuid = key.uuid ? key.uuid : es.UUID.randomUUID();
return key.uuid;
}
}
var HashMap = /** @class */ (function () {
function HashMap() {
this.clear();
}
HashMap.prototype.clear = function () {
this.map_ = {};
this.keys_ = {};
};
HashMap.prototype.values = function () {
var result = [];
var map = this.map_;
for (var key in map) {
result.push(map[key]);
}
return result;
};
HashMap.prototype.contains = function (value) {
var map = this.map_;
for (var key in map) {
if (value === map[key]) {
return true;
}
}
return false;
};
HashMap.prototype.containsKey = function (key) {
return decode(key) in this.map_;
};
HashMap.prototype.containsValue = function (value) {
var map = this.map_;
for (var key in map) {
if (value === map[key]) {
return true;
}
}
return false;
};
HashMap.prototype.get = function (key) {
return this.map_[decode(key)];
};
HashMap.prototype.isEmpty = function () {
return Object.keys(this.map_).length === 0;
};
HashMap.prototype.keys = function () {
var keys = this.map_;
var result = [];
for (var key in keys) {
result.push(keys[key]);
}
return result;
};
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
HashMap.prototype.put = function (key, value) {
var k = decode(key);
this.map_[k] = value;
this.keys_[k] = key;
};
HashMap.prototype.remove = function (key) {
var map = this.map_;
var k = decode(key);
var value = map[k];
delete map[k];
delete this.keys_[k];
return value;
};
HashMap.prototype.size = function () {
return Object.keys(this.map_).length;
};
return HashMap;
}());
es.HashMap = HashMap;
})(es || (es = {}));
///<reference path="../../Utils/Collections/HashMap.ts"/>
var es;
///<reference path="../../Utils/Collections/HashMap.ts"/>
(function (es_1) {
var SystemIndexManager = /** @class */ (function () {
function SystemIndexManager() {
}
SystemIndexManager.getIndexFor = function (es) {
var index = SystemIndexManager.indices.get(es);
if (index === undefined) {
index = SystemIndexManager.INDEX++;
SystemIndexManager.indices.put(es, index);
}
return index;
};
SystemIndexManager.INDEX = 0;
SystemIndexManager.indices = new es_1.HashMap();
return SystemIndexManager;
}());
es_1.SystemIndexManager = SystemIndexManager;
/** /**
* 追踪实体的子集,但不实现任何排序或迭代。 * 追踪实体的子集,但不实现任何排序或迭代。
*/ */
@@ -2983,7 +3105,8 @@ var es;
this._startTime = 0; this._startTime = 0;
this._endTime = 0; this._endTime = 0;
this._useTime = 0; this._useTime = 0;
this._matcher = matcher ? matcher : es.Matcher.empty(); this._matcher = matcher ? matcher : es_1.Matcher.empty();
this.systemIndex_ = SystemIndexManager.getIndexFor(this.constructor);
this.initialize(); this.initialize();
} }
Object.defineProperty(EntitySystem.prototype, "scene", { Object.defineProperty(EntitySystem.prototype, "scene", {
@@ -3018,7 +3141,7 @@ var es;
EntitySystem.prototype.initialize = function () { EntitySystem.prototype.initialize = function () {
}; };
EntitySystem.prototype.onChanged = function (entity) { EntitySystem.prototype.onChanged = function (entity) {
var contains = new es.List(this._entities).contains(entity); var contains = entity.getSystemBits().get(this.systemIndex_);
var interest = this._matcher.isInterestedEntity(entity); var interest = this._matcher.isInterestedEntity(entity);
if (interest && !contains) if (interest && !contains)
this.add(entity); this.add(entity);
@@ -3027,11 +3150,13 @@ var es;
}; };
EntitySystem.prototype.add = function (entity) { EntitySystem.prototype.add = function (entity) {
this._entities.push(entity); this._entities.push(entity);
entity.getSystemBits().set(this.systemIndex_);
this.onAdded(entity); this.onAdded(entity);
}; };
EntitySystem.prototype.onAdded = function (entity) { }; EntitySystem.prototype.onAdded = function (entity) { };
EntitySystem.prototype.remove = function (entity) { EntitySystem.prototype.remove = function (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);
}; };
EntitySystem.prototype.onRemoved = function (entity) { }; EntitySystem.prototype.onRemoved = function (entity) { };
@@ -3052,7 +3177,7 @@ var es;
* 在下一个系统开始处理或新的处理回合开始之前(以先到者为准),使用此方法创建的任何实体都不会激活 * 在下一个系统开始处理或新的处理回合开始之前(以先到者为准),使用此方法创建的任何实体都不会激活
*/ */
EntitySystem.prototype.begin = function () { EntitySystem.prototype.begin = function () {
if (!es.Core.Instance.debug) if (!es_1.Core.Instance.debug)
return; return;
this._startTime = Date.now(); this._startTime = Date.now();
}; };
@@ -3062,7 +3187,7 @@ var es;
* 系统处理完毕后调用 * 系统处理完毕后调用
*/ */
EntitySystem.prototype.end = function () { EntitySystem.prototype.end = function () {
if (!es.Core.Instance.debug) if (!es_1.Core.Instance.debug)
return; return;
this._endTime = Date.now(); this._endTime = Date.now();
this._useTime = this._endTime - this._startTime; this._useTime = this._endTime - this._startTime;
@@ -3079,7 +3204,7 @@ var es;
}; };
return EntitySystem; return EntitySystem;
}()); }());
es.EntitySystem = EntitySystem; es_1.EntitySystem = EntitySystem;
})(es || (es = {})); })(es || (es = {}));
///<reference path="./EntitySystem.ts"/> ///<reference path="./EntitySystem.ts"/>
var es; var es;
@@ -4026,10 +4151,10 @@ var es;
} }
this._tempBufferList.length = 0; this._tempBufferList.length = 0;
} }
if (this._isComponentListUnsorted) { // if (this._isComponentListUnsorted) {
this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare); // this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare);
this._isComponentListUnsorted = false; // this._isComponentListUnsorted = false;
} // }
}; };
ComponentList.prototype.handleRemove = function (component) { ComponentList.prototype.handleRemove = function (component) {
if (es.isIUpdatable(component)) if (es.isIUpdatable(component))
@@ -4192,11 +4317,12 @@ var es;
/** /**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/ */
this._entitiesToAdded = new es.HashSet(); // public _entitiesToAdded: Entity[] = [];
this._entitiesToAdded = {};
/** /**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/ */
this._entitiesToRemove = new es.HashSet(); this._entitiesToRemove = {};
/** /**
* 通过标签跟踪实体,便于检索 * 通过标签跟踪实体,便于检索
*/ */
@@ -4229,28 +4355,27 @@ var es;
* @param entity * @param entity
*/ */
EntityList.prototype.add = function (entity) { EntityList.prototype.add = function (entity) {
this._entitiesToAdded.add(entity); this._entitiesToAdded[entity.id] = entity;
}; };
/** /**
* 从列表中删除一个实体。所有的生命周期方法将在下一帧中被调用 * 从列表中删除一个实体。所有的生命周期方法将在下一帧中被调用
* @param entity * @param entity
*/ */
EntityList.prototype.remove = function (entity) { EntityList.prototype.remove = function (entity) {
es.Debug.warnIf(this._entitiesToRemove.contains(entity), "\u60A8\u6B63\u5728\u5C1D\u8BD5\u5220\u9664\u5DF2\u7ECF\u5220\u9664\u7684\u5B9E\u4F53(" + entity.name + ")");
// 防止在同一帧中添加或删除实体 // 防止在同一帧中添加或删除实体
if (this._entitiesToAdded.contains(entity)) { if (this._entitiesToAdded[entity.id]) {
this._entitiesToAdded.remove(entity); delete this._entitiesToAdded[entity.id];
return; return;
} }
if (!this._entitiesToRemove.contains(entity)) if (!this._entitiesToRemove[entity.id])
this._entitiesToRemove.add(entity); this._entitiesToRemove[entity.id] = entity;
}; };
/** /**
* 从实体列表中删除所有实体 * 从实体列表中删除所有实体
*/ */
EntityList.prototype.removeAllEntities = function () { EntityList.prototype.removeAllEntities = function () {
this._unsortedTags.clear(); this._unsortedTags.clear();
this._entitiesToAdded.clear(); this._entitiesToAdded = {};
this._isEntityListUnsorted = false; this._isEntityListUnsorted = false;
// 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体。 // 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体。
// 它们仍然会在_entitiesToRemove列表中这将由updateLists处理。 // 它们仍然会在_entitiesToRemove列表中这将由updateLists处理。
@@ -4268,7 +4393,7 @@ var es;
* @param entity * @param entity
*/ */
EntityList.prototype.contains = function (entity) { EntityList.prototype.contains = function (entity) {
return new es.List(this._entities).contains(entity) || this._entitiesToAdded.contains(entity); return !!this._entitiesToAdded[entity.id];
}; };
EntityList.prototype.getTagList = function (tag) { EntityList.prototype.getTagList = function (tag) {
var list = this._entityDict.get(tag); var list = this._entityDict.get(tag);
@@ -4305,36 +4430,32 @@ var es;
} }
}; };
EntityList.prototype.updateLists = function () { EntityList.prototype.updateLists = function () {
var _this = this; for (var i in this._entitiesToRemove) {
if (this._entitiesToRemove.getCount() > 0) { var entity = this._entitiesToRemove[i];
this._entitiesToRemove.toArray().forEach(function (entity) { this.removeFromTagList(entity);
// 处理标签列表 // 处理常规实体列表
_this.removeFromTagList(entity); new es.List(this._entities).remove(entity);
// 处理常规实体列表 entity.onRemovedFromScene();
new es.List(_this._entities).remove(entity); entity.scene = null;
entity.onRemovedFromScene(); this.scene.entityProcessors.onEntityRemoved(entity);
entity.scene = null;
_this.scene.entityProcessors.onEntityRemoved(entity);
});
this._entitiesToRemove.clear();
} }
if (this._entitiesToAdded.getCount() > 0) { this._entitiesToRemove = {};
this._entitiesToAdded.toArray().forEach(function (entity) { for (var i in this._entitiesToAdded) {
_this._entities.push(entity); var entity = this._entitiesToAdded[i];
entity.scene = _this.scene; this._entities.push(entity);
_this.addToTagList(entity); entity.scene = this.scene;
_this.scene.entityProcessors.onEntityAdded(entity); this.addToTagList(entity);
}); this.scene.entityProcessors.onEntityAdded(entity);
this._entitiesToAdded.toArray().forEach(function (entity) {
entity.onAddedToScene();
});
this._entitiesToAdded.clear();
this._isEntityListUnsorted = true;
} }
if (this._isEntityListUnsorted) { for (var i in this._entitiesToAdded) {
this._entities.sort(es.Entity.entityComparer.compare); this._entitiesToAdded[i].onAddedToScene();
this._isEntityListUnsorted = false;
} }
this._entitiesToAdded = {};
// this._isEntityListUnsorted = true;
// if (this._isEntityListUnsorted) {
// this._entities.sort(Entity.entityComparer.compare);
// this._isEntityListUnsorted = false;
// }
}; };
/** /**
* 返回第一个找到的名字为name的实体。如果没有找到则返回null * 返回第一个找到的名字为name的实体。如果没有找到则返回null
@@ -4345,8 +4466,13 @@ var es;
if (this._entities[i].name == name) if (this._entities[i].name == name)
return this._entities[i]; return this._entities[i];
} }
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.size; i++) {
var entity = this._entitiesToAdded.toArray()[i]; // let entity = this._entitiesToAdded.values;
// if (entity.name == name)
// return entity;
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.name == name) if (entity.name == name)
return entity; return entity;
} }
@@ -4399,25 +4525,6 @@ var es;
} }
return null; return null;
}; };
/**
* 返回一个T类型的所有实体的列表。
* 返回的List可以通过ListPool.free放回池中。
* @param type
*/
EntityList.prototype.entitiesOfType = function (type) {
var list = es.ListPool.obtain();
for (var i = 0; i < this._entities.length; i++) {
if (this._entities[i] instanceof type)
list.push(this._entities[i]);
}
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i];
if (es.TypeUtils.getType(entity) instanceof type) {
list.push(entity);
}
}
return list;
};
/** /**
* 返回在场景中找到的第一个T类型的组件。 * 返回在场景中找到的第一个T类型的组件。
* @param type * @param type
@@ -4430,8 +4537,16 @@ var es;
return comp; return comp;
} }
} }
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i]; // let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let comp = entity.getComponent<T>(type);
// if (comp)
// return comp;
// }
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.enabled) { if (entity.enabled) {
var comp = entity.getComponent(type); var comp = entity.getComponent(type);
if (comp) if (comp)
@@ -4451,8 +4566,13 @@ var es;
if (this._entities[i].enabled) if (this._entities[i].enabled)
this._entities[i].getComponents(type, comps); this._entities[i].getComponents(type, comps);
} }
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i]; // let entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled)
// entity.getComponents(type, comps);
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.enabled) if (entity.enabled)
entity.getComponents(type, comps); entity.getComponents(type, comps);
} }
@@ -4495,8 +4615,24 @@ var es;
} }
} }
} }
for (var i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
var entity = this._entitiesToAdded.toArray()[i]; // let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let meet = true;
// for (let type of types) {
// let hasComp = entity.hasComponent(type);
// if (!hasComp) {
// meet = false;
// break;
// }
// }
// if (meet) {
// entities.push(entity);
// }
// }
// }
for (var i in this._entitiesToAdded) {
var entity = this._entitiesToAdded[i];
if (entity.enabled) { if (entity.enabled) {
var meet = true; var meet = true;
try { try {
@@ -8979,6 +9115,307 @@ var es;
es.Triangulator = Triangulator; es.Triangulator = Triangulator;
})(es || (es = {})); })(es || (es = {}));
var es; var es;
(function (es) {
var hex = [
// hex identity values 0-255
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
"60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
"70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
"b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
"c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
"d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
"e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
"f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
];
var UUID = /** @class */ (function () {
function UUID() {
}
UUID.randomUUID = function () {
var d0 = (Math.random() * 0xffffffff) | 0;
var d1 = (Math.random() * 0xffffffff) | 0;
var d2 = (Math.random() * 0xffffffff) | 0;
var d3 = (Math.random() * 0xffffffff) | 0;
return (hex[d0 & 0xff] +
hex[(d0 >> 8) & 0xff] +
hex[(d0 >> 16) & 0xff] +
hex[(d0 >> 24) & 0xff] +
"-" +
hex[d1 & 0xff] +
hex[(d1 >> 8) & 0xff] +
"-" +
hex[((d1 >> 16) & 0x0f) | 0x40] +
hex[(d1 >> 24) & 0xff] +
"-" +
hex[(d2 & 0x3f) | 0x80] +
hex[(d2 >> 8) & 0xff] +
"-" +
hex[(d2 >> 16) & 0xff] +
hex[(d2 >> 24) & 0xff] +
hex[d3 & 0xff] +
hex[(d3 >> 8) & 0xff] +
hex[(d3 >> 16) & 0xff] +
hex[(d3 >> 24) & 0xff]);
};
return UUID;
}());
es.UUID = UUID;
})(es || (es = {}));
var es;
(function (es) {
function getClassName(klass) {
return klass.className || klass.name;
}
es.getClassName = getClassName;
})(es || (es = {}));
var es;
(function (es) { (function (es) {
/** /**
* 记录时间的持续时间,一些设计灵感来自物理秒表。 * 记录时间的持续时间,一些设计灵感来自物理秒表。
@@ -9163,6 +9600,139 @@ var es;
var _defaultSystemTimeGetter = Date.now; var _defaultSystemTimeGetter = Date.now;
})(es || (es = {})); })(es || (es = {}));
var es; var es;
(function (es) {
var Bag = /** @class */ (function () {
function Bag(capacity) {
if (capacity === void 0) { capacity = 64; }
this.size_ = 0;
this.length = 0;
this.array = [];
this.length = capacity;
}
Bag.prototype.removeAt = function (index) {
var e = this.array[index];
this.array[index] = this.array[--this.size_];
this.array[this.size_] = null;
return e;
};
Bag.prototype.remove = function (e) {
var i;
var e2;
var size = this.size_;
for (i = 0; i < size; i++) {
e2 = this.array[i];
if (e == e2) {
this.array[i] = this.array[--this.size_];
this.array[this.size_] = null;
return true;
}
}
return false;
};
Bag.prototype.removeLast = function () {
if (this.size_ > 0) {
var e = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
return null;
};
Bag.prototype.contains = function (e) {
var i;
var size;
for (i = 0, size = this.size_; size > i; i++) {
if (e === this.array[i]) {
return true;
}
}
return false;
};
Bag.prototype.removeAll = function (bag) {
var modified = false;
var i;
var j;
var l;
var e1;
var e2;
for (i = 0, l = bag.size(); i < l; i++) {
e1 = bag[i];
for (j = 0; j < this.size_; j++) {
e2 = this.array[j];
if (e1 === e2) {
this.removeAt(j);
j--;
modified = true;
break;
}
}
}
return modified;
};
Bag.prototype.get = function (index) {
if (index >= this.length) {
throw new Error("ArrayIndexOutOfBoundsException");
}
return this.array[index];
};
Bag.prototype.safeGet = function (index) {
if (index >= this.length) {
this.grow((index * 7) / 4 + 1);
}
return this.array[index];
};
Bag.prototype.size = function () {
return this.size_;
};
Bag.prototype.getCapacity = function () {
return this.length;
};
Bag.prototype.isIndexWithinBounds = function (index) {
return index < this.getCapacity();
};
Bag.prototype.isEmpty = function () {
return this.size_ == 0;
};
Bag.prototype.add = function (e) {
if (this.size_ === this.length) {
this.grow();
}
this.array[this.size_++] = e;
};
Bag.prototype.set = function (index, e) {
if (index >= this.length) {
this.grow(index * 2);
}
this.size_ = index + 1;
this.array[index] = e;
};
Bag.prototype.grow = function (newCapacity) {
if (newCapacity === void 0) { newCapacity = ~~((this.length * 3) / 2) + 1; }
this.length = ~~newCapacity;
};
Bag.prototype.ensureCapacity = function (index) {
if (index >= this.length) {
this.grow(index * 2);
}
};
Bag.prototype.clear = function () {
var i;
var size;
for (i = 0, size = this.size_; i < size; i++) {
this.array[i] = null;
}
this.size_ = 0;
};
Bag.prototype.addAll = function (items) {
var i;
for (i = 0; items.size() > i; i++) {
this.add(items.get(i));
}
};
return Bag;
}());
es.Bag = Bag;
})(es || (es = {}));
var es;
(function (es) { (function (es) {
/** /**
* 创建这个字典的原因只有一个: * 创建这个字典的原因只有一个:

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
module es {
export class ComponentType {
public static INDEX = 0;
private index_ = 0;
private type_: Class;
constructor(type: Class, index?: number) {
if (index !== undefined) {
this.index_ = ComponentType.INDEX++;
} else {
this.index_ = index;
}
this.type_ = type;
}
public getName(): string {
return getClassName(this.type_);
}
public getIndex(): number {
return this.index_;
}
public toString(): string {
return "ComponentType[" + getClassName(ComponentType) + "] (" + this.index_ + ")";
}
}
}

View File

@@ -39,6 +39,7 @@ module es {
* 返回一个BitSet实例包含实体拥有的组件的位 * 返回一个BitSet实例包含实体拥有的组件的位
*/ */
public componentBits: BitSet; public componentBits: BitSet;
private systemBits_: BitSet;
constructor(name: string) { constructor(name: string) {
this.components = new ComponentList(this); this.components = new ComponentList(this);
@@ -46,6 +47,7 @@ module es {
this.name = name; this.name = name;
this.id = Entity._idGenerator++; this.id = Entity._idGenerator++;
this.systemBits_ = new BitSet();
this.componentBits = new BitSet(); this.componentBits = new BitSet();
} }
@@ -109,6 +111,10 @@ 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;
} }

View File

@@ -1,16 +1,5 @@
///<reference path="../Math/Vector2.ts" /> ///<reference path="../Math/Vector2.ts" />
module es { module es {
export enum SceneResolutionPolicy {
/**
* 默认情况下RenderTarget与屏幕大小匹配。RenderTarget与屏幕大小相匹配
*/
none,
/**
* 该应用程序采用最适合设计分辨率的宽度和高度
*/
bestFit
}
/** 场景 */ /** 场景 */
export class Scene { export class Scene {
/** /**
@@ -209,14 +198,6 @@ module es {
return this.entities.entityWithTag(tag); return this.entities.entityWithTag(tag);
} }
/**
* 返回类型为T的所有实体
* @param type
*/
public entitiesOfType<T extends Entity>(type): T[] {
return this.entities.entitiesOfType<T>(type);
}
/** /**
* 返回第一个启用加载的类型为T的组件 * 返回第一个启用加载的类型为T的组件
* @param type * @param type

View File

@@ -1,12 +1,29 @@
///<reference path="../../Utils/Collections/HashMap.ts"/>
module es { module es {
export class SystemIndexManager {
public static INDEX = 0;
private static indices: HashMap<Function, number> = new HashMap<Function, number>();
public static getIndexFor(es: Class): number {
let index: number = SystemIndexManager.indices.get(es);
if (index === undefined) {
index = SystemIndexManager.INDEX++;
SystemIndexManager.indices.put(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();
} }
@@ -43,7 +60,7 @@ module es {
} }
public onChanged(entity: Entity) { public onChanged(entity: Entity) {
let contains = new es.List(this._entities).contains(entity); let contains = entity.getSystemBits().get(this.systemIndex_);
let interest = this._matcher.isInterestedEntity(entity); let interest = this._matcher.isInterestedEntity(entity);
if (interest && !contains) if (interest && !contains)
@@ -54,6 +71,7 @@ module es {
public add(entity: Entity) { public add(entity: Entity) {
this._entities.push(entity); this._entities.push(entity);
entity.getSystemBits().set(this.systemIndex_);
this.onAdded(entity); this.onAdded(entity);
} }
@@ -61,6 +79,7 @@ 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);
} }

View File

@@ -145,10 +145,10 @@ module es {
this._tempBufferList.length = 0; this._tempBufferList.length = 0;
} }
if (this._isComponentListUnsorted) { // if (this._isComponentListUnsorted) {
this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare); // this._updatableComponents.sort(ComponentList.compareUpdatableOrder.compare);
this._isComponentListUnsorted = false; // this._isComponentListUnsorted = false;
} // }
} }
public handleRemove(component: Component) { public handleRemove(component: Component) {

View File

@@ -8,11 +8,12 @@ module es {
/** /**
* 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 本帧添加的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/ */
public _entitiesToAdded: HashSet<Entity> = new HashSet<Entity>(); // public _entitiesToAdded: Entity[] = [];
public _entitiesToAdded: {[index: number]: Entity} = {};
/** /**
* 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们 * 本帧被标记为删除的实体列表。用于对实体进行分组,以便我们可以同时处理它们
*/ */
public _entitiesToRemove: HashSet<Entity> = new HashSet<Entity>(); public _entitiesToRemove: {[index: number]: Entity} = {};
/** /**
* 标志,用于确定我们是否需要在这一帧中对实体进行排序 * 标志,用于确定我们是否需要在这一帧中对实体进行排序
*/ */
@@ -48,7 +49,7 @@ module es {
* @param entity * @param entity
*/ */
public add(entity: Entity) { public add(entity: Entity) {
this._entitiesToAdded.add(entity); this._entitiesToAdded[entity.id] = entity;
} }
/** /**
@@ -56,16 +57,14 @@ module es {
* @param entity * @param entity
*/ */
public remove(entity: Entity) { public remove(entity: Entity) {
Debug.warnIf(this._entitiesToRemove.contains(entity), `您正在尝试删除已经删除的实体(${entity.name})`);
// 防止在同一帧中添加或删除实体 // 防止在同一帧中添加或删除实体
if (this._entitiesToAdded.contains(entity)) { if (this._entitiesToAdded[entity.id]) {
this._entitiesToAdded.remove(entity); delete this._entitiesToAdded[entity.id];
return; return;
} }
if (!this._entitiesToRemove.contains(entity)) if (!this._entitiesToRemove[entity.id])
this._entitiesToRemove.add(entity); this._entitiesToRemove[entity.id] = entity;
} }
/** /**
@@ -73,7 +72,7 @@ module es {
*/ */
public removeAllEntities() { public removeAllEntities() {
this._unsortedTags.clear(); this._unsortedTags.clear();
this._entitiesToAdded.clear(); this._entitiesToAdded = {};
this._isEntityListUnsorted = false; this._isEntityListUnsorted = false;
// 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体。 // 为什么我们要在这里更新列表?主要是为了处理在场景切换前被分离的实体。
@@ -95,7 +94,7 @@ module es {
* @param entity * @param entity
*/ */
public contains(entity: Entity): boolean { public contains(entity: Entity): boolean {
return new es.List(this._entities).contains(entity) || this._entitiesToAdded.contains(entity); return !!this._entitiesToAdded[entity.id];
} }
public getTagList(tag: number) { public getTagList(tag: number) {
@@ -127,43 +126,40 @@ module es {
} }
public updateLists() { public updateLists() {
if (this._entitiesToRemove.getCount() > 0) { for (let i in this._entitiesToRemove) {
this._entitiesToRemove.toArray().forEach(entity => { let entity = this._entitiesToRemove[i];
// 处理标签列表 this.removeFromTagList(entity);
this.removeFromTagList(entity);
// 处理常规实体列表 // 处理常规实体列表
new es.List(this._entities).remove(entity); new es.List(this._entities).remove(entity);
entity.onRemovedFromScene(); entity.onRemovedFromScene();
entity.scene = null; entity.scene = null;
this.scene.entityProcessors.onEntityRemoved(entity); this.scene.entityProcessors.onEntityRemoved(entity);
}); }
this._entitiesToRemove.clear(); this._entitiesToRemove = {};
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
this._entities.push(entity);
entity.scene = this.scene;
this.addToTagList(entity);
this.scene.entityProcessors.onEntityAdded(entity);
} }
if (this._entitiesToAdded.getCount() > 0) { for (let i in this._entitiesToAdded) {
this._entitiesToAdded.toArray().forEach(entity => { this._entitiesToAdded[i].onAddedToScene();
this._entities.push(entity);
entity.scene = this.scene;
this.addToTagList(entity);
this.scene.entityProcessors.onEntityAdded(entity);
});
this._entitiesToAdded.toArray().forEach(entity => {
entity.onAddedToScene();
})
this._entitiesToAdded.clear();
this._isEntityListUnsorted = true;
} }
if (this._isEntityListUnsorted) { this._entitiesToAdded = {};
this._entities.sort(Entity.entityComparer.compare); // this._isEntityListUnsorted = true;
this._isEntityListUnsorted = false;
} // if (this._isEntityListUnsorted) {
// this._entities.sort(Entity.entityComparer.compare);
// this._isEntityListUnsorted = false;
// }
} }
/** /**
@@ -176,8 +172,13 @@ module es {
return this._entities[i]; return this._entities[i];
} }
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.size; i++) {
let entity = this._entitiesToAdded.toArray()[i]; // let entity = this._entitiesToAdded.values;
// if (entity.name == name)
// return entity;
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.name == name) if (entity.name == name)
return entity; return entity;
} }
@@ -216,28 +217,6 @@ module es {
return null; return null;
} }
/**
* 返回一个T类型的所有实体的列表。
* 返回的List可以通过ListPool.free放回池中。
* @param type
*/
public entitiesOfType<T extends Entity>(type): T[] {
let list = ListPool.obtain<T>();
for (let i = 0; i < this._entities.length; i++) {
if (this._entities[i] instanceof type)
list.push(this._entities[i] as T);
}
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity = this._entitiesToAdded.toArray()[i];
if (TypeUtils.getType(entity) instanceof type) {
list.push(entity as T);
}
}
return list;
}
/** /**
* 返回在场景中找到的第一个T类型的组件。 * 返回在场景中找到的第一个T类型的组件。
* @param type * @param type
@@ -251,8 +230,17 @@ module es {
} }
} }
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity: Entity = this._entitiesToAdded.toArray()[i]; // let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let comp = entity.getComponent<T>(type);
// if (comp)
// return comp;
// }
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.enabled) { if (entity.enabled) {
let comp = entity.getComponent<T>(type); let comp = entity.getComponent<T>(type);
if (comp) if (comp)
@@ -275,8 +263,14 @@ module es {
this._entities[i].getComponents(type, comps); this._entities[i].getComponents(type, comps);
} }
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity = this._entitiesToAdded.toArray()[i]; // let entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled)
// entity.getComponents(type, comps);
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.enabled) if (entity.enabled)
entity.getComponents(type, comps); entity.getComponents(type, comps);
} }
@@ -308,8 +302,26 @@ module es {
} }
} }
for (let i = 0; i < this._entitiesToAdded.getCount(); i++) { // for (let i = 0; i < this._entitiesToAdded.getCount(); i++) {
let entity: Entity = this._entitiesToAdded.toArray()[i]; // let entity: Entity = this._entitiesToAdded.toArray()[i];
// if (entity.enabled) {
// let meet = true;
// for (let type of types) {
// let hasComp = entity.hasComponent(type);
// if (!hasComp) {
// meet = false;
// break;
// }
// }
// if (meet) {
// entities.push(entity);
// }
// }
// }
for (let i in this._entitiesToAdded) {
let entity = this._entitiesToAdded[i];
if (entity.enabled) { if (entity.enabled) {
let meet = true; let meet = true;
for (let type of types) { for (let type of types) {

View File

@@ -0,0 +1,158 @@
module es {
export class Bag<E> implements ImmutableBag<E> {
public size_ = 0;
public length = 0;
private array: Array<E> = [];
constructor(capacity = 64) {
this.length = capacity;
}
removeAt(index: number): E {
const e: E = this.array[index];
this.array[index] = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
remove(e: E): boolean {
let i: number;
let e2: E;
const size = this.size_;
for (i = 0; i < size; i++) {
e2 = this.array[i];
if (e == e2) {
this.array[i] = this.array[--this.size_];
this.array[this.size_] = null;
return true;
}
}
return false;
}
removeLast(): E {
if (this.size_ > 0) {
const e: E = this.array[--this.size_];
this.array[this.size_] = null;
return e;
}
return null;
}
contains(e: E): boolean {
let i: number;
let size: number;
for (i = 0, size = this.size_; size > i; i++) {
if (e === this.array[i]) {
return true;
}
}
return false;
}
removeAll(bag: ImmutableBag<E>): boolean {
let modified = false;
let i: number;
let j: number;
let l: number;
let e1: E;
let e2: E;
for (i = 0, l = bag.size(); i < l; i++) {
e1 = bag[i];
for (j = 0; j < this.size_; j++) {
e2 = this.array[j];
if (e1 === e2) {
this.removeAt(j);
j--;
modified = true;
break;
}
}
}
return modified;
}
get(index: number): E {
if (index >= this.length) {
throw new Error("ArrayIndexOutOfBoundsException");
}
return this.array[index];
}
safeGet(index: number): E {
if (index >= this.length) {
this.grow((index * 7) / 4 + 1);
}
return this.array[index];
}
size(): number {
return this.size_;
}
getCapacity(): number {
return this.length;
}
isIndexWithinBounds(index: number): boolean {
return index < this.getCapacity();
}
isEmpty(): boolean {
return this.size_ == 0;
}
add(e: E): void {
if (this.size_ === this.length) {
this.grow();
}
this.array[this.size_++] = e;
}
set(index: number, e: E): void {
if (index >= this.length) {
this.grow(index * 2);
}
this.size_ = index + 1;
this.array[index] = e;
}
grow(newCapacity: number = ~~((this.length * 3) / 2) + 1): void {
this.length = ~~newCapacity;
}
ensureCapacity(index: number): void {
if (index >= this.length) {
this.grow(index * 2);
}
}
clear(): void {
let i: number;
let size: number;
for (i = 0, size = this.size_; i < size; i++) {
this.array[i] = null;
}
this.size_ = 0;
}
addAll(items: ImmutableBag<E>): void {
let i: number;
for (i = 0; items.size() > i; i++) {
this.add(items.get(i));
}
}
}
}

View File

@@ -0,0 +1,119 @@
module es {
interface Map<K, V> {
clear(): void;
containsKey(key): boolean;
containsValue(value): boolean;
get(key): V;
isEmpty(): boolean;
put(key, value): void;
remove(key): V;
size(): number;
values(): V[];
}
function decode(key): string {
switch (typeof key) {
case "boolean":
return "" + key;
case "number":
return "" + key;
case "string":
return "" + key;
case "function":
return getClassName(key);
default:
key.uuid = key.uuid ? key.uuid : UUID.randomUUID();
return key.uuid;
}
}
export class HashMap<K, V> implements Map<K, V> {
private map_;
private keys_;
constructor() {
this.clear();
}
clear(): void {
this.map_ = {};
this.keys_ = {};
}
values(): V[] {
const result = [];
const map = this.map_;
for (const key in map) {
result.push(map[key]);
}
return result;
}
contains(value): boolean {
const map = this.map_;
for (const key in map) {
if (value === map[key]) {
return true;
}
}
return false;
}
containsKey(key): boolean {
return decode(key) in this.map_;
}
containsValue(value): boolean {
const map = this.map_;
for (const key in map) {
if (value === map[key]) {
return true;
}
}
return false;
}
get(key: K): V {
return this.map_[decode(key)];
}
isEmpty(): boolean {
return Object.keys(this.map_).length === 0;
}
keys(): K[] {
const keys = this.map_;
const result = [];
for (const key in keys) {
result.push(keys[key]);
}
return result;
}
/**
* if key is a string, use as is, else use key.id_ or key.name
*/
put(key, value): void {
const k = decode(key);
this.map_[k] = value;
this.keys_[k] = key;
}
remove(key): V {
const map = this.map_;
const k = decode(key);
const value = map[k];
delete map[k];
delete this.keys_[k];
return value;
}
size(): number {
return Object.keys(this.map_).length;
}
}
}

View File

@@ -0,0 +1,11 @@
module es {
export interface ImmutableBag<E> {
get(index: number): E;
size(): number;
isEmpty(): boolean;
contains(e: E): boolean;
}
}

293
source/src/Utils/UUID.ts Normal file
View File

@@ -0,0 +1,293 @@
module es {
const hex = [
// hex identity values 0-255
"00",
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"0a",
"0b",
"0c",
"0d",
"0e",
"0f",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"1a",
"1b",
"1c",
"1d",
"1e",
"1f",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"2a",
"2b",
"2c",
"2d",
"2e",
"2f",
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
"38",
"39",
"3a",
"3b",
"3c",
"3d",
"3e",
"3f",
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
"48",
"49",
"4a",
"4b",
"4c",
"4d",
"4e",
"4f",
"50",
"51",
"52",
"53",
"54",
"55",
"56",
"57",
"58",
"59",
"5a",
"5b",
"5c",
"5d",
"5e",
"5f",
"60",
"61",
"62",
"63",
"64",
"65",
"66",
"67",
"68",
"69",
"6a",
"6b",
"6c",
"6d",
"6e",
"6f",
"70",
"71",
"72",
"73",
"74",
"75",
"76",
"77",
"78",
"79",
"7a",
"7b",
"7c",
"7d",
"7e",
"7f",
"80",
"81",
"82",
"83",
"84",
"85",
"86",
"87",
"88",
"89",
"8a",
"8b",
"8c",
"8d",
"8e",
"8f",
"90",
"91",
"92",
"93",
"94",
"95",
"96",
"97",
"98",
"99",
"9a",
"9b",
"9c",
"9d",
"9e",
"9f",
"a0",
"a1",
"a2",
"a3",
"a4",
"a5",
"a6",
"a7",
"a8",
"a9",
"aa",
"ab",
"ac",
"ad",
"ae",
"af",
"b0",
"b1",
"b2",
"b3",
"b4",
"b5",
"b6",
"b7",
"b8",
"b9",
"ba",
"bb",
"bc",
"bd",
"be",
"bf",
"c0",
"c1",
"c2",
"c3",
"c4",
"c5",
"c6",
"c7",
"c8",
"c9",
"ca",
"cb",
"cc",
"cd",
"ce",
"cf",
"d0",
"d1",
"d2",
"d3",
"d4",
"d5",
"d6",
"d7",
"d8",
"d9",
"da",
"db",
"dc",
"dd",
"de",
"df",
"e0",
"e1",
"e2",
"e3",
"e4",
"e5",
"e6",
"e7",
"e8",
"e9",
"ea",
"eb",
"ec",
"ed",
"ee",
"ef",
"f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"fa",
"fb",
"fc",
"fd",
"fe",
"ff",
];
export class UUID {
static randomUUID(): string {
const d0 = (Math.random() * 0xffffffff) | 0;
const d1 = (Math.random() * 0xffffffff) | 0;
const d2 = (Math.random() * 0xffffffff) | 0;
const d3 = (Math.random() * 0xffffffff) | 0;
return (
hex[d0 & 0xff] +
hex[(d0 >> 8) & 0xff] +
hex[(d0 >> 16) & 0xff] +
hex[(d0 >> 24) & 0xff] +
"-" +
hex[d1 & 0xff] +
hex[(d1 >> 8) & 0xff] +
"-" +
hex[((d1 >> 16) & 0x0f) | 0x40] +
hex[(d1 >> 24) & 0xff] +
"-" +
hex[(d2 & 0x3f) | 0x80] +
hex[(d2 >> 8) & 0xff] +
"-" +
hex[(d2 >> 16) & 0xff] +
hex[(d2 >> 24) & 0xff] +
hex[d3 & 0xff] +
hex[(d3 >> 8) & 0xff] +
hex[(d3 >> 16) & 0xff] +
hex[(d3 >> 24) & 0xff]
);
}
}
}

View File

@@ -0,0 +1,7 @@
module es {
export interface Class extends Function {}
export function getClassName(klass): string {
return klass.className || klass.name;
}
}