@woosh/meep-engine 2.60.0 → 2.61.0

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.
Files changed (65) hide show
  1. package/build/meep.cjs +20211 -20240
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +20211 -20240
  4. package/package.json +1 -1
  5. package/src/core/binary/BitSet.js +1 -1
  6. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +30 -182
  7. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.spec.js +27 -1
  8. package/src/core/geom/ConicRay.js +16 -21
  9. package/src/core/geom/ConicRay.spec.js +24 -0
  10. package/src/core/geom/packing/miniball/Miniball.js +68 -117
  11. package/src/core/geom/packing/miniball/Miniball.spec.js +3 -3
  12. package/src/core/geom/packing/miniball/Subspan.js +47 -34
  13. package/src/core/geom/packing/miniball/miniball_compute_quality.js +64 -0
  14. package/src/core/math/bessel_3.js +1 -0
  15. package/src/core/math/random/randomBytes.js +2 -2
  16. package/src/core/math/sqr.js +8 -0
  17. package/src/core/model/node-graph/Connection.js +21 -23
  18. package/src/core/model/node-graph/DataType.js +16 -17
  19. package/src/core/model/node-graph/NodeGraph.js +49 -50
  20. package/src/core/model/node-graph/node/NodeDescription.js +42 -44
  21. package/src/core/model/node-graph/node/NodeInstance.js +59 -60
  22. package/src/core/model/node-graph/node/NodeInstancePortReference.js +27 -29
  23. package/src/core/model/node-graph/node/NodeRegistry.js +16 -18
  24. package/src/core/model/node-graph/node/Port.js +35 -37
  25. package/src/core/model/node-graph/node/parameter/NodeParameterDescription.js +27 -13
  26. package/src/core/path/computePathDirectory.spec.js +8 -0
  27. package/src/core/process/BaseProcess.d.ts +5 -0
  28. package/src/core/process/WatchDog.js +76 -75
  29. package/src/core/process/action/AsynchronousAction.js +24 -22
  30. package/src/core/process/executor/profile/Profile.js +34 -24
  31. package/src/core/process/executor/profile/TraceEvent.js +75 -75
  32. package/src/core/process/worker/OnDemandWorkerManager.js +27 -30
  33. package/src/core/process/worker/WorkerBuilder.js +149 -149
  34. package/src/core/process/worker/WorkerProxy.js +25 -21
  35. package/src/core/process/worker/extractTransferables.js +2 -2
  36. package/src/engine/Engine.js +58 -53
  37. package/src/engine/EngineConfiguration.d.ts +4 -4
  38. package/src/engine/ecs/EntityManager.js +517 -614
  39. package/src/engine/ecs/System.js +2 -2
  40. package/src/engine/ecs/transform/Transform.d.ts +7 -5
  41. package/src/engine/ecs/transform/Transform.js +30 -16
  42. package/src/engine/ecs/validateSystem.js +89 -0
  43. package/src/engine/graphics/GraphicsEngine.js +433 -483
  44. package/src/engine/graphics/camera/testClippingPlaneComputation.js +46 -48
  45. package/src/engine/graphics/ecs/camera/Camera.js +11 -11
  46. package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
  47. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
  48. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +2 -2
  49. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +60 -62
  50. package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +20 -22
  51. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +15 -4
  52. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +156 -180
  53. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +69 -71
  54. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +51 -53
  55. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +67 -69
  56. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +56 -58
  57. package/src/engine/graphics/shadows/testShadowMapRendering.js +30 -34
  58. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js +22 -20
  59. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.js +10 -13
  60. package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +1 -1
  61. package/src/engine/plugin/EnginePluginManager.d.ts +6 -1
  62. package/src/engine/ecs/components/ClingToHeightMap.js +0 -19
  63. package/src/engine/ecs/components/SynchronizePosition.js +0 -15
  64. package/src/engine/ecs/systems/ClingToHeightMapSystem.js +0 -170
  65. package/src/engine/ecs/systems/SynchronizePositionSystem.js +0 -43
