@woosh/meep-engine 2.42.0 → 2.42.2
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/core/assert.js +2 -2
- package/core/collection/RingBuffer.js +15 -0
- package/core/collection/array/array_swap.js +3 -3
- package/core/collection/map/AsyncLoadingCache.js +47 -0
- package/core/geom/3d/aabb/aabb3_compute_distance_above_plane_max.js +1 -1
- package/core/math/statistics/computeSampleSize_Cochran.js +3 -3
- package/editor/ecs/component/editors/geom/QuaternionEditor.js +12 -5
- package/engine/Engine.js +6 -1
- package/engine/EngineBootstrapper.js +2 -1
- package/engine/EngineHarness.js +5 -1
- package/engine/asset/AssetManager.js +97 -7
- package/engine/development/performance/AbstractMetric.js +3 -1
- package/engine/development/performance/RingBufferMetric.js +39 -4
- package/engine/ecs/EntityBuilder.js +29 -4
- package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +17 -1
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +18 -30
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +57 -16
- package/engine/graphics/ecs/mesh-v2/allocate_v3.js +37 -0
- package/engine/graphics/geometry/MikkT/AddTriToGroup.js +10 -0
- package/engine/graphics/geometry/MikkT/AssignRecur.js +84 -0
- package/engine/graphics/geometry/MikkT/AvgTSpace.js +38 -0
- package/engine/graphics/geometry/MikkT/Build4RuleGroups.js +96 -0
- package/engine/graphics/geometry/MikkT/BuildNeighborsFast.js +137 -0
- package/engine/graphics/geometry/MikkT/CalcTexArea.js +31 -0
- package/engine/graphics/geometry/MikkT/CompareSubGroups.js +26 -0
- package/engine/graphics/geometry/MikkT/DegenEpilogue.js +220 -0
- package/engine/graphics/geometry/MikkT/DegenPrologue.js +115 -0
- package/engine/graphics/geometry/MikkT/EvalTspace.js +128 -0
- package/engine/graphics/geometry/MikkT/GenerateInitialVerticesIndexList.js +48 -0
- package/engine/graphics/geometry/MikkT/GenerateSharedVerticesIndexList.js +184 -0
- package/engine/graphics/geometry/MikkT/GenerateTSpaces.js +226 -0
- package/engine/graphics/geometry/MikkT/GetEdge.js +45 -0
- package/engine/graphics/geometry/MikkT/GetNormal.js +16 -0
- package/engine/graphics/geometry/MikkT/GetPosition.js +25 -0
- package/engine/graphics/geometry/MikkT/GetTexCoord.js +18 -0
- package/engine/graphics/geometry/MikkT/InitTriInfo.js +180 -0
- package/engine/graphics/geometry/MikkT/Length.js +10 -0
- package/engine/graphics/geometry/MikkT/MakeIndex.js +18 -0
- package/engine/graphics/geometry/MikkT/MikkTSpace.js +165 -2197
- package/engine/graphics/geometry/MikkT/NormalizeSafe.js +21 -0
- package/engine/graphics/geometry/MikkT/NotZero.js +10 -0
- package/engine/graphics/geometry/MikkT/QuickSort.js +54 -0
- package/engine/graphics/geometry/MikkT/QuickSortEdges.js +71 -0
- package/engine/graphics/geometry/MikkT/SSubGroup.js +15 -0
- package/engine/graphics/geometry/MikkT/STSpace.js +36 -0
- package/engine/graphics/geometry/MikkT/constants/GROUP_WITH_ANY.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/INTERNAL_RND_SORT_SEED.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/MARK_DEGENERATE.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/ORIENT_PRESERVING.js +1 -0
- package/engine/graphics/geometry/MikkT/constants/QUAD_ONE_DEGEN_TRI.js +1 -0
- package/engine/graphics/geometry/MikkT/m_getNormal.js +16 -0
- package/engine/graphics/geometry/MikkT/m_getNumFaces.js +8 -0
- package/engine/graphics/geometry/MikkT/m_getNumVerticesOfFace.js +11 -0
- package/engine/graphics/geometry/MikkT/m_getPosition.js +20 -0
- package/engine/graphics/geometry/MikkT/m_getTexCoord.js +16 -0
- package/engine/graphics/geometry/MikkT/m_setTSpace.js +35 -0
- package/engine/graphics/geometry/MikkT/m_setTSpaceBasic.js +22 -0
- package/engine/graphics/geometry/MikkT/malloc.js +16 -0
- package/engine/graphics/geometry/MikkT/v3_scale_dot_sub_normalize.js +52 -0
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +3 -2
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +5 -5
- package/engine/graphics/render/forward_plus/LightManager.js +16 -6
- package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +7 -1
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +13 -3
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +2 -1
- package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +14 -2
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
- package/engine/intelligence/behavior/util/RotationBehavior.js +69 -0
- package/generation/example/filters/SampleGroundMoistureFilter.js +5 -5
- package/package.json +1 -1
package/core/assert.js
CHANGED
|
@@ -167,8 +167,8 @@ function arrayHasNo(haystack, needle, message = 'Array contains the item') {
|
|
|
167
167
|
|
|
168
168
|
/**
|
|
169
169
|
* @template T
|
|
170
|
-
* @param {T[]|ArrayLike<T>|Float32Array} a
|
|
171
|
-
* @param {T[]|ArrayLike<T>|Float32Array} b
|
|
170
|
+
* @param {T[]|ArrayLike<T>|Float32Array|Int32Array} a
|
|
171
|
+
* @param {T[]|ArrayLike<T>|Float32Array|Int32Array} b
|
|
172
172
|
* @param {string} [message]
|
|
173
173
|
*/
|
|
174
174
|
function arrayEqual(a, b, message = 'Arrays are not equal') {
|
|
@@ -42,6 +42,21 @@ export class RingBuffer {
|
|
|
42
42
|
this.data = new Array(size);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {number} new_size
|
|
48
|
+
*/
|
|
49
|
+
resize(new_size) {
|
|
50
|
+
const array = new Array(new_size);
|
|
51
|
+
|
|
52
|
+
this.data = array;
|
|
53
|
+
this.size = new_size;
|
|
54
|
+
|
|
55
|
+
this.clear();
|
|
56
|
+
|
|
57
|
+
// TODO implement a way to keep the old data, need to figure out the correct adjustments to head and tail
|
|
58
|
+
}
|
|
59
|
+
|
|
45
60
|
/**
|
|
46
61
|
*
|
|
47
62
|
* @return {V}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array} a
|
|
2
|
+
* @template T
|
|
3
|
+
* @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array|Float32Array} a
|
|
4
4
|
* @param {number} a_offset
|
|
5
|
-
* @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array} b
|
|
5
|
+
* @param {T[]|ArrayLike<T>|TypedArray|Uint8ClampedArray|Uint8Array|Float32Array} b
|
|
6
6
|
* @param {number} b_offset
|
|
7
7
|
* @param {number} length How many elements should be moved
|
|
8
8
|
*/
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AbstractAsyncMap } from "./AbstractAsyncMap.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cache wrapper that loads data when it's not found in the cache
|
|
5
|
+
*/
|
|
6
|
+
export class AsyncLoadingCache extends AbstractAsyncMap {
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {Map} cache
|
|
10
|
+
* @param {function(K):Promise<T>} loader
|
|
11
|
+
*/
|
|
12
|
+
constructor(cache, loader) {
|
|
13
|
+
super();
|
|
14
|
+
|
|
15
|
+
this.__cache = cache;
|
|
16
|
+
this.__loader = loader;
|
|
17
|
+
this.__pending = new Map();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async get(key) {
|
|
21
|
+
|
|
22
|
+
const cached = this.__cache.get(key);
|
|
23
|
+
|
|
24
|
+
if (cached !== undefined) {
|
|
25
|
+
return cached;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let promise = this.__pending.get(key);
|
|
29
|
+
let original_loader = false;
|
|
30
|
+
|
|
31
|
+
if (promise === undefined) {
|
|
32
|
+
promise = this.__loader(key);
|
|
33
|
+
|
|
34
|
+
this.__pending.set(key, promise);
|
|
35
|
+
|
|
36
|
+
original_loader = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const value = await promise;
|
|
40
|
+
|
|
41
|
+
if (original_loader) {
|
|
42
|
+
this.__cache.get(key, value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -18,7 +18,7 @@ export function aabb3_computeDistanceAbovePlane_max(
|
|
|
18
18
|
_x1, _y1, _z1
|
|
19
19
|
) {
|
|
20
20
|
|
|
21
|
-
// pick a corner point
|
|
21
|
+
// pick a corner point that is the closest along the plane normal
|
|
22
22
|
const px = plane_normal_x > 0 ? _x1 : _x0;
|
|
23
23
|
const py = plane_normal_y > 0 ? _y1 : _y0;
|
|
24
24
|
const pz = plane_normal_z > 0 ? _z1 : _z0;
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* 99% | 2.57583
|
|
13
13
|
* 99.9% | 3.29053
|
|
14
14
|
*
|
|
15
|
-
* @param z Standard distribution value. # of standard deviations. See statistical tables
|
|
16
|
-
* @param p Fraction of the population with attribute in question. For example if we want to estimate what time people have breakfast and we know that only 30% of people have have breakfast overall, p would be 0.3
|
|
17
|
-
* @param e Error tolerance, 0.05 represents 5% error tolerance
|
|
15
|
+
* @param {number} z Standard distribution value. # of standard deviations. See statistical tables
|
|
16
|
+
* @param {number} p Fraction of the population with attribute in question. For example if we want to estimate what time people have breakfast and we know that only 30% of people have have breakfast overall, p would be 0.3
|
|
17
|
+
* @param {number} e Error tolerance, 0.05 represents 5% error tolerance
|
|
18
18
|
* @returns {number} Sample size
|
|
19
19
|
*/
|
|
20
20
|
export function computeSampleSize_Cochran(z, p, e) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { TypeEditor } from "../../TypeEditor.js";
|
|
2
2
|
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
3
|
-
import { DEG2RAD, RAD2DEG } from "three/src/math/MathUtils.js";
|
|
4
3
|
import { makeV3_editor } from "../common/makeV3_editor.js";
|
|
4
|
+
import { DEG_TO_RAD } from "../../../../../core/math/DEG_TO_RAD.js";
|
|
5
|
+
import { RAD_TO_DEG } from "../../../../../core/math/RAD_TO_DEG.js";
|
|
5
6
|
|
|
6
7
|
export class QuaternionEditor extends TypeEditor {
|
|
7
8
|
build(parent, field, registry) {
|
|
@@ -20,7 +21,13 @@ export class QuaternionEditor extends TypeEditor {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
lock = true;
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
q.__setFromEuler(
|
|
26
|
+
euler.x * DEG_TO_RAD,
|
|
27
|
+
euler.y * DEG_TO_RAD,
|
|
28
|
+
euler.z * DEG_TO_RAD
|
|
29
|
+
);
|
|
30
|
+
|
|
24
31
|
lock = false;
|
|
25
32
|
};
|
|
26
33
|
|
|
@@ -36,9 +43,9 @@ export class QuaternionEditor extends TypeEditor {
|
|
|
36
43
|
q.toEulerAnglesXYZ(t);
|
|
37
44
|
|
|
38
45
|
euler.set(
|
|
39
|
-
t.x *
|
|
40
|
-
t.y *
|
|
41
|
-
t.z *
|
|
46
|
+
t.x * RAD_TO_DEG,
|
|
47
|
+
t.y * RAD_TO_DEG,
|
|
48
|
+
t.z * RAD_TO_DEG,
|
|
42
49
|
);
|
|
43
50
|
|
|
44
51
|
lock = false;
|
package/engine/Engine.js
CHANGED
|
@@ -84,7 +84,7 @@ class Engine {
|
|
|
84
84
|
*
|
|
85
85
|
* @type {ConcurrentExecutor}
|
|
86
86
|
*/
|
|
87
|
-
this.executor = new ConcurrentExecutor(
|
|
87
|
+
this.executor = new ConcurrentExecutor(1, 10);
|
|
88
88
|
|
|
89
89
|
this.__using_external_entity_manager = entityManager !== undefined;
|
|
90
90
|
|
|
@@ -412,6 +412,9 @@ class Engine {
|
|
|
412
412
|
start() {
|
|
413
413
|
const self = this;
|
|
414
414
|
|
|
415
|
+
|
|
416
|
+
this.assetManager.startup();
|
|
417
|
+
|
|
415
418
|
function promiseEntityManager() {
|
|
416
419
|
return new Promise(function (resolve, reject) {
|
|
417
420
|
//initialize entity manager
|
|
@@ -488,6 +491,8 @@ class Engine {
|
|
|
488
491
|
|
|
489
492
|
|
|
490
493
|
// TODO shutdown executor
|
|
494
|
+
|
|
495
|
+
await this.assetManager.shutdown();
|
|
491
496
|
}
|
|
492
497
|
|
|
493
498
|
exit() {
|
|
@@ -30,7 +30,8 @@ export class EngineBootstrapper {
|
|
|
30
30
|
|
|
31
31
|
this.rootNode.appendChild(v.el);
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
// NOTE: the engine used to be started here, this was moved out
|
|
34
|
+
const started = Promise.resolve();
|
|
34
35
|
|
|
35
36
|
const vExecutionEngineState = new LabelView('');
|
|
36
37
|
const vAssetManagerState = new LabelView('');
|
package/engine/EngineHarness.js
CHANGED
|
@@ -201,6 +201,7 @@ export class EngineHarness {
|
|
|
201
201
|
|
|
202
202
|
camera.active.set(true);
|
|
203
203
|
camera.autoClip = autoClip;
|
|
204
|
+
camera.clip_far = distanceMax;
|
|
204
205
|
camera.fov.set(fieldOfView);
|
|
205
206
|
|
|
206
207
|
const entityBuilder = new EntityBuilder();
|
|
@@ -233,6 +234,7 @@ export class EngineHarness {
|
|
|
233
234
|
* @param {boolean} [enableTerrain]
|
|
234
235
|
* @param {boolean} [enableLights=true]
|
|
235
236
|
* @param {number} [cameraFieldOfView]
|
|
237
|
+
* @param {number} [cameraFarDistance]
|
|
236
238
|
* @param {boolean} [cameraController=true]
|
|
237
239
|
*/
|
|
238
240
|
static async buildBasics({
|
|
@@ -249,6 +251,7 @@ export class EngineHarness {
|
|
|
249
251
|
enableTerrain = true,
|
|
250
252
|
enableLights = true,
|
|
251
253
|
cameraFieldOfView,
|
|
254
|
+
cameraFarDistance,
|
|
252
255
|
cameraController = true
|
|
253
256
|
}) {
|
|
254
257
|
|
|
@@ -262,7 +265,8 @@ export class EngineHarness {
|
|
|
262
265
|
pitch,
|
|
263
266
|
yaw,
|
|
264
267
|
distance,
|
|
265
|
-
fieldOfView: cameraFieldOfView
|
|
268
|
+
fieldOfView: cameraFieldOfView,
|
|
269
|
+
distanceMax: cameraFarDistance
|
|
266
270
|
});
|
|
267
271
|
|
|
268
272
|
const cameraEntity = camera.entity;
|
|
@@ -13,6 +13,9 @@ import { CrossOriginConfig } from "./CORS/CrossOriginConfig.js";
|
|
|
13
13
|
import { array_remove_element } from "../../core/collection/array/array_remove_element.js";
|
|
14
14
|
import { AssetDescription } from "./AssetDescription.js";
|
|
15
15
|
import { noop } from "../../core/function/Functions.js";
|
|
16
|
+
import { Deque } from "../../core/collection/queue/Deque.js";
|
|
17
|
+
import Task from "../../core/process/task/Task.js";
|
|
18
|
+
import { TaskSignal } from "../../core/process/task/TaskSignal.js";
|
|
16
19
|
|
|
17
20
|
class AssetRequest {
|
|
18
21
|
/**
|
|
@@ -68,6 +71,18 @@ class PendingAsset {
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
class Response {
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param {Asset} asset
|
|
78
|
+
* @param {AssetRequest} request
|
|
79
|
+
*/
|
|
80
|
+
constructor(asset, request) {
|
|
81
|
+
this.asset = asset;
|
|
82
|
+
this.request = request;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
71
86
|
|
|
72
87
|
/**
|
|
73
88
|
* @class
|
|
@@ -139,6 +154,60 @@ export class AssetManager {
|
|
|
139
154
|
* @type {boolean}
|
|
140
155
|
*/
|
|
141
156
|
this.isAssetManager = true;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* @type {Deque<Response>}
|
|
161
|
+
* @private
|
|
162
|
+
*/
|
|
163
|
+
this.__response_queue = new Deque();
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
*
|
|
167
|
+
* @type {Task}
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
this.__response_processor = new Task({
|
|
171
|
+
name: "Asset Manager Response processor",
|
|
172
|
+
cycleFunction: () => {
|
|
173
|
+
if (this.__response_queue.isEmpty()) {
|
|
174
|
+
return TaskSignal.Yield;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const response = this.__response_queue.removeFirst();
|
|
178
|
+
|
|
179
|
+
this.__process_response(response);
|
|
180
|
+
|
|
181
|
+
return TaskSignal.Continue;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
this.__is_running = false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
startup() {
|
|
189
|
+
if (this.__is_running) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.__engine.executor.run(this.__response_processor);
|
|
194
|
+
|
|
195
|
+
this.__is_running = true;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async shutdown(immediate = false) {
|
|
199
|
+
if (!this.__is_running) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (!immediate) {
|
|
204
|
+
// wait until all responses have been processed
|
|
205
|
+
await Promise.allSettled([Task.promise(this.__response_processor)]);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
this.__engine.executor.removeTask(this.__response_processor);
|
|
209
|
+
|
|
210
|
+
this.__is_running = false;
|
|
142
211
|
}
|
|
143
212
|
|
|
144
213
|
/**
|
|
@@ -215,6 +284,30 @@ export class AssetManager {
|
|
|
215
284
|
this.assets.set(assetDescription, asset);
|
|
216
285
|
}
|
|
217
286
|
|
|
287
|
+
/**
|
|
288
|
+
*
|
|
289
|
+
* @param {Response} response
|
|
290
|
+
* @private
|
|
291
|
+
*/
|
|
292
|
+
__process_response(response) {
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
response.request.successCallback(response.asset);
|
|
296
|
+
} catch (e) {
|
|
297
|
+
console.error("Failed to execute asset success callback", e);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
*
|
|
303
|
+
* @param {Asset} asset
|
|
304
|
+
* @param {AssetRequest} request
|
|
305
|
+
* @private
|
|
306
|
+
*/
|
|
307
|
+
__schedule_response(asset, request) {
|
|
308
|
+
this.__response_queue.add(new Response(asset, request));
|
|
309
|
+
}
|
|
310
|
+
|
|
218
311
|
/**
|
|
219
312
|
*
|
|
220
313
|
* @param {string} path
|
|
@@ -299,18 +392,15 @@ export class AssetManager {
|
|
|
299
392
|
//register asset
|
|
300
393
|
assets.set(assetDescription, asset);
|
|
301
394
|
|
|
395
|
+
//clear callbacks
|
|
396
|
+
requestMap.delete(assetDescription);
|
|
397
|
+
|
|
302
398
|
// process callbacks
|
|
303
399
|
for (let i = 0; i < requests.length; i++) {
|
|
304
400
|
const request = requests[i];
|
|
305
|
-
|
|
306
|
-
request.successCallback(asset);
|
|
307
|
-
} catch (e) {
|
|
308
|
-
console.error("Failed to execute asset success callback", e);
|
|
309
|
-
}
|
|
401
|
+
this.__schedule_response(asset, request);
|
|
310
402
|
}
|
|
311
403
|
|
|
312
|
-
//clear callbacks
|
|
313
|
-
requestMap.delete(assetDescription);
|
|
314
404
|
}
|
|
315
405
|
|
|
316
406
|
function failure(error) {
|
|
@@ -2,6 +2,7 @@ export class AbstractMetric {
|
|
|
2
2
|
/**
|
|
3
3
|
*
|
|
4
4
|
* @param {number} value
|
|
5
|
+
* @returns {void}
|
|
5
6
|
*/
|
|
6
7
|
record(value) {
|
|
7
8
|
throw new Error('Not implemented');
|
|
@@ -17,12 +18,13 @@ export class AbstractMetric {
|
|
|
17
18
|
/**
|
|
18
19
|
*
|
|
19
20
|
* @param {MetricStatistics} result
|
|
21
|
+
* @returns {boolean} whether metric was successfully computed or not
|
|
20
22
|
*/
|
|
21
23
|
computeStats(result) {
|
|
22
24
|
throw new Error('Not implemented');
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
clear(){
|
|
27
|
+
clear() {
|
|
26
28
|
throw new Error('Not implemented');
|
|
27
29
|
}
|
|
28
30
|
}
|
|
@@ -9,9 +9,23 @@ export class RingBufferMetric extends AbstractMetric {
|
|
|
9
9
|
constructor(size = 100) {
|
|
10
10
|
super();
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @type {RingBuffer}
|
|
15
|
+
* @readonly
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
12
18
|
this.__data = new RingBuffer(size);
|
|
13
19
|
}
|
|
14
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Resize underlying buffer to be able to keep a different number of records
|
|
23
|
+
* @param {number} size
|
|
24
|
+
*/
|
|
25
|
+
resize(size) {
|
|
26
|
+
this.__data.resize(size);
|
|
27
|
+
}
|
|
28
|
+
|
|
15
29
|
getLastRecord() {
|
|
16
30
|
return this.__data.getHead();
|
|
17
31
|
}
|
|
@@ -20,16 +34,37 @@ export class RingBufferMetric extends AbstractMetric {
|
|
|
20
34
|
this.__data.push(value);
|
|
21
35
|
}
|
|
22
36
|
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param {MetricStatistics} result
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
23
42
|
computeStats(result) {
|
|
24
43
|
|
|
25
44
|
const buffer = this.__data;
|
|
26
45
|
const array = buffer.data;
|
|
27
46
|
const data_count = buffer.count;
|
|
28
47
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
48
|
+
if (data_count === 0) {
|
|
49
|
+
|
|
50
|
+
// no data
|
|
51
|
+
result.mean = 0;
|
|
52
|
+
result.meadian = 0;
|
|
53
|
+
result.min = 0;
|
|
54
|
+
result.max = 0;
|
|
55
|
+
|
|
56
|
+
return false;
|
|
57
|
+
|
|
58
|
+
} else {
|
|
59
|
+
|
|
60
|
+
result.mean = computeStatisticalMean(array, 0, data_count);
|
|
61
|
+
result.meadian = computeStatisticalPartialMedian(array, 0, data_count);
|
|
62
|
+
result.max = computeArrayMax(array, 0, data_count);
|
|
63
|
+
result.min = computeArrayMin(array, 0, data_count);
|
|
64
|
+
|
|
65
|
+
return true;
|
|
66
|
+
|
|
67
|
+
}
|
|
33
68
|
}
|
|
34
69
|
|
|
35
70
|
clear() {
|
|
@@ -8,11 +8,30 @@ import { isDefined } from "../../core/process/matcher/Matchers.js";
|
|
|
8
8
|
* @enum
|
|
9
9
|
*/
|
|
10
10
|
export const EntityBuilderFlags = {
|
|
11
|
+
/**
|
|
12
|
+
* Whether the entity is built, set internally
|
|
13
|
+
*/
|
|
11
14
|
Built: 1,
|
|
12
|
-
|
|
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
|
|
13
25
|
};
|
|
14
26
|
|
|
15
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Set of default flags
|
|
29
|
+
* @type {number}
|
|
30
|
+
*/
|
|
31
|
+
const DEFAULT_FLAGS =
|
|
32
|
+
EntityBuilderFlags.RegisterComponents
|
|
33
|
+
| EntityBuilderFlags.WatchDestruction
|
|
34
|
+
;
|
|
16
35
|
|
|
17
36
|
/**
|
|
18
37
|
* Representation of an entity, helps build entities and keep track of them without having to access {@link EntityComponentDataset} directly
|
|
@@ -53,6 +72,10 @@ class EntityBuilder {
|
|
|
53
72
|
*/
|
|
54
73
|
this.dataset = null;
|
|
55
74
|
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @type {EntityBuilderFlags|number}
|
|
78
|
+
*/
|
|
56
79
|
this.flags = DEFAULT_FLAGS;
|
|
57
80
|
|
|
58
81
|
/**
|
|
@@ -132,7 +155,7 @@ class EntityBuilder {
|
|
|
132
155
|
throw new Error("Can not add " + componentInstance + " to EntityBuilder");
|
|
133
156
|
}
|
|
134
157
|
|
|
135
|
-
assert.notOk(this.hasComponent(Object.getPrototypeOf(componentInstance).constructor)
|
|
158
|
+
assert.notOk(this.hasComponent(Object.getPrototypeOf(componentInstance).constructor), 'Component of this type already exists');
|
|
136
159
|
|
|
137
160
|
this.element.push(componentInstance);
|
|
138
161
|
|
|
@@ -378,7 +401,9 @@ class EntityBuilder {
|
|
|
378
401
|
|
|
379
402
|
this.setFlag(EntityBuilderFlags.Built);
|
|
380
403
|
|
|
381
|
-
|
|
404
|
+
if (this.getFlag(EntityBuilderFlags.WatchDestruction)) {
|
|
405
|
+
dataset.addEntityEventListener(entity, EventType.EntityRemoved, this.__handleEntityDestroyed, this);
|
|
406
|
+
}
|
|
382
407
|
|
|
383
408
|
this.on.built.send2(entity, dataset);
|
|
384
409
|
return entity;
|
|
@@ -24,6 +24,22 @@ class TopDownCameraControllerSystem extends System {
|
|
|
24
24
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {TopDownCameraController} ctrl
|
|
30
|
+
* @param {number} entity
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
__visit_camera_entity(ctrl, entity){
|
|
34
|
+
const transform = this.entityManager.dataset.getComponent(entity,Transform);
|
|
35
|
+
|
|
36
|
+
if(transform === undefined){
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
computeTopDownTransform(ctrl,transform);
|
|
41
|
+
}
|
|
42
|
+
|
|
27
43
|
update(timeDelta) {
|
|
28
44
|
const em = this.entityManager;
|
|
29
45
|
|
|
@@ -34,7 +50,7 @@ class TopDownCameraControllerSystem extends System {
|
|
|
34
50
|
const dataset = em.dataset;
|
|
35
51
|
|
|
36
52
|
if (this.enabled.get() && dataset !== null) {
|
|
37
|
-
dataset.
|
|
53
|
+
dataset.traverseComponents(TopDownCameraController, this.__visit_camera_entity, this);
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
}
|
|
@@ -8,6 +8,8 @@ import { Decal as FPDecal } from '../../../render/forward_plus/model/Decal.js';
|
|
|
8
8
|
import { AssetManager } from "../../../../asset/AssetManager.js";
|
|
9
9
|
import { Sampler2D } from "../../../texture/sampler/Sampler2D.js";
|
|
10
10
|
import { GameAssetType } from "../../../../asset/GameAssetType.js";
|
|
11
|
+
import { assert } from "../../../../../core/assert.js";
|
|
12
|
+
import { AsyncLoadingCache } from "../../../../../core/collection/map/AsyncLoadingCache.js";
|
|
11
13
|
|
|
12
14
|
const placeholder_texture = Sampler2D.uint8(4, 1, 1);
|
|
13
15
|
placeholder_texture.data.fill(255);
|
|
@@ -65,8 +67,20 @@ class Context extends SystemEntityContext {
|
|
|
65
67
|
return;
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
/**
|
|
71
|
+
*
|
|
72
|
+
* @type {FPDecalSystem}
|
|
73
|
+
*/
|
|
74
|
+
const system = this.system;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @type {Sampler2D}
|
|
78
|
+
*/
|
|
79
|
+
const loaded_texture = await system.__texture_cache.get(_uri);
|
|
68
80
|
|
|
69
|
-
|
|
81
|
+
assert.defined(loaded_texture, 'loaded_texture');
|
|
82
|
+
assert.notNull(loaded_texture, 'loaded_texture');
|
|
83
|
+
assert.equal(loaded_texture.isSampler2D, true, 'texture.isSampler2D !== true');
|
|
70
84
|
|
|
71
85
|
decal_spec.__cached_sampler = loaded_texture;
|
|
72
86
|
decal_spec.__cached_uri = _uri;
|
|
@@ -147,7 +161,9 @@ export class FPDecalSystem extends AbstractContextSystem {
|
|
|
147
161
|
* @type {Map<string, Sampler2D>}
|
|
148
162
|
* @private
|
|
149
163
|
*/
|
|
150
|
-
this.__texture_cache = new Map()
|
|
164
|
+
this.__texture_cache = new AsyncLoadingCache(new Map(), (key) => {
|
|
165
|
+
return this.__assets.promise(key, GameAssetType.Image).then(asset => asset.create());
|
|
166
|
+
});
|
|
151
167
|
|
|
152
168
|
/**
|
|
153
169
|
*
|
|
@@ -171,34 +187,6 @@ export class FPDecalSystem extends AbstractContextSystem {
|
|
|
171
187
|
this.__fp_plugin = Reference.NULL;
|
|
172
188
|
}
|
|
173
189
|
|
|
174
|
-
/**
|
|
175
|
-
*
|
|
176
|
-
* @param {string} uri
|
|
177
|
-
* @returns {Promise<void>}
|
|
178
|
-
*/
|
|
179
|
-
async internal_loadTexture(uri) {
|
|
180
|
-
const cached = this.__texture_cache.get(uri);
|
|
181
|
-
|
|
182
|
-
if (cached !== undefined) {
|
|
183
|
-
return cached;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const asset = await this.__assets.promise(uri, GameAssetType.Image);
|
|
187
|
-
|
|
188
|
-
// check cache again, in case another request has succeeded
|
|
189
|
-
const cached_v2 = this.__texture_cache.get(uri);
|
|
190
|
-
|
|
191
|
-
if (cached_v2 !== undefined) {
|
|
192
|
-
return cached_v2;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const sampler = asset.create();
|
|
196
|
-
|
|
197
|
-
this.__texture_cache.set(uri, sampler);
|
|
198
|
-
|
|
199
|
-
return sampler;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
190
|
async startup(em, ready_callback, error_callback) {
|
|
203
191
|
this.__fp_plugin = await this.__engine.plugins.acquire(ForwardPlusRenderingPlugin);
|
|
204
192
|
|