@woosh/meep-engine 2.48.16 → 2.48.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/editor/tools/TransformTool.js +4 -2
- package/package.json +1 -1
- package/src/core/binary/dec2hex.spec.js +13 -0
- package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.d.ts +18 -0
- package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +18 -0
- package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.spec.js +56 -0
- package/src/core/cache/Cache.d.ts +5 -0
- package/src/core/cache/Cache.js +8 -1
- package/src/core/cache/Cache.spec.js +47 -3
- package/src/core/codegen/LineBuilder.js +117 -106
- package/src/core/collection/HashMap.spec.js +32 -0
- package/src/core/collection/list/List.js +6 -4
- package/src/core/geom/Quaternion.d.ts +3 -1
- package/src/core/geom/Quaternion.js +8 -4
- package/src/core/geom/Vector3.js +9 -31
- package/src/core/math/fract.spec.js +11 -0
- package/src/core/math/isPowerOfTwo.spec.js +9 -0
- package/src/core/math/isPowerOrTwo.js +5 -0
- package/src/core/math/newton_solver_1d.js +1 -1
- package/src/core/math/newton_solver_1d.spec.js +9 -0
- package/src/core/math/pingpong.spec.js +11 -0
- package/src/core/math/random/randomBytes.js +16 -0
- package/src/core/math/random/randomFloatBetween.spec.js +8 -0
- package/src/core/math/random/randomFromArray.js +3 -3
- package/src/core/math/random/randomIntegerBetween.js +5 -0
- package/src/core/math/random/randomIntegerBetween.spec.js +7 -0
- package/src/core/math/statistics/halton_sequence.spec.js +17 -0
- package/src/engine/asset/AssetManager.d.ts +11 -1
- package/src/engine/asset/AssetManager.spec.js +2 -2
- package/src/engine/control/ControlContext.js +2 -1
- package/src/engine/ecs/EntityBuilder.d.ts +6 -0
- package/src/engine/ecs/EntityBuilder.js +2 -22
- package/src/engine/ecs/EntityBuilder.spec.js +71 -1
- package/src/engine/ecs/EntityBuilderFlags.js +20 -0
- package/src/engine/ecs/EntityComponentDataset.js +3 -6
- package/src/engine/ecs/dynamic_actions/DynamicActorSystem.js +2 -1
- package/src/engine/ecs/gui/menu/radial/RadialContextMenu.js +2 -1
- package/src/engine/ecs/guid/GUID.js +48 -26
- package/src/engine/ecs/guid/GUID.spec.js +56 -10
- package/src/engine/ecs/speaker/VoiceSystem.js +2 -1
- package/src/engine/ecs/transform/Transform.d.ts +11 -1
- package/src/engine/ecs/transform/Transform.js +6 -3
- package/src/engine/ecs/transform/Transform.spec.js +67 -1
- package/src/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +2 -1
- package/src/engine/physics/fluid/Fluid.js +3 -0
- package/src/engine/graphics/ecs/mesh/setThreeObjectRotation.js +0 -11
package/src/core/geom/Vector3.js
CHANGED
|
@@ -38,7 +38,7 @@ class Vector3 {
|
|
|
38
38
|
* @param {number[]} array
|
|
39
39
|
* @param {number} offset
|
|
40
40
|
*/
|
|
41
|
-
readFromArray(array, offset=0) {
|
|
41
|
+
readFromArray(array, offset = 0) {
|
|
42
42
|
this.set(
|
|
43
43
|
array[offset],
|
|
44
44
|
array[offset + 1],
|
|
@@ -51,16 +51,16 @@ class Vector3 {
|
|
|
51
51
|
* @param {number[]} array
|
|
52
52
|
* @param {number} offset
|
|
53
53
|
*/
|
|
54
|
-
writeToArray(array, offset=0) {
|
|
54
|
+
writeToArray(array, offset = 0) {
|
|
55
55
|
array[offset] = this.x;
|
|
56
56
|
array[offset + 1] = this.y;
|
|
57
57
|
array[offset + 2] = this.z;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
asArray(){
|
|
60
|
+
asArray() {
|
|
61
61
|
const r = [];
|
|
62
62
|
|
|
63
|
-
this.writeToArray(r,0);
|
|
63
|
+
this.writeToArray(r, 0);
|
|
64
64
|
|
|
65
65
|
return r;
|
|
66
66
|
}
|
|
@@ -171,12 +171,12 @@ class Vector3 {
|
|
|
171
171
|
* @param {Vector3} a
|
|
172
172
|
* @param {Vector3} b
|
|
173
173
|
*/
|
|
174
|
-
addVectors(a,b){
|
|
174
|
+
addVectors(a, b) {
|
|
175
175
|
const x = a.x + b.x;
|
|
176
176
|
const y = a.y + b.y;
|
|
177
177
|
const z = a.z + b.z;
|
|
178
178
|
|
|
179
|
-
this.set(x,y,z);
|
|
179
|
+
this.set(x, y, z);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
/**
|
|
@@ -378,7 +378,7 @@ class Vector3 {
|
|
|
378
378
|
* @returns {number}
|
|
379
379
|
*/
|
|
380
380
|
length() {
|
|
381
|
-
return
|
|
381
|
+
return v3_length(this.x, this.y, this.z);
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
/**
|
|
@@ -532,7 +532,7 @@ class Vector3 {
|
|
|
532
532
|
* @param {number} fraction
|
|
533
533
|
*/
|
|
534
534
|
lerpVectors(a, b, fraction) {
|
|
535
|
-
|
|
535
|
+
v3_lerp(this, a.x, a.y, a.z, b.x, b.y, b.z, fraction);
|
|
536
536
|
}
|
|
537
537
|
|
|
538
538
|
/**
|
|
@@ -806,7 +806,7 @@ class Vector3 {
|
|
|
806
806
|
}
|
|
807
807
|
|
|
808
808
|
toString() {
|
|
809
|
-
return `
|
|
809
|
+
return `{ x:${this.x}, y:${this.y}, z:${this.z} }`;
|
|
810
810
|
}
|
|
811
811
|
|
|
812
812
|
/**
|
|
@@ -1095,7 +1095,6 @@ Vector3.back = Object.freeze(new Vector3(0, 0, -1));
|
|
|
1095
1095
|
|
|
1096
1096
|
Vector3.typeName = "Vector3";
|
|
1097
1097
|
|
|
1098
|
-
|
|
1099
1098
|
/**
|
|
1100
1099
|
*
|
|
1101
1100
|
* @param {number} x0
|
|
@@ -1109,25 +1108,4 @@ Vector3.typeName = "Vector3";
|
|
|
1109
1108
|
Vector3._dot = v3_dot;
|
|
1110
1109
|
|
|
1111
1110
|
|
|
1112
|
-
/**
|
|
1113
|
-
*
|
|
1114
|
-
* @param {{x:number, y:number, z:number}} v
|
|
1115
|
-
* @return {number}
|
|
1116
|
-
*/
|
|
1117
|
-
function v3Length(v) {
|
|
1118
|
-
return v3_length(v.x, v.y, v.z);
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
/**
|
|
1123
|
-
*
|
|
1124
|
-
* @param {Vector3} result
|
|
1125
|
-
* @param {Vector3} a
|
|
1126
|
-
* @param {Vector3} b
|
|
1127
|
-
* @param {number} fraction
|
|
1128
|
-
*/
|
|
1129
|
-
function v3Lerp(result, a, b, fraction) {
|
|
1130
|
-
v3_lerp(result, a.x, a.y, a.z, b.x, b.y, b.z, fraction);
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
1111
|
export default Vector3;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { fract } from "./fract.js";
|
|
2
|
+
|
|
3
|
+
test("correctness", () => {
|
|
4
|
+
|
|
5
|
+
expect(fract(0)).toBeCloseTo(0);
|
|
6
|
+
expect(fract(0.1)).toBeCloseTo(0.1);
|
|
7
|
+
expect(fract(-0.1)).toBeCloseTo(-0.1);
|
|
8
|
+
expect(fract(1.1)).toBeCloseTo(0.1);
|
|
9
|
+
expect(fract(-1.1)).toBeCloseTo(-0.1);
|
|
10
|
+
|
|
11
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { isPowerOfTwo } from "./isPowerOrTwo.js";
|
|
2
|
+
|
|
3
|
+
test("correctness", () => {
|
|
4
|
+
expect(isPowerOfTwo(1)).toBe(true);
|
|
5
|
+
expect(isPowerOfTwo(2)).toBe(true);
|
|
6
|
+
expect(isPowerOfTwo(3)).toBe(false);
|
|
7
|
+
expect(isPowerOfTwo(4)).toBe(true);
|
|
8
|
+
expect(isPowerOfTwo(5)).toBe(false);
|
|
9
|
+
});
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import { assert } from "../assert.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Is the number a power of two?
|
|
3
5
|
* e.g. 2,4,8,16 etc.
|
|
6
|
+
* NOTE: only valid for non-negative integers
|
|
4
7
|
* @param {number} value
|
|
5
8
|
* @returns {boolean}
|
|
6
9
|
*/
|
|
7
10
|
export function isPowerOfTwo(value) {
|
|
11
|
+
assert.isNonNegativeInteger(value, 'value');
|
|
12
|
+
|
|
8
13
|
|
|
9
14
|
return (value & (value - 1)) === 0 && value !== 0;
|
|
10
15
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pingpong } from "./pingpong.js";
|
|
2
|
+
|
|
3
|
+
test("correctness", () => {
|
|
4
|
+
|
|
5
|
+
expect(pingpong(0, 1)).toBe(0);
|
|
6
|
+
expect(pingpong(0.1, 1)).toBeCloseTo(0.1);
|
|
7
|
+
expect(pingpong(1, 1)).toBe(1);
|
|
8
|
+
expect(pingpong(1.1, 1)).toBeCloseTo(0.9);
|
|
9
|
+
expect(pingpong(2.1, 1)).toBeCloseTo(0.1);
|
|
10
|
+
|
|
11
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { randomUint8 } from "./randomUint8.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {Uint8Array} result
|
|
6
|
+
* @param {number} result_offset
|
|
7
|
+
* @param {function():number} random
|
|
8
|
+
* @param {number} count
|
|
9
|
+
*/
|
|
10
|
+
export function randomBytes(result, result_offset, random, count) {
|
|
11
|
+
for (let i = 0; i < count; i++) {
|
|
12
|
+
|
|
13
|
+
result[result_offset + i] = randomUint8(random);
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { returnOne, returnZero } from "../../function/Functions.js";
|
|
2
|
+
import { randomFloatBetween } from "./randomFloatBetween.js";
|
|
3
|
+
|
|
4
|
+
test("limits", () => {
|
|
5
|
+
|
|
6
|
+
expect(randomFloatBetween(returnZero, -3.11, 7.23)).toEqual(-3.11);
|
|
7
|
+
expect(randomFloatBetween(returnOne, -3.11, 7.23)).toEqual(7.23);
|
|
8
|
+
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../assert.js";
|
|
2
|
-
import {
|
|
2
|
+
import { randomIntegerBetween } from "./randomIntegerBetween.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @template T
|
|
@@ -13,7 +13,7 @@ export function randomFromArray(random, array) {
|
|
|
13
13
|
|
|
14
14
|
const length = array.length;
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const index = randomIntegerBetween(random, 0, length - 1);
|
|
17
17
|
|
|
18
|
-
return array[
|
|
18
|
+
return array[index];
|
|
19
19
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Inclusive random between two boundaries, result is integer
|
|
3
5
|
* @param {function} random
|
|
@@ -6,6 +8,9 @@
|
|
|
6
8
|
* @returns {number}
|
|
7
9
|
*/
|
|
8
10
|
export function randomIntegerBetween(random, min, max) {
|
|
11
|
+
assert.isInteger(min, 'min');
|
|
12
|
+
assert.isInteger(max, 'max');
|
|
13
|
+
|
|
9
14
|
const span = max - min;
|
|
10
15
|
|
|
11
16
|
const roll = random();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { randomIntegerBetween } from "./randomIntegerBetween.js";
|
|
2
|
+
import { returnOne, returnZero } from "../../function/Functions.js";
|
|
3
|
+
|
|
4
|
+
test("limits", () => {
|
|
5
|
+
expect(randomIntegerBetween(returnZero, -3, 7)).toEqual(-3);
|
|
6
|
+
expect(randomIntegerBetween(returnOne, -3, 7)).toEqual(7);
|
|
7
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { halton_sequence } from "./halton_sequence.js";
|
|
2
|
+
|
|
3
|
+
test("unique values in base 10", () => {
|
|
4
|
+
|
|
5
|
+
const values = [];
|
|
6
|
+
|
|
7
|
+
for (let i = 0; i < 10; i++) {
|
|
8
|
+
values.push(halton_sequence(10, i));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
values.sort();
|
|
12
|
+
|
|
13
|
+
for (let i = 1; i < 10; i++) {
|
|
14
|
+
expect(values[i]).not.toEqual(values[i - 1]);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
});
|
|
@@ -13,6 +13,14 @@ interface AssetManagerOptions<CTX> {
|
|
|
13
13
|
executor?: ConcurrentExecutor
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
interface GetOptions<T> {
|
|
17
|
+
type: string
|
|
18
|
+
path: string
|
|
19
|
+
callback: (asset: Asset<T>) => any
|
|
20
|
+
failure: (reason: any) => any
|
|
21
|
+
progress: (current: number, total: number) => any
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
export declare class AssetManager<CTX> {
|
|
17
25
|
constructor(options?: AssetManagerOptions<CTX>)
|
|
18
26
|
|
|
@@ -24,13 +32,15 @@ export declare class AssetManager<CTX> {
|
|
|
24
32
|
|
|
25
33
|
shutdown(immediate?: boolean): Promise<void>
|
|
26
34
|
|
|
35
|
+
get<T>(options: GetOptions<T>): void
|
|
36
|
+
|
|
27
37
|
promise<T>(path: string, type: string, options?: PromiseOptions): Promise<Asset<T>>
|
|
28
38
|
|
|
29
39
|
remove(path: string, type: string): boolean
|
|
30
40
|
|
|
31
41
|
clear(): void
|
|
32
42
|
|
|
33
|
-
registerLoader<T>(type: string, loader: AssetLoader<T, CTX>): Promise<AssetLoader<T,CTX>>
|
|
43
|
+
registerLoader<T>(type: string, loader: AssetLoader<T, CTX>): Promise<AssetLoader<T, CTX>>
|
|
34
44
|
|
|
35
45
|
unregisterLoader(type: string): Promise<void>
|
|
36
46
|
|
|
@@ -16,7 +16,7 @@ function dummyEngine() {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
class DummyLoader extends AssetLoader {
|
|
19
|
-
load(scope,path, success, failure, progress) {
|
|
19
|
+
load(scope, path, success, failure, progress) {
|
|
20
20
|
success(new Asset(() => 1));
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -29,7 +29,7 @@ test('successful get', async () => {
|
|
|
29
29
|
am.startup();
|
|
30
30
|
|
|
31
31
|
return new Promise(function (resolve, reject) {
|
|
32
|
-
am.get('bla', 'a', resolve, reject);
|
|
32
|
+
am.get({ path: 'bla', type: 'a', callback: resolve, failure: reject });
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
35
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import EntityBuilder
|
|
1
|
+
import EntityBuilder from "../ecs/EntityBuilder.js";
|
|
2
2
|
import { ControlContextState } from "./ControlContextState.js";
|
|
3
3
|
import { IllegalStateException } from "../../core/fsm/exceptions/IllegalStateException.js";
|
|
4
4
|
import { SerializationMetadata } from "../ecs/components/SerializationMetadata.js";
|
|
5
|
+
import { EntityBuilderFlags } from "../ecs/EntityBuilderFlags.js";
|
|
5
6
|
|
|
6
7
|
export class ControlContext {
|
|
7
8
|
constructor() {
|
|
@@ -11,6 +11,8 @@ export default class EntityBuilder {
|
|
|
11
11
|
|
|
12
12
|
removeComponent<T>(componentType: Type<T>): T | null
|
|
13
13
|
|
|
14
|
+
removeAllComponents(): void
|
|
15
|
+
|
|
14
16
|
getComponent<T>(componentType: Type<T>): T | null
|
|
15
17
|
|
|
16
18
|
getComponentSafe<T>(componentType: Type<T>): T
|
|
@@ -30,4 +32,8 @@ export default class EntityBuilder {
|
|
|
30
32
|
removeEventListener(eventName: string, listener: (data?: any) => void, context?: any): EntityBuilder
|
|
31
33
|
|
|
32
34
|
static readFromDataset(entity: number, dataset: EntityComponentDataset): EntityBuilder
|
|
35
|
+
|
|
36
|
+
getFlag(flag: number): boolean
|
|
37
|
+
|
|
38
|
+
setFlag(flag: number, value: number): void
|
|
33
39
|
}
|
|
@@ -2,27 +2,7 @@ import Signal from "../../core/events/signal/Signal.js";
|
|
|
2
2
|
import { assert } from "../../core/assert.js";
|
|
3
3
|
import { EventType } from "./EntityManager.js";
|
|
4
4
|
import { isDefined } from "../../core/process/matcher/Matchers.js";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
* @enum
|
|
9
|
-
*/
|
|
10
|
-
export const EntityBuilderFlags = {
|
|
11
|
-
/**
|
|
12
|
-
* Whether the entity is built, set internally
|
|
13
|
-
*/
|
|
14
|
-
Built: 1,
|
|
15
|
-
/**
|
|
16
|
-
* If component type is not registered on the {@link EntityComponentDataset} when calling {@link #build} - will register the component first
|
|
17
|
-
*/
|
|
18
|
-
RegisterComponents: 2,
|
|
19
|
-
/**
|
|
20
|
-
* Entity builder will watch destruction of the entity (subscribe to event), this will make the EntityBuilder automatically
|
|
21
|
-
* recognize when the corresponding entity is destroyed outside the EntityBuilder API
|
|
22
|
-
* NOTE: useful to turn off to save a bit of memory, as those event listeners take up a bit of space. Feel free to turn this flag off when you don't care to keep the reference to the EntityBuilder
|
|
23
|
-
*/
|
|
24
|
-
WatchDestruction: 4
|
|
25
|
-
};
|
|
5
|
+
import { EntityBuilderFlags } from "./EntityBuilderFlags.js";
|
|
26
6
|
|
|
27
7
|
/**
|
|
28
8
|
* Set of default flags
|
|
@@ -152,7 +132,7 @@ class EntityBuilder {
|
|
|
152
132
|
*/
|
|
153
133
|
add(componentInstance) {
|
|
154
134
|
if (componentInstance === undefined) {
|
|
155
|
-
throw new Error(
|
|
135
|
+
throw new Error(`Can not add ${componentInstance} to EntityBuilder`);
|
|
156
136
|
}
|
|
157
137
|
|
|
158
138
|
assert.notOk(this.hasComponent(Object.getPrototypeOf(componentInstance).constructor), 'Component of this type already exists');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import EntityBuilder
|
|
1
|
+
import EntityBuilder from "./EntityBuilder.js";
|
|
2
2
|
import { EntityComponentDataset } from "./EntityComponentDataset.js";
|
|
3
|
+
import { EntityBuilderFlags } from "./EntityBuilderFlags.js";
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class DummyComponent {
|
|
@@ -62,3 +63,72 @@ test("'Built' flag is reset when entity is removed without invoking 'destroy' me
|
|
|
62
63
|
|
|
63
64
|
expect(b.getFlag(EntityBuilderFlags.Built)).toBe(false);
|
|
64
65
|
});
|
|
66
|
+
|
|
67
|
+
test("removeAllComponents from empty", () => {
|
|
68
|
+
const entity = new EntityBuilder();
|
|
69
|
+
|
|
70
|
+
expect(() => entity.removeAllComponents()).not.toThrow()
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("removeAllComponents with 1 entity", () => {
|
|
74
|
+
const entity = new EntityBuilder();
|
|
75
|
+
|
|
76
|
+
entity.add(new DummyComponent());
|
|
77
|
+
|
|
78
|
+
expect(entity.hasComponent(DummyComponent)).toBe(true);
|
|
79
|
+
|
|
80
|
+
entity.removeAllComponents();
|
|
81
|
+
|
|
82
|
+
expect(entity.hasComponent(DummyComponent)).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("removeComponent when component is not preset", () => {
|
|
86
|
+
const entity = new EntityBuilder();
|
|
87
|
+
|
|
88
|
+
expect(entity.removeComponent(DummyComponent)).toBe(null);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("removeComponent when component is preset", () => {
|
|
92
|
+
const entity = new EntityBuilder();
|
|
93
|
+
|
|
94
|
+
const component = new DummyComponent();
|
|
95
|
+
|
|
96
|
+
entity.add(component)
|
|
97
|
+
|
|
98
|
+
expect(entity.removeComponent(DummyComponent)).toBe(component);
|
|
99
|
+
|
|
100
|
+
expect(entity.hasComponent(DummyComponent)).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("getComponentSafe throws when component is missing", () => {
|
|
104
|
+
|
|
105
|
+
const entity = new EntityBuilder();
|
|
106
|
+
|
|
107
|
+
expect(() => entity.getComponentSafe(DummyComponent)).toThrow();
|
|
108
|
+
|
|
109
|
+
});
|
|
110
|
+
test("getComponentSafe throws when component is present", () => {
|
|
111
|
+
|
|
112
|
+
const entity = new EntityBuilder();
|
|
113
|
+
|
|
114
|
+
const component = new DummyComponent();
|
|
115
|
+
entity.add(component);
|
|
116
|
+
|
|
117
|
+
expect(() => entity.getComponentSafe(DummyComponent)).not.toThrow();
|
|
118
|
+
|
|
119
|
+
expect(entity.getComponentSafe(DummyComponent)).toBe(component);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("adding component to live entity results in component being added to the dataset", () => {
|
|
123
|
+
|
|
124
|
+
const entity = new EntityBuilder();
|
|
125
|
+
|
|
126
|
+
const ecd = sampleDataset();
|
|
127
|
+
|
|
128
|
+
entity.build(ecd)
|
|
129
|
+
|
|
130
|
+
const component = new DummyComponent();
|
|
131
|
+
entity.add(component);
|
|
132
|
+
|
|
133
|
+
expect(ecd.getComponent(entity.entity, DummyComponent)).toBe(component);
|
|
134
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @enum
|
|
4
|
+
*/
|
|
5
|
+
export const EntityBuilderFlags = {
|
|
6
|
+
/**
|
|
7
|
+
* Whether the entity is built, set internally
|
|
8
|
+
*/
|
|
9
|
+
Built: 1,
|
|
10
|
+
/**
|
|
11
|
+
* If component type is not registered on the {@link EntityComponentDataset} when calling {@link #build} - will register the component first
|
|
12
|
+
*/
|
|
13
|
+
RegisterComponents: 2,
|
|
14
|
+
/**
|
|
15
|
+
* Entity builder will watch destruction of the entity (subscribe to event), this will make the EntityBuilder automatically
|
|
16
|
+
* recognize when the corresponding entity is destroyed outside the EntityBuilder API
|
|
17
|
+
* NOTE: useful to turn off to save a bit of memory, as those event listeners take up a bit of space. Feel free to turn this flag off when you don't care to keep the reference to the EntityBuilder
|
|
18
|
+
*/
|
|
19
|
+
WatchDestruction: 4
|
|
20
|
+
};
|
|
@@ -1071,7 +1071,7 @@ export class EntityComponentDataset {
|
|
|
1071
1071
|
* @param {function} callback
|
|
1072
1072
|
* @param {*} [thisArg]
|
|
1073
1073
|
*/
|
|
1074
|
-
getComponentAsync
|
|
1074
|
+
getComponentAsync(entityId, componentClass, callback, thisArg) {
|
|
1075
1075
|
const component = this.getComponent(entityId, componentClass);
|
|
1076
1076
|
|
|
1077
1077
|
const handler = (options) => {
|
|
@@ -1274,11 +1274,8 @@ export class EntityComponentDataset {
|
|
|
1274
1274
|
*/
|
|
1275
1275
|
traverseComponentsByIndex(componentTypeIndex, visitor, thisArg) {
|
|
1276
1276
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
assert.isFunction(visitor, "visitor");
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1277
|
+
assert.isNumber(componentTypeIndex, "componentTypeIndex");
|
|
1278
|
+
assert.isFunction(visitor, "visitor");
|
|
1282
1279
|
|
|
1283
1280
|
this.__traverseComponentsByIndex_via_property(componentTypeIndex, visitor, thisArg);
|
|
1284
1281
|
}
|
|
@@ -5,7 +5,7 @@ import { DataScope } from "../../../../../model/game/unit/actions/data/DataScope
|
|
|
5
5
|
import { Blackboard } from "../../intelligence/blackboard/Blackboard.js";
|
|
6
6
|
import { compareNumbersDescending, returnTrue } from "../../../core/function/Functions.js";
|
|
7
7
|
import { EntityProxyScope } from "../binding/EntityProxyScope.js";
|
|
8
|
-
import EntityBuilder
|
|
8
|
+
import EntityBuilder from "../EntityBuilder.js";
|
|
9
9
|
import { BehaviorComponent } from "../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
10
10
|
import { SequenceBehavior } from "../../intelligence/behavior/composite/SequenceBehavior.js";
|
|
11
11
|
import { DieBehavior } from "../../intelligence/behavior/ecs/DieBehavior.js";
|
|
@@ -22,6 +22,7 @@ import { randomFloatBetween } from "../../../core/math/random/randomFloatBetween
|
|
|
22
22
|
import { randomMultipleFromArray } from "../../../core/collection/array/randomMultipleFromArray.js";
|
|
23
23
|
import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js";
|
|
24
24
|
import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
|
|
25
|
+
import { EntityBuilderFlags } from "../EntityBuilderFlags.js";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* In seconds
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { SerializationMetadata } from "../../../components/SerializationMetadata.js";
|
|
5
5
|
|
|
6
|
-
import EntityBuilder
|
|
6
|
+
import EntityBuilder from "../../../EntityBuilder.js";
|
|
7
7
|
import GUIElement from "../../GUIElement.js";
|
|
8
8
|
import { MouseEvents } from "../../../../input/devices/events/MouseEvents.js";
|
|
9
9
|
import { TouchEvents } from "../../../../input/devices/events/TouchEvents.js";
|
|
@@ -12,6 +12,7 @@ import RadialMenuView from "../../../../../view/elements/radial/RadialMenu.js";
|
|
|
12
12
|
import { animateAppearance } from "./AnimateAppearance.js";
|
|
13
13
|
import { animateDisappearance } from "./AnimateDisappearance.js";
|
|
14
14
|
import { RadialMenuSettings } from "./RadialMenuSettings.js";
|
|
15
|
+
import { EntityBuilderFlags } from "../../../EntityBuilderFlags.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
*
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { seededRandom } from "../../../core/math/random/seededRandom.js";
|
|
2
2
|
import { randomUint8 } from "../../../core/math/random/randomUint8.js";
|
|
3
|
-
import { is_typed_array_equals } from "../../../core/collection/array/typed/is_typed_array_equals.js";
|
|
4
3
|
import { dec2hex } from "../../../core/binary/dec2hex.js";
|
|
5
4
|
import { array_copy } from "../../../core/collection/array/copyArray.js";
|
|
5
|
+
import { randomBytes } from "../../../core/math/random/randomBytes.js";
|
|
6
|
+
import { assert } from "../../../core/assert.js";
|
|
6
7
|
|
|
7
8
|
// Previous uuid creation time
|
|
8
9
|
let _lastMSecs = 0;
|
|
@@ -10,23 +11,8 @@ let _lastNSecs = 0;
|
|
|
10
11
|
|
|
11
12
|
const random = seededRandom(Date.now());
|
|
12
13
|
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* @param {Uint8Array} result
|
|
16
|
-
* @param {number} result_offset
|
|
17
|
-
* @param {function():number} random
|
|
18
|
-
* @param {number} count
|
|
19
|
-
*/
|
|
20
|
-
function randomBytes(result, result_offset, random, count) {
|
|
21
|
-
for (let i = 0; i < count; i++) {
|
|
22
|
-
|
|
23
|
-
result[result_offset + i] = randomUint8(random);
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
14
|
// node and clockseq need to be initialized to random values.
|
|
29
|
-
|
|
15
|
+
const _nodeId = new Uint8Array(6);
|
|
30
16
|
|
|
31
17
|
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
|
|
32
18
|
randomBytes(_nodeId, 0, random, 6);
|
|
@@ -41,15 +27,14 @@ let _clockseq = ((randomUint8(random) << 8) | randomUint8(random)) & 0x3fff;
|
|
|
41
27
|
export class GUID {
|
|
42
28
|
#data = new Uint8Array(16);
|
|
43
29
|
|
|
44
|
-
constructor() {
|
|
45
|
-
this.v1();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
30
|
/**
|
|
49
31
|
*
|
|
50
32
|
* @param {number[]|Uint8Array|ArrayLike<number>} bytes
|
|
51
33
|
*/
|
|
52
34
|
set data(bytes) {
|
|
35
|
+
assert.isArrayLike(bytes, 'bytes');
|
|
36
|
+
assert.greaterThanOrEqual(bytes.length, 16, 'bytes.length >= 16');
|
|
37
|
+
|
|
53
38
|
array_copy(bytes, 0, this.#data, 0, 16);
|
|
54
39
|
}
|
|
55
40
|
|
|
@@ -136,12 +121,27 @@ export class GUID {
|
|
|
136
121
|
}
|
|
137
122
|
}
|
|
138
123
|
|
|
124
|
+
/**
|
|
125
|
+
*
|
|
126
|
+
* @return {GUID}
|
|
127
|
+
*/
|
|
128
|
+
static v1() {
|
|
129
|
+
const uuid = new GUID();
|
|
130
|
+
|
|
131
|
+
uuid.v1();
|
|
132
|
+
|
|
133
|
+
return uuid;
|
|
134
|
+
}
|
|
135
|
+
|
|
139
136
|
/***
|
|
140
137
|
* String in UUID format
|
|
141
138
|
* @see https://github.com/uuidjs/uuid/blob/8f028c4ea42ce41a9a9dc5fa634abe525b2e2066/src/parse.js#L3
|
|
142
139
|
* @param {string} string
|
|
143
140
|
*/
|
|
144
141
|
parse(string) {
|
|
142
|
+
assert.isString(string, 'string');
|
|
143
|
+
assert.greaterThanOrEqual(string.length, 36, 'string.length');
|
|
144
|
+
|
|
145
145
|
let v;
|
|
146
146
|
const arr = this.#data;
|
|
147
147
|
|
|
@@ -173,6 +173,19 @@ export class GUID {
|
|
|
173
173
|
arr[15] = v & 0xff;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
*
|
|
178
|
+
* @param {string} string
|
|
179
|
+
* @return {GUID}
|
|
180
|
+
*/
|
|
181
|
+
static parse(string) {
|
|
182
|
+
const r = new GUID();
|
|
183
|
+
|
|
184
|
+
r.parse(string);
|
|
185
|
+
|
|
186
|
+
return r;
|
|
187
|
+
}
|
|
188
|
+
|
|
176
189
|
/**
|
|
177
190
|
* @see https://github.com/uuidjs/uuid/blob/8f028c4ea42ce41a9a9dc5fa634abe525b2e2066/src/stringify.js#L16
|
|
178
191
|
* @returns {string}
|
|
@@ -218,7 +231,16 @@ export class GUID {
|
|
|
218
231
|
* @returns {boolean}
|
|
219
232
|
*/
|
|
220
233
|
equals(other) {
|
|
221
|
-
|
|
234
|
+
const this_data = this.#data;
|
|
235
|
+
const other_data = other.#data;
|
|
236
|
+
|
|
237
|
+
for (let i = 0; i < 16; i++) {
|
|
238
|
+
if (this_data[i] !== other_data[i]) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return true;
|
|
222
244
|
}
|
|
223
245
|
|
|
224
246
|
/**
|
|
@@ -228,10 +250,10 @@ export class GUID {
|
|
|
228
250
|
const data = this.#data;
|
|
229
251
|
|
|
230
252
|
// use some non-metadata bytes as a hash
|
|
231
|
-
return data[
|
|
232
|
-
| data[
|
|
233
|
-
| data[
|
|
234
|
-
| data[
|
|
253
|
+
return data[3] // low byte of "time_low", very likely to differ between two UUIDs
|
|
254
|
+
| data[5] << 8 // low byte of "time_mid"
|
|
255
|
+
| data[9] << 16 // "clock_seq_low"
|
|
256
|
+
| data[15] << 24 // low byte of "node"
|
|
235
257
|
;
|
|
236
258
|
}
|
|
237
259
|
|