@@ -3,53 +3,163 @@
3
3
  */
4
4
 
5
5
 
6
- import { convertPathToURL } from "../../../engine/network/convertPathToURL.js";
7
- import WorkerProxy from "./WorkerProxy.js";
6
+ import {convertPathToURL} from "../../../engine/network/convertPathToURL.js";
8
7
  import LineBuilder from "../../codegen/LineBuilder.js";
8
+ import WorkerProxy from "./WorkerProxy.js";
9
9
 
10
10
  const RxMatchFunctionName = /(function\s*)([a-zA-Z0-9_]+)?(\s*\([^\]]*\)\s*\{.*)/g;
11
11
 
12
- const WorkerBuilder = function () {
13
- this.imports = [];
14
- this.methods = {};
15
- this.functions = [];
16
- this.preable = new LineBuilder();
17
- };
12
+ class WorkerBuilder {
18
13
 
19
- WorkerBuilder.prototype.addCode = function (code) {
20
- this.preable.add(code);
21
- };
14
+ imports = [];
15
+ methods = {};
16
+ functions = [];
17
+ preamble = new LineBuilder();
22
18
 
23
- /**
24
- *
25
- * @param {string} name
26
- * @param {function|string} method
27
- */
28
- WorkerBuilder.prototype.addMethod = function (name, method) {
29
- this.methods[name] = method;
30
- };
19
+ addCode(code) {
20
+ this.preamble.add(code);
21
+ }
31
22
 
32
- /**
33
- * NOTE: take care when using minifiers as they may mangle function names
34
- * @deprecated
35
- * @param name
36
- * @param {function} f
37
- */
38
- WorkerBuilder.prototype.importFunction = function (name, f) {
39
- this.functions.push({
40
- f,
41
- name
42
- });
43
- };
23
+ /**
24
+ *
25
+ * @param {string} name
26
+ * @param {function|string} method
27
+ */
28
+ addMethod(name, method) {
29
+ this.methods[name] = method;
30
+ }
44
31
 
45
- /**
46
- *
47
- * @param {string} path
48
- */
49
- WorkerBuilder.prototype.importScript = function (path) {
50
- path = convertPathToURL(path);
32
+ /**
33
+ * NOTE: take care when using minifiers as they may mangle function names
34
+ * @deprecated
35
+ * @param name
36
+ * @param {function} f
37
+ */
38
+ importFunction(name, f) {
39
+ this.functions.push({
40
+ f,
41
+ name
42
+ });
43
+ }
44
+
45
+ /**
46
+ *
47
+ * @param {string} path
48
+ */
49
+ importScript(path) {
50
+ path = convertPathToURL(path);
51
+
52
+ this.imports.push(path);
53
+ }
54
+
55
+ /**
56
+ *
57
+ * @returns {WorkerProxy}
58
+ */
59
+ build() {
60
+ const codeLines = [];
61
+
62
+ codeLines.push('var globalScope = this;');
63
+
64
+ //handle imports
65
+ this.imports.forEach(function (url) {
66
+ codeLines.push("globalScope.importScripts('" + url + "');");
67
+ });
68
+
69
+ codeLines.push(this.preamble.build());
70
+
71
+ //handle functions
72
+ this.functions.forEach(function (spec) {
73
+ const f = spec.f;
74
+
75
+ const function_string = f.toString();
76
+
77
+ // We rewrite the function to explicitly set function name. This is needed to work around various code compressors such as Uglify or Terser that mange original function names or remove them altogether
78
+ const renamed_function_string = function_string.replace(RxMatchFunctionName, `$1${spec.name}$3`);
79
+
80
+ codeLines.push(renamed_function_string);
81
+ });
82
+
83
+
84
+ //api hash
85
+ codeLines.push('var api = {};');
86
+ for (let apiName in this.methods) {
87
+ if (this.methods.hasOwnProperty(apiName)) {
88
+ const method = this.methods[apiName];
89
+
90
+
91
+ const type_of_method = typeof method;
92
+
93
+ let method_code;
94
+
95
+ if (type_of_method === 'function') {
96
+ method_code = method.toString();
97
+ } else if (type_of_method === 'string') {
98
+ method_code = method;
99
+ } else {
100
+ throw new Error(`Unsupported method type '${type_of_method}'`);
101
+ }
51
102
 
52
- this.imports.push(path);
103
+
104
+ codeLines.push("api['" + apiName + "'] = " + method_code + ";");
105
+ }
106
+ }
107
+
108
+ //api handler
109
+ Array.prototype.push.apply(codeLines, [
110
+ `function extractTransferables(obj, result) {
111
+ if (typeof obj !== "object") {
112
+ return; //not an object, skip
113
+ } else if (obj instanceof ArrayBuffer) {
114
+ result.push(obj);
115
+ } else if (obj.buffer instanceof ArrayBuffer) {
116
+ result.push(obj.buffer);
117
+ } else if (obj instanceof ImageBitmap) {
118
+ result.push(obj);
119
+ } else {
120
+ for (var i in obj) {
121
+ if (obj.hasOwnProperty(i)) {
122
+ extractTransferables(obj[i], result);
123
+ }
124
+ }
125
+ }
126
+ }`,
127
+ 'globalScope.onmessage = function(event){',
128
+ ' var eventData = event.data;',
129
+ ' var requestId = eventData.id',
130
+ ' var methodName = eventData.methodName;',
131
+ ' var parameters = eventData.parameters;',
132
+ ' var method = api[methodName];',
133
+
134
+ ' function sendResult(result){',
135
+ ' var transferables = [];',
136
+ ' extractTransferables(result, transferables);',
137
+ ' globalScope.postMessage({methodName: methodName, id: requestId, result: result}, transferables);',
138
+ ' }',
139
+
140
+ ' function sendError(error){',
141
+ ' let stack = "";',
142
+ ' try{stack = error.stack.split("\\n")}catch(e){}',
143
+ ' globalScope.postMessage({methodName: methodName, id: requestId, error: {message: error.message, stack: stack }});',
144
+ ' }',
145
+
146
+ ' if(method === undefined){',
147
+ ' sendError(new Error("API named \'"+methodName+"\' was not found."));',
148
+ ' }else{',
149
+ ' try{',
150
+ ' method.apply(null,parameters).then(sendResult, sendError);',
151
+ ' }catch(e){',
152
+ ' sendError(e);',
153
+ ' }',
154
+ ' }',
155
+ '};'
156
+ ]);
157
+
158
+ const code = codeLines.join("\n");
159
+ const workerURL = codeToURL(code);
160
+
161
+ return new WorkerProxy(workerURL, this.methods);
162
+ }
53
163
  };
54
164
 
55
165
  /**
@@ -64,7 +174,7 @@ function codeToURL(code) {
64
174
 
65
175
  if (typeof window === 'object') {
66
176
  if (typeof window.Blob !== "undefined") {
67
- blob = new Blob([code], { type: js_mime });
177
+ blob = new Blob([code], {type: js_mime});
68
178
  } else {
69
179
  // Backwards-compatibility
70
180
  const BlobBuilder = window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
@@ -84,114 +194,4 @@ function codeToURL(code) {
84
194
  }
85
195
  }
86
196
 
87
- /**
88
- *
89
- * @returns {WorkerProxy}
90
- */
91
- WorkerBuilder.prototype.build = function () {
92
- const codeLines = [];
93
-
94
- codeLines.push('var globalScope = this;');
95
-
96
- //handle imports
97
- this.imports.forEach(function (url) {
98
- codeLines.push("globalScope.importScripts('" + url + "');");
99
- });
100
-
101
- codeLines.push(this.preable.build());
102
-
103
- //handle functions
104
- this.functions.forEach(function (spec) {
105
- const f = spec.f;
106
-
107
- const function_string = f.toString();
108
-
109
- // We rewrite the function to explicitly set function name. This is needed to work around various code compressors such as Uglify or Terser that mange original function names or remove them altogether
110
- const renamed_function_string = function_string.replace(RxMatchFunctionName, `$1${spec.name}$3`);
111
-
112
- codeLines.push(renamed_function_string);
113
- });
114
-
115
-
116
- //api hash
117
- codeLines.push('var api = {};');
118
- for (let apiName in this.methods) {
119
- if (this.methods.hasOwnProperty(apiName)) {
120
- const method = this.methods[apiName];
121
-
122
-
123
- const type_of_method = typeof method;
124
-
125
- let method_code;
126
-
127
- if (type_of_method === 'function') {
128
- method_code = method.toString();
129
- } else if (type_of_method === 'string') {
130
- method_code = method;
131
- } else {
132
- throw new Error(`Unsupported method type '${type_of_method}'`);
133
- }
134
-
135
-
136
- codeLines.push("api['" + apiName + "'] = " + method_code + ";");
137
- }
138
- }
139
-
140
- //api handler
141
- Array.prototype.push.apply(codeLines, [
142
- `function extractTransferables(obj, result) {
143
- if (typeof obj !== "object") {
144
- return; //not an object, skip
145
- } else if (obj instanceof ArrayBuffer) {
146
- result.push(obj);
147
- } else if (obj.buffer instanceof ArrayBuffer) {
148
- result.push(obj.buffer);
149
- } else if (obj instanceof ImageBitmap) {
150
- result.push(obj);
151
- } else {
152
- for (var i in obj) {
153
- if (obj.hasOwnProperty(i)) {
154
- extractTransferables(obj[i], result);
155
- }
156
- }
157
- }
158
- }`,
159
- 'globalScope.onmessage = function(event){',
160
- ' var eventData = event.data;',
161
- ' var requestId = eventData.id',
162
- ' var methodName = eventData.methodName;',
163
- ' var parameters = eventData.parameters;',
164
- ' var method = api[methodName];',
165
-
166
- ' function sendResult(result){',
167
- ' var transferables = [];',
168
- ' extractTransferables(result, transferables);',
169
- ' globalScope.postMessage({methodName: methodName, id: requestId, result: result}, transferables);',
170
- ' }',
171
-
172
- ' function sendError(error){',
173
- ' let stack = "";',
174
- ' try{stack = error.stack.split("\\n")}catch(e){}',
175
- ' globalScope.postMessage({methodName: methodName, id: requestId, error: {message: error.message, stack: stack }});',
176
- ' }',
177
-
178
- ' if(method === undefined){',
179
- ' sendError(new Error("API named \'"+methodName+"\' was not found."));',
180
- ' }else{',
181
- ' try{',
182
- ' method.apply(null,parameters).then(sendResult, sendError);',
183
- ' }catch(e){',
184
- ' sendError(e);',
185
- ' }',
186
- ' }',
187
- '};'
188
- ]);
189
-
190
- const code = codeLines.join("\n");
191
- const workerURL = codeToURL(code);
192
-
193
- const proxy = new WorkerProxy(workerURL, this.methods);
194
- return proxy;
195
- };
196
-
197
197
  export default WorkerBuilder;
@@ -39,29 +39,29 @@ function needsSerialization(value) {
39
39
 
40
40
 
41
41
  class WorkerProxy {
42
+
43
+ __pending = {};
44
+ __isRunning = false;
45
+
46
+ /**
47
+ *
48
+ * @type {Worker|null}
49
+ * @private
50
+ */
51
+ __worker = null;
52
+
53
+ /**
54
+ *
55
+ * @type {number}
56
+ * @private
57
+ */
58
+ __id_counter = 0;
59
+
60
+
42
61
  constructor(url, methods) {
43
62
  this.url = url;
44
63
  this.methods = methods;
45
64
 
46
- this.__pending = {};
47
- this.__isRunning = false;
48
- /**
49
- *
50
- * @type {Worker|null}
51
- * @private
52
- */
53
- this.__worker = null;
54
-
55
- /**
56
- *
57
- * @type {number}
58
- * @private
59
- */
60
- this.__id_counter = 0;
61
- //
62
-
63
- this.__handleMessageBound = this.__handleMessage.bind(this);
64
-
65
65
  this.__generateAPI(this, methods);
66
66
  }
67
67
 
@@ -119,6 +119,10 @@ class WorkerProxy {
119
119
  }
120
120
 
121
121
  __makeMethod(name) {
122
+ if (this.__pending.hasOwnProperty(name)) {
123
+ throw new Error(`Method '${name}' already defined`);
124
+ }
125
+
122
126
  this.__pending[name] = [];
123
127
 
124
128
  const proxy = this;
@@ -144,7 +148,7 @@ class WorkerProxy {
144
148
  * @param {Event} event
145
149
  * @private
146
150
  */
147
- __handleMessage(event) {
151
+ __handleMessage = (event) => {
148
152
  const pending = this.__pending;
149
153
 
150
154
  const data = event.data;
@@ -262,7 +266,7 @@ class WorkerProxy {
262
266
  }
263
267
 
264
268
  this.__worker = new Worker(this.url);
265
- this.__worker.onmessage = this.__handleMessageBound;
269
+ this.__worker.onmessage = this.__handleMessage;
266
270
 
267
271
  // TODO attach proper error handler
268
272
  this.__worker.onerror = (errorEvent) => {
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export function extractTransferables(obj, result) {
8
8
  if (typeof obj !== "object") {
9
- return; //not an object, skip
9
+ // not an object, skip
10
10
  } else if (obj instanceof ArrayBuffer) {
11
11
  result.push(obj);
12
12
  } else if (obj.buffer instanceof ArrayBuffer) {
@@ -14,7 +14,7 @@ export function extractTransferables(obj, result) {
14
14
  } else if (obj instanceof ImageBitmap) {
15
15
  result.push(obj);
16
16
  } else {
17
- for (var i in obj) {
17
+ for (let i in obj) {
18
18
  if (obj.hasOwnProperty(i)) {
19
19
  extractTransferables(obj[i], result);
20
20
  }
@@ -2,35 +2,35 @@
2
2
  *
3
3
  */
4
4
 
5
+ import {PerspectiveCamera as ThreePerspectiveCamera} from 'three';
6
+ import {assert} from "../core/assert.js";
7
+ import Vector1 from "../core/geom/Vector1.js";
8
+ import {Localization} from "../core/localization/Localization.js";
9
+ import {ModuleRegistry} from "../core/model/ModuleRegistry.js";
10
+ import ObservedBoolean from "../core/model/ObservedBoolean.js";
5
11
  import ConcurrentExecutor from '../core/process/executor/ConcurrentExecutor.js';
12
+ import EmptyView from "../view/elements/EmptyView.js";
13
+ import {ViewStack} from "../view/elements/navigation/ViewStack.js";
6
14
 
7
- import { AssetManager } from './asset/AssetManager.js';
8
- import { GraphicsEngine } from './graphics/GraphicsEngine.js';
9
- import SoundEngine from './sound/SoundEngine.js';
10
- import { PerspectiveCamera as ThreePerspectiveCamera } from 'three';
11
- import { PointerDevice } from "./input/devices/PointerDevice.js";
12
- import KeyboardDevice from "./input/devices/KeyboardDevice.js";
15
+ import {AssetManager} from './asset/AssetManager.js';
13
16
  import Preloader from "./asset/preloader/Preloader.js";
17
+ import {MetricCollection} from "./development/performance/MetricCollection.js";
18
+ import {MetricStatistics} from "./development/performance/MetricStatistics.js";
19
+ import {PeriodicConsolePrinter} from "./development/performance/monitor/PeriodicConsolePrinter.js";
20
+ import {EntityManager} from "./ecs/EntityManager.js";
21
+ import {BinarySerializationRegistry} from "./ecs/storage/binary/BinarySerializationRegistry.js";
22
+ import {GraphicsEngine} from './graphics/GraphicsEngine.js';
23
+ import KeyboardDevice from "./input/devices/KeyboardDevice.js";
24
+ import {PointerDevice} from "./input/devices/PointerDevice.js";
25
+ import {StaticKnowledgeDatabase} from "./knowledge/database/StaticKnowledgeDatabase.js";
26
+ import {logger} from "./logging/GlobalLogger.js";
27
+ import {OptionGroup} from "./options/OptionGroup.js";
28
+ import {EnginePluginManager} from "./plugin/EnginePluginManager.js";
14
29
  import SceneManager from "./scene/SceneManager.js";
30
+ import Ticker from "./simulation/Ticker.js";
31
+ import SoundEngine from './sound/SoundEngine.js';
15
32
 
16
33
  import GUIEngine from './ui/GUIEngine.js';
17
- import { EntityManager } from "./ecs/EntityManager.js";
18
- import ObservedBoolean from "../core/model/ObservedBoolean.js";
19
- import Vector1 from "../core/geom/Vector1.js";
20
- import { ViewStack } from "../view/elements/navigation/ViewStack.js";
21
- import EmptyView from "../view/elements/EmptyView.js";
22
- import { assert } from "../core/assert.js";
23
- import { StaticKnowledgeDatabase } from "./knowledge/database/StaticKnowledgeDatabase.js";
24
- import Ticker from "./simulation/Ticker.js";
25
- import { Localization } from "../core/localization/Localization.js";
26
- import { ModuleRegistry } from "../core/model/ModuleRegistry.js";
27
- import { BinarySerializationRegistry } from "./ecs/storage/binary/BinarySerializationRegistry.js";
28
- import { EnginePluginManager } from "./plugin/EnginePluginManager.js";
29
- import { OptionGroup } from "./options/OptionGroup.js";
30
- import { MetricCollection } from "./development/performance/MetricCollection.js";
31
- import { PeriodicConsolePrinter } from "./development/performance/monitor/PeriodicConsolePrinter.js";
32
- import { MetricStatistics } from "./development/performance/MetricStatistics.js";
33
- import { logger } from "./logging/GlobalLogger.js";
34
34
 
35
35
 
36
36
  function EngineSettings() {
@@ -44,6 +44,10 @@ const METRIC_ID_RENDER = 'render_time';
44
44
  const METRIC_ID_SIMULATION = 'simulation_time';
45
45
 
46
46
  class Engine {
47
+ #last_frame_timestamp = 0;
48
+
49
+ viewStack = new ViewStack();
50
+
47
51
  /**
48
52
  *
49
53
  * @param {EnginePlatform} platform
@@ -220,7 +224,7 @@ class Engine {
220
224
 
221
225
  if (enableGraphics !== false) {
222
226
 
223
- const graphicsEngine = new GraphicsEngine(this.camera, this.entityManager);
227
+ const graphicsEngine = new GraphicsEngine(this.camera);
224
228
 
225
229
  /**
226
230
  *
@@ -317,8 +321,6 @@ class Engine {
317
321
  });
318
322
  this.gameView = gameView;
319
323
 
320
-
321
- this.viewStack = new ViewStack();
322
324
  this.viewStack.push(gameView, 'game-view');
323
325
 
324
326
  if (this.graphics !== undefined) {
@@ -409,6 +411,8 @@ class Engine {
409
411
  }
410
412
 
411
413
  render() {
414
+ assert.isInstanceOf(this, Engine, 'this', 'Engine');
415
+
412
416
  const graphics = this.graphics;
413
417
 
414
418
  if (graphics.autoDraw) {
@@ -437,56 +441,38 @@ class Engine {
437
441
  * @returns {Promise}
438
442
  */
439
443
  start() {
440
- const self = this;
441
-
442
-
443
444
  this.assetManager.startup();
444
445
 
445
- function promiseEntityManager() {
446
- return new Promise(function (resolve, reject) {
446
+ const promiseEntityManager = () => {
447
+ return new Promise((resolve, reject) => {
447
448
  //initialize entity manager
448
- self.entityManager.startup(resolve, reject);
449
+ this.entityManager.startup(resolve, reject);
449
450
  });
450
451
  }
451
452
 
452
453
  this.__performacne_monitor.start();
453
454
 
454
- const metrics = this.performance;
455
-
456
455
  return Promise.all([
457
456
  this.sound.start()
458
457
  .then(promiseEntityManager),
459
458
  this.staticKnowledge.load(this.assetManager, this.executor),
460
459
  this.gui.startup(this),
461
460
  this.plugins.startup()
462
- ]).then(function () {
463
-
464
- let t0 = performance.now();
465
-
466
- function animate() {
467
- const t1 = performance.now();
468
- requestAnimationFrame(animate);
469
- self.render();
461
+ ]).then(async () => {
470
462
 
471
- const frame_delay = (t1 - t0) / 1000;
472
-
473
- // swap variables
474
- t0 = t1;
475
-
476
- // record metric
477
- metrics.get(METRIC_ID_FRAME).record(frame_delay);
478
- }
463
+ this.#last_frame_timestamp = performance.now();
479
464
 
480
465
  /**
481
466
  * Starting the engine
482
467
  */
483
- requestAnimationFrame(animate);
468
+ requestAnimationFrame(this.#animation_frame);
469
+
484
470
  //start simulation
485
- self.ticker.start({ maxTimeout: 200 });
471
+ this.ticker.start({maxTimeout: 200});
486
472
  //self.uiController.init(self);
487
473
 
488
474
  //load options
489
- self.options.attachToStorage('lazykitty.komrade.options', self.storage);
475
+ await this.options.attachToStorage('lazykitty.komrade.options', this.storage);
490
476
 
491
477
  logger.info('engine started');
492
478
  }, function (e) {
@@ -496,6 +482,25 @@ class Engine {
496
482
 
497
483
  }
498
484
 
485
+ /**
486
+ * Fired every animation frame via {@link requestAnimationFrame}
487
+ */
488
+ #animation_frame = () => {
489
+
490
+ const t0 = this.#last_frame_timestamp;
491
+ const t1 = performance.now();
492
+ requestAnimationFrame(this.#animation_frame);
493
+ this.render();
494
+
495
+ const frame_delay = (t1 - t0) / 1000;
496
+
497
+ // swap variables
498
+ this.#last_frame_timestamp = t1;
499
+
500
+ // record metric
501
+ this.performance.get(METRIC_ID_FRAME).record(frame_delay);
502
+ }
503
+
499
504
  /**
500
505
  * Shutdown the engine, disposing all relevant resources
501
506
  */
@@ -1,7 +1,7 @@
1
- import {EnginePlugin} from "./plugin/EnginePlugin";
1
+ import {AssetLoader} from "./asset/loaders/AssetLoader";
2
2
  import {System} from "./ecs/System";
3
3
  import {StaticKnowledgeDataTableDescriptor} from "./knowledge/database/StaticKnowledgeDataTableDescriptor";
4
- import {AssetLoader} from "./asset/loaders/AssetLoader";
4
+ import {EnginePlugin} from "./plugin/EnginePlugin";
5
5
 
6
6
  export class EngineConfiguration {
7
7
  addPlugin(plugin: EnginePlugin): boolean
@@ -10,9 +10,9 @@ export class EngineConfiguration {
10
10
 
11
11
  addManySystems(...systems: System<any>[]): void
12
12
 
13
- addDataTable(table: StaticKnowledgeDataTableDescriptor): boolean
13
+ addDataTable<T>(table: StaticKnowledgeDataTableDescriptor<T>): boolean
14
14
 
15
- addLoader<T>(type: string, loader: AssetLoader<T>): boolean
15
+ addLoader<T, CTX>(type: string, loader: AssetLoader<T, CTX>): boolean
16
16
 
17
17
  hasLoader(type: string): boolean
18
18