@woosh/meep-engine 2.84.11 → 2.85.1

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.
@@ -49071,15 +49071,21 @@ function interpolate_bicubic(t, a, b, c, d) {
49071
49071
  function computeStridedIntegerArrayHash(
49072
49072
  array, offset, length, stride
49073
49073
  ) {
49074
- let result = length;
49074
+ let hash = length;
49075
49075
 
49076
49076
  for (let i = offset; i < length; i += stride) {
49077
- const value = array[i];
49077
+ const value = array[i] >>> 0; //force int32
49078
49078
 
49079
- result = ((result * 31) + value) | 0;
49079
+ /**
49080
+ * Simple hashing scheme, multiplying existing hash by a prime and adding next value
49081
+ * (h<<5) - h === h*31
49082
+ * @type {number}
49083
+ */
49084
+ hash = ((hash << 5) - hash) + value;
49080
49085
  }
49081
49086
 
49082
- return result;
49087
+ // force uint32
49088
+ return hash >>> 0;
49083
49089
  }
49084
49090
 
49085
49091
  function typedArrayConstructorByInstance(a) {
@@ -50478,22 +50484,7 @@ Vector1.one = Object.freeze(new Vector1(1));
50478
50484
  * @param {number} length
50479
50485
  */
50480
50486
  function computeIntegerArrayHash(data, offset, length) {
50481
- const end = offset + length;
50482
-
50483
- let hash = length;
50484
-
50485
- for (let i = offset; i < end; i++) {
50486
- const singleValue = data[i];
50487
- /**
50488
- * Simple hashing scheme, multiplying existing hash by a prime and adding next value
50489
- * (h<<5) - h === h*31
50490
- * @type {number}
50491
- */
50492
- hash = ((hash << 5) - hash) + singleValue;
50493
- hash |= 0; // Convert to 32bit integer
50494
- }
50495
-
50496
- return hash;
50487
+ return computeStridedIntegerArrayHash(data, offset, length, 1);
50497
50488
  }
50498
50489
 
50499
50490
  /**
@@ -61166,6 +61157,7 @@ function arrayIndexByEquality(array, element, equals) {
61166
61157
 
61167
61158
  /**
61168
61159
  * Compute a diff between two arrays, result is a 3 way split between common items, unique items in `a` array and unique items in `b` array
61160
+ * @see prefer to use {@link arraySetSortingDiff}, as it's much faster, especially for large sets
61169
61161
  * @template T
61170
61162
  * @param {T[]} a
61171
61163
  * @param {T[]} b
@@ -91082,7 +91074,21 @@ class StaticKnowledgeDatabase {
91082
91074
  * @private
91083
91075
  */
91084
91076
  __specs = [];
91085
-
91077
+
91078
+ /**
91079
+ *
91080
+ * @type {boolean}
91081
+ */
91082
+ #validation_enabled = false;
91083
+
91084
+ /**
91085
+ *
91086
+ * @param {boolean} v
91087
+ */
91088
+ set validation_enabled(v) {
91089
+ this.#validation_enabled = v;
91090
+ }
91091
+
91086
91092
 
91087
91093
  /**
91088
91094
  * Reset database, drop all table data
@@ -91325,7 +91331,7 @@ class StaticKnowledgeDatabase {
91325
91331
  return Promise.all(promises).then(() => {
91326
91332
  let p = this.link(am, executor);
91327
91333
 
91328
- if (!ENV_PRODUCTION) {
91334
+ if (this.#validation_enabled) {
91329
91335
  p = p.then(() => this.validate(executor));
91330
91336
  }
91331
91337
 
@@ -103172,14 +103178,16 @@ class Engine {
103172
103178
  *
103173
103179
  * @param {EnginePlatform} platform
103174
103180
  * @param {EntityManager} [entityManager]
103175
- * @param enableGraphics
103176
- * @param enableAudio
103181
+ * @param {boolean} [enableGraphics]
103182
+ * @param {boolean} [enableAudio]
103183
+ * @param {boolean} [validation]
103177
103184
  * @constructor
103178
103185
  */
103179
103186
  constructor(platform, {
103180
103187
  entityManager,
103181
103188
  enableGraphics = true,
103182
- enableAudio = true
103189
+ enableAudio = true,
103190
+ validation = true
103183
103191
  } = {}) {
103184
103192
 
103185
103193
  /**
@@ -103193,6 +103201,7 @@ class Engine {
103193
103201
  * @type {StaticKnowledgeDatabase}
103194
103202
  */
103195
103203
  this.staticKnowledge = new StaticKnowledgeDatabase();
103204
+ this.staticKnowledge.validation_enabled = validation;
103196
103205
 
103197
103206
  /**
103198
103207
  *
@@ -103586,7 +103595,7 @@ class Engine {
103586
103595
  requestAnimationFrame(this.#animation_frame);
103587
103596
 
103588
103597
  //start simulation
103589
- this.ticker.start({maxTimeout: 200});
103598
+ this.ticker.start({ maxTimeout: 200 });
103590
103599
  //self.uiController.init(self);
103591
103600
 
103592
103601
  //load options
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.84.11",
8
+ "version": "2.85.1",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -148,16 +148,17 @@ export class LoadingCache {
148
148
 
149
149
  this.#internal.put(key, record);
150
150
 
151
- promise.then((value) => {
152
- // re-score value based on actual data
153
- record.weight = this.#value_weigher(value);
154
- this.#internal.updateElementWeight(key);
155
- });
156
-
157
- promise.catch(() => {
158
- // mark as failure
159
- record.failed = true;
160
- });
151
+ promise.then(
152
+ (value) => {
153
+ // re-score value based on actual data
154
+ record.weight = this.#value_weigher(value);
155
+ this.#internal.updateElementWeight(key);
156
+ },
157
+ () => {
158
+ // mark as failure
159
+ record.failed = true;
160
+ }
161
+ );
161
162
 
162
163
  return record;
163
164
  }
@@ -1,26 +1,27 @@
1
- import { delay } from "../process/delay.js";
2
1
  import { LoadingCache } from "./LoadingCache.js";
3
2
 
4
- test("successful load", async () => {
3
+ jest.useFakeTimers();
4
+
5
+ test("successful load", () => {
5
6
  const cache = new LoadingCache({
6
7
  async load(key) {
7
8
  return 17;
8
9
  }
9
10
  });
10
11
 
11
- expect(await cache.get(1)).toEqual(17);
12
+ expect( cache.get(1)).resolves.toEqual(17);
12
13
  });
13
14
 
14
- test("when loader throws an exception, we should get a failed promise", async () => {
15
+ test("when loader throws an exception, we should get a failed promise", () => {
15
16
  const cache = new LoadingCache({
16
17
  load(key) {
17
- throw 1;
18
+ throw "Designed Thrown Thing";
18
19
  }
19
20
  });
20
21
 
21
22
  const promise = cache.get("a");
22
23
 
23
- await expect(promise).rejects.toEqual(1);
24
+ expect(promise).rejects.toEqual("Designed Thrown Thing");
24
25
  });
25
26
 
26
27
  test("record reuse", async () => {
@@ -30,8 +31,8 @@ test("record reuse", async () => {
30
31
  load
31
32
  });
32
33
 
33
- expect(await cache.get(1)).toEqual(17);
34
- expect(await cache.get(1)).toEqual(17);
34
+ await expect(cache.get(1)).resolves.toEqual(17);
35
+ await expect(cache.get(1)).resolves.toEqual(17);
35
36
 
36
37
  expect(load).toHaveBeenCalledTimes(1);
37
38
  });
@@ -44,47 +45,23 @@ test("timeout reload reuse", async () => {
44
45
 
45
46
  const cache = new LoadingCache({
46
47
  load,
47
- timeToLive: 0.0000001
48
+ timeToLive: 0.00000001
48
49
  });
49
50
 
50
51
  const request_1 = await cache.get(1);
51
52
  expect(request_1).toEqual(11);
52
53
 
53
- await delay(2);
54
+ jest.advanceTimersByTime(1);
54
55
 
55
56
  const request_2 = await cache.get(1);
56
57
  expect(request_2).toEqual(5);
57
58
 
58
- await delay(2);
59
+ jest.advanceTimersByTime(1);
59
60
 
60
61
  const request_3 = await cache.get(1);
61
62
  expect(request_3).toEqual(3);
62
63
  });
63
64
 
64
- test("insert element directly", async () => {
65
-
66
- const cache = new LoadingCache({
67
- load: async () => 3
68
- });
69
-
70
- cache.put("x", 1);
71
-
72
- expect(await cache.get("x")).toEqual(1);
73
- });
74
-
75
- test("clear", async () => {
76
-
77
- const cache = new LoadingCache({
78
- load: async () => 3
79
- });
80
-
81
- cache.put("x", 1);
82
-
83
- cache.clear();
84
-
85
- expect(await cache.get("x")).toEqual(3);
86
- });
87
-
88
65
  test("eviction", async () => {
89
66
 
90
67
  /**
@@ -111,11 +88,33 @@ test("eviction", async () => {
111
88
 
112
89
  await cache.get(4);
113
90
 
114
- await delay(1);
115
-
116
91
  expect(cache.contains(1)).toBe(false);
117
92
  expect(cache.contains(2)).toBe(true);
118
93
  expect(cache.contains(3)).toBe(true);
119
94
  expect(cache.contains(4)).toBe(true);
120
95
 
121
- });
96
+ });
97
+
98
+ test("insert element directly", async () => {
99
+
100
+ const cache = new LoadingCache({
101
+ load: async () => 3
102
+ });
103
+
104
+ cache.put("x", 1);
105
+
106
+ expect(await cache.get("x")).toEqual(1);
107
+ });
108
+
109
+ test("clear", async () => {
110
+
111
+ const cache = new LoadingCache({
112
+ load: async () => 3
113
+ });
114
+
115
+ cache.put("x", 1);
116
+
117
+ cache.clear();
118
+
119
+ expect(await cache.get("x")).toEqual(3);
120
+ });
@@ -5,6 +5,7 @@ import { arrayIndexByEquality } from "./arrayIndexByEquality.js";
5
5
 
6
6
  /**
7
7
  * Compute a diff between two arrays, result is a 3 way split between common items, unique items in `a` array and unique items in `b` array
8
+ * @see prefer to use {@link arraySetSortingDiff}, as it's much faster, especially for large sets
8
9
  * @template T
9
10
  * @param {T[]} a
10
11
  * @param {T[]} b
@@ -1,6 +1,6 @@
1
1
  import { assert } from "../../../assert.js";
2
- import { NodeInstance } from "../node/NodeInstance.js";
3
2
  import { abstractJSONDeserializer } from "../../../json/abstractJSONDeserializer.js";
3
+ import { NodeInstance } from "../node/NodeInstance.js";
4
4
  import { NodeRegistry } from "../node/NodeRegistry.js";
5
5
 
6
6
  /**
@@ -25,47 +25,73 @@ function nodeParametersFromJSON(node, json, deserializers) {
25
25
 
26
26
  /**
27
27
  *
28
- * @param {NodeGraph} graph
29
- * @param {{nodes:[], connections:[], descriptions:[]}} json
30
- * @param {NodeRegistry} [node_registry]
31
- * @param {Map<string, function>} [deserializers]
32
- * @param {boolean} [allow_node_id_collisions]
28
+ * @param {[]} j_descriptions
29
+ * @param {Map<string,function>} deserializers
30
+ * @param {NodeRegistry} node_registry
31
+ * @param {boolean} allow_node_id_collisions
32
+ * @returns {Promise<NodeDescription[]>}
33
33
  */
34
- export function deserializeNodeGraphFromJSON({
35
- graph,
36
- json,
37
- node_registry = new NodeRegistry(),
38
- deserializers = new Map(),
39
- allow_node_id_collisions = false
40
- }) {
41
-
42
- const j_nodes = json.nodes;
43
- const j_connections = json.connections;
44
- const j_descriptions = json.descriptions;
45
-
46
-
47
- assert.defined(j_nodes, 'json.nodes');
48
- assert.defined(j_connections, 'json.connections');
49
- assert.defined(j_descriptions, 'json.descriptions');
34
+ async function deserializeNodeDescriptors(j_descriptions, deserializers, node_registry, allow_node_id_collisions) {
35
+ /**
36
+ *
37
+ * @type {NodeDescription[]}
38
+ */
39
+ const result = [];
50
40
 
51
- graph.reset();
41
+ /**
42
+ *
43
+ * @type {{index:number, promise:Promise<NodeDescription>}[]}
44
+ */
45
+ const deferred = [];
52
46
 
53
47
  /**
54
48
  *
55
49
  * @type {NodeDescription[]}
56
50
  */
57
- const descriptions = [];
51
+ const deserialized = [];
58
52
 
59
- // parse node descriptions
60
- for (let i = 0; i < j_descriptions.length; i++) {
53
+
54
+ const node_description_count = j_descriptions.length;
55
+
56
+ // parse node result
57
+ for (let i = 0; i < node_description_count; i++) {
61
58
  const jDescription = j_descriptions[i];
62
59
 
63
- const loaded_node = abstractJSONDeserializer(jDescription, deserializers);
60
+ const result = abstractJSONDeserializer(jDescription, deserializers);
61
+
62
+ if (result instanceof Promise) {
63
+ deferred.push({
64
+ index: i,
65
+ promise: result
66
+ });
67
+ } else {
68
+ deserialized[i] = result;
69
+ }
70
+
71
+ }
72
+
73
+ if (deferred.length > 0) {
74
+ const resolved = await Promise.all(deferred.map(m => m.promise));
75
+
76
+ for (let i = 0; i < deferred.length; i++) {
77
+ const node_description = resolved[i];
78
+
79
+ const spec = deferred[i];
80
+
81
+ deserialized[spec.index] = node_description;
82
+ }
83
+ }
84
+
85
+ for (let i = 0; i < node_description_count; i++) {
86
+
87
+ const loaded_node = deserialized[i];
64
88
 
65
89
  if (
66
90
  typeof loaded_node !== "object"
67
91
  || loaded_node.isNodeDescription !== true
68
92
  ) {
93
+ const jDescription = j_descriptions[i];
94
+
69
95
  throw new Error(`Deserialized object was expected to be a NodeDescription, instead got something else. Source JSON[${i}]: ${jDescription}`);
70
96
  }
71
97
 
@@ -73,7 +99,7 @@ export function deserializeNodeGraphFromJSON({
73
99
 
74
100
  if (existing_node === undefined) {
75
101
 
76
- descriptions[i] = loaded_node;
102
+ result[i] = loaded_node;
77
103
 
78
104
  // make sure to register the node
79
105
  node_registry.addNode(loaded_node);
@@ -85,7 +111,7 @@ export function deserializeNodeGraphFromJSON({
85
111
  // collision exists
86
112
 
87
113
  if (allow_node_id_collisions) {
88
- descriptions[i] = loaded_node;
114
+ result[i] = loaded_node;
89
115
  } else {
90
116
  // illegal collision
91
117
  throw new Error(`Loaded node does not match the one in the registry. Loaded: ${loaded_node}, Existing: ${existing_node}`);
@@ -94,11 +120,45 @@ export function deserializeNodeGraphFromJSON({
94
120
  } else {
95
121
 
96
122
  // re-use node from registry
97
- descriptions[i] = existing_node;
123
+ result[i] = existing_node;
98
124
  }
99
125
  }
100
-
101
126
  }
127
+ return result;
128
+ }
129
+
130
+ /**
131
+ *
132
+ * @param {NodeGraph} graph
133
+ * @param {{nodes:[], connections:[], descriptions:[]}} json
134
+ * @param {NodeRegistry} [node_registry]
135
+ * @param {Map<string, function>} [deserializers]
136
+ * @param {boolean} [allow_node_id_collisions]
137
+ */
138
+ export async function deserializeNodeGraphFromJSON({
139
+ graph,
140
+ json,
141
+ node_registry = new NodeRegistry(),
142
+ deserializers = new Map(),
143
+ allow_node_id_collisions = false
144
+ }) {
145
+
146
+ const j_nodes = json.nodes;
147
+ const j_connections = json.connections;
148
+ const j_descriptions = json.descriptions;
149
+
150
+ assert.defined(j_nodes, 'json.nodes');
151
+ assert.defined(j_connections, 'json.connections');
152
+ assert.defined(j_descriptions, 'json.descriptions');
153
+
154
+ graph.reset();
155
+
156
+ const descriptions = await deserializeNodeDescriptors(
157
+ j_descriptions,
158
+ deserializers,
159
+ node_registry,
160
+ allow_node_id_collisions
161
+ );
102
162
 
103
163
  // parse nodes
104
164
  const node_count = j_nodes.length;
@@ -1,3 +1,5 @@
1
+ import { computeStridedIntegerArrayHash } from "./computeStridedIntegerArrayHash.js";
2
+
1
3
  /**
2
4
  *
3
5
  * @param {Uint8Array|number[]|ArrayLike<number>|IArguments} data
@@ -5,20 +7,5 @@
5
7
  * @param {number} length
6
8
  */
7
9
  export function computeIntegerArrayHash(data, offset, length) {
8
- const end = offset + length;
9
-
10
- let hash = length;
11
-
12
- for (let i = offset; i < end; i++) {
13
- const singleValue = data[i];
14
- /**
15
- * Simple hashing scheme, multiplying existing hash by a prime and adding next value
16
- * (h<<5) - h === h*31
17
- * @type {number}
18
- */
19
- hash = ((hash << 5) - hash) + singleValue;
20
- hash |= 0; // Convert to 32bit integer
21
- }
22
-
23
- return hash;
10
+ return computeStridedIntegerArrayHash(data, offset, length, 1);
24
11
  }
@@ -9,13 +9,19 @@
9
9
  export function computeStridedIntegerArrayHash(
10
10
  array, offset, length, stride
11
11
  ) {
12
- let result = length;
12
+ let hash = length;
13
13
 
14
14
  for (let i = offset; i < length; i += stride) {
15
- const value = array[i];
15
+ const value = array[i] >>> 0; //force int32
16
16
 
17
- result = ((result * 31) + value) | 0;
17
+ /**
18
+ * Simple hashing scheme, multiplying existing hash by a prime and adding next value
19
+ * (h<<5) - h === h*31
20
+ * @type {number}
21
+ */
22
+ hash = ((hash << 5) - hash) + value;
18
23
  }
19
24
 
20
- return result;
25
+ // force uint32
26
+ return hash >>> 0;
21
27
  }
@@ -1,20 +1,21 @@
1
- import {EnginePlatform} from "./platform/EnginePlatform";
2
- import SceneManager from "./scene/SceneManager";
1
+ import ConcurrentExecutor from "../core/process/executor/ConcurrentExecutor";
2
+ import View from "../view/View";
3
+ import {AssetManager} from "./asset/AssetManager";
4
+ import {EntityManager} from "./ecs/EntityManager";
3
5
  import {GraphicsEngine} from "./graphics/GraphicsEngine";
4
- import SoundEngine from "./sound/SoundEngine";
5
6
  import KeyboardDevice from "./input/devices/KeyboardDevice";
6
7
  import {PointerDevice} from "./input/devices/PointerDevice";
7
- import {AssetManager} from "./asset/AssetManager";
8
- import {EntityManager} from "./ecs/EntityManager";
9
- import View from "../view/View";
10
- import Ticker from "./simulation/Ticker";
8
+ import {EnginePlatform} from "./platform/EnginePlatform";
11
9
  import {EnginePluginManager} from "./plugin/EnginePluginManager";
12
- import ConcurrentExecutor from "../core/process/executor/ConcurrentExecutor";
10
+ import SceneManager from "./scene/SceneManager";
11
+ import Ticker from "./simulation/Ticker";
12
+ import SoundEngine from "./sound/SoundEngine";
13
13
 
14
14
  export interface IEngineInitializationOptions {
15
15
  entityManager?: EntityManager,
16
16
  enableAudio?: boolean
17
17
  enableGraphics?: boolean
18
+ validation?:boolean
18
19
  }
19
20
 
20
21
  export default class Engine {
@@ -2,30 +2,30 @@
2
2
  *
3
3
  */
4
4
 
5
- import {PerspectiveCamera as ThreePerspectiveCamera} from 'three';
6
- import {assert} from "../core/assert.js";
5
+ import { PerspectiveCamera as ThreePerspectiveCamera } from 'three';
6
+ import { assert } from "../core/assert.js";
7
7
  import Vector1 from "../core/geom/Vector1.js";
8
- import {Localization} from "../core/localization/Localization.js";
9
- import {ModuleRegistry} from "../core/model/ModuleRegistry.js";
8
+ import { Localization } from "../core/localization/Localization.js";
9
+ import { ModuleRegistry } from "../core/model/ModuleRegistry.js";
10
10
  import ObservedBoolean from "../core/model/ObservedBoolean.js";
11
11
  import ConcurrentExecutor from '../core/process/executor/ConcurrentExecutor.js';
12
12
  import EmptyView from "../view/elements/EmptyView.js";
13
- import {ViewStack} from "../view/elements/navigation/ViewStack.js";
13
+ import { ViewStack } from "../view/elements/navigation/ViewStack.js";
14
14
 
15
- import {AssetManager} from './asset/AssetManager.js';
15
+ import { AssetManager } from './asset/AssetManager.js';
16
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';
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
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";
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";
29
29
  import SceneManager from "./scene/SceneManager.js";
30
30
  import Ticker from "./simulation/Ticker.js";
31
31
  import SoundEngine from './sound/SoundEngine.js';
@@ -52,14 +52,16 @@ class Engine {
52
52
  *
53
53
  * @param {EnginePlatform} platform
54
54
  * @param {EntityManager} [entityManager]
55
- * @param enableGraphics
56
- * @param enableAudio
55
+ * @param {boolean} [enableGraphics]
56
+ * @param {boolean} [enableAudio]
57
+ * @param {boolean} [validation]
57
58
  * @constructor
58
59
  */
59
60
  constructor(platform, {
60
61
  entityManager,
61
62
  enableGraphics = true,
62
- enableAudio = true
63
+ enableAudio = true,
64
+ validation = true
63
65
  } = {}) {
64
66
  assert.defined(platform, 'platform');
65
67
 
@@ -74,6 +76,7 @@ class Engine {
74
76
  * @type {StaticKnowledgeDatabase}
75
77
  */
76
78
  this.staticKnowledge = new StaticKnowledgeDatabase();
79
+ this.staticKnowledge.validation_enabled = validation;
77
80
 
78
81
  /**
79
82
  *
@@ -468,7 +471,7 @@ class Engine {
468
471
  requestAnimationFrame(this.#animation_frame);
469
472
 
470
473
  //start simulation
471
- this.ticker.start({maxTimeout: 200});
474
+ this.ticker.start({ maxTimeout: 200 });
472
475
  //self.uiController.init(self);
473
476
 
474
477
  //load options