@woosh/meep-engine 2.33.56 → 2.33.60

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 (49) hide show
  1. package/core/bvh2/aabb3/AABB3.js +4 -1
  2. package/core/bvh2/traversal/traverseBinaryNodeUsingVisitor.js +6 -6
  3. package/core/cache/Cache.js +7 -0
  4. package/core/collection/array/fastArrayEquals.js +17 -0
  5. package/core/collection/array/typed/is_typed_array_equals.js +58 -0
  6. package/core/collection/map/AbstractAsyncMap.js +30 -0
  7. package/core/collection/map/AsyncMapWrapper.js +16 -0
  8. package/core/collection/map/AsyncRemoteHashMap.js +358 -0
  9. package/core/collection/map/CachedAsyncMap.js +34 -0
  10. package/core/geom/Vector4.js +5 -5
  11. package/engine/animation/removeEntityGenericEffect.js +22 -31
  12. package/engine/asset/Asset.js +0 -45
  13. package/engine/asset/AssetDescription.js +51 -0
  14. package/engine/asset/AssetManager.d.ts +7 -0
  15. package/engine/asset/AssetManager.js +98 -2
  16. package/engine/asset/AssetTransformer.d.ts +5 -0
  17. package/engine/asset/AssetTransformer.js +15 -0
  18. package/engine/asset/loaders/GLTFAssetLoader.js +27 -25
  19. package/engine/asset/loaders/material/computeImageBitmapEquality.js +2 -2
  20. package/engine/asset/loaders/material/computeTextureEquality.js +2 -2
  21. package/engine/ecs/gui/GUIElement.js +0 -106
  22. package/engine/ecs/gui/GUIElementSerializationAdapter.js +108 -0
  23. package/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +60 -45
  24. package/engine/ecs/storage/binary/BinaryClassUpgrader.js +1 -0
  25. package/engine/ecs/util/removeComponentsExcept.js +3 -3
  26. package/engine/graphics/GraphicsEngine.js +3 -3
  27. package/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +0 -1
  28. package/engine/graphics/ecs/camera/topdown/TopDownCameraController.spec.js +8 -0
  29. package/engine/graphics/ecs/mesh/Mesh.js +5 -5
  30. package/engine/graphics/ecs/mesh/MeshSystem.js +12 -20
  31. package/engine/graphics/ecs/path/PathDisplaySystem.d.ts +3 -1
  32. package/engine/graphics/ecs/trail2d/Trail2D.js +35 -1
  33. package/engine/graphics/ecs/trail2d/Trail2DSystem.js +26 -19
  34. package/engine/graphics/ecs/trail2d/makeGradientTrail.js +68 -0
  35. package/engine/graphics/micron/convert_three_object_to_micron.js +24 -7
  36. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +107 -4
  37. package/engine/graphics/micron/plugin/serialization/BufferGeometrySerializationAdapter.js +176 -0
  38. package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.d.ts +2 -0
  39. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -2
  40. package/engine/graphics/render/buffer/simple-fx/DepthLimitedBlur.js +2 -2
  41. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +1 -1
  42. package/engine/graphics/render/buffer/simple-fx/ao/SAOShader.js +9 -15
  43. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +2 -0
  44. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +3 -1
  45. package/engine/graphics/shadows/ShadowMapRenderer.js +10 -4
  46. package/engine/graphics/texture/sampler/Sampler2D.js +24 -45
  47. package/engine/intelligence/behavior/ecs/WaitForEventBehavior.js +3 -0
  48. package/engine/save/storage/IndexedDBStorage.js +8 -1
  49. package/package.json +1 -1
@@ -4,51 +4,6 @@
4
4
  * @param {string} type
5
5
  * @constructor
6
6
  */
7
- import { assert } from "../../core/assert.js";
8
- import { computeStringHash } from "../../core/primitives/strings/computeStringHash.js";
9
- import { computeHashIntegerArray } from "../../core/collection/array/computeHashIntegerArray.js";
10
-
11
- export class AssetDescription {
12
- /**
13
- *
14
- * @param {string} path
15
- * @param {string} type
16
- * @constructor
17
- */
18
- constructor(path, type) {
19
- assert.typeOf(path, 'string', 'path');
20
- assert.typeOf(type, 'string', 'type');
21
-
22
- /**
23
- * @type {string}
24
- */
25
- this.path = path;
26
- /**
27
- * @type {string}
28
- */
29
- this.type = type;
30
- }
31
-
32
- /**
33
- *
34
- * @param {AssetDescription} other
35
- * @returns {boolean}
36
- */
37
- equals(other) {
38
- return this.path === other.path && this.type === other.type;
39
- }
40
-
41
- /**
42
- *
43
- * @returns {number}
44
- */
45
- hash() {
46
- return computeHashIntegerArray(
47
- computeStringHash(this.path),
48
- computeStringHash(this.type)
49
- );
50
- }
51
- }
52
7
 
53
8
 
54
9
  export class Asset {
@@ -0,0 +1,51 @@
1
+ import { assert } from "../../core/assert.js";
2
+ import { computeHashIntegerArray } from "../../core/collection/array/computeHashIntegerArray.js";
3
+ import { computeStringHash } from "../../core/primitives/strings/computeStringHash.js";
4
+
5
+ export class AssetDescription {
6
+ /**
7
+ *
8
+ * @param {string} path
9
+ * @param {string} type
10
+ * @constructor
11
+ */
12
+ constructor(path, type) {
13
+ assert.isString(path, 'path');
14
+ assert.isString(type, 'type');
15
+
16
+ /**
17
+ * @type {string}
18
+ */
19
+ this.path = path;
20
+ /**
21
+ * @type {string}
22
+ */
23
+ this.type = type;
24
+ }
25
+
26
+ /**
27
+ *
28
+ * @param {AssetDescription} other
29
+ * @returns {boolean}
30
+ */
31
+ equals(other) {
32
+ return this.path === other.path
33
+ && this.type === other.type
34
+ ;
35
+ }
36
+
37
+ /**
38
+ *
39
+ * @returns {number}
40
+ */
41
+ hash() {
42
+ return computeHashIntegerArray(
43
+ computeStringHash(this.path),
44
+ computeStringHash(this.type)
45
+ );
46
+ }
47
+
48
+ toString() {
49
+ return `{ type: '${this.type}', path: '${this.path}' }`;
50
+ }
51
+ }
@@ -1,6 +1,7 @@
1
1
  import {AssetLoader} from "./loaders/AssetLoader";
2
2
  import {Asset} from "./Asset";
3
3
  import {CrossOriginConfig} from "./CORS/CrossOriginConfig";
4
+ import {AssetTransformer} from "./AssetTransformer";
4
5
 
5
6
  export class AssetManager {
6
7
  public readonly crossOriginConfig: CrossOriginConfig
@@ -12,4 +13,10 @@ export class AssetManager {
12
13
  public clear(): void
13
14
 
14
15
  public registerLoader<T>(type: string, loader: AssetLoader<T>): Promise<void>
16
+
17
+ public unregisterLoader(type: string): Promise<void>
18
+
19
+ public registerTransformer<T extends Asset<X>, X = any>(type: string, transformer: AssetTransformer<T>): void
20
+
21
+ public unregisterTransformer<T extends Asset<X>, X = any>(type: string, transformer: AssetTransformer<T>): boolean
15
22
  }
@@ -5,12 +5,13 @@
5
5
 
6
6
  import BoundedValue from "../../core/model/BoundedValue.js";
7
7
  import { ObservedMap } from "../../core/collection/ObservedMap.js";
8
- import { AssetDescription } from "./Asset.js";
9
8
  import { HashMap } from "../../core/collection/HashMap.js";
10
9
  import { extractAssetListFromManager } from "./preloader/extractAssetListFromManager.js";
11
10
  import { assert } from "../../core/assert.js";
12
11
  import { HashSet } from "../../core/collection/HashSet.js";
13
12
  import { CrossOriginConfig } from "./CORS/CrossOriginConfig.js";
13
+ import { array_remove_element } from "../../core/collection/array/array_remove_element.js";
14
+ import { AssetDescription } from "./AssetDescription.js";
14
15
 
15
16
  /**
16
17
  *
@@ -62,6 +63,13 @@ function AssetManager(engine) {
62
63
  */
63
64
  this.loaders = {};
64
65
 
66
+ /**
67
+ * After asset is loaded, a chain of transforms can be applied to it, these are registered here
68
+ * Transformers are executed in the order in which they are added
69
+ * @type {Object<AssetTransformer[]>}
70
+ */
71
+ this.transformers = {};
72
+
65
73
  /**
66
74
  * Named links to specific assets. Useful to later re-mapping assets and having meaningful names for them
67
75
  * @type {Map<string, AssetDescription>}
@@ -209,7 +217,30 @@ AssetManager.prototype.submitRequest = function (path, type, request) {
209
217
  const assets = this.assets;
210
218
  const failures = this.failures;
211
219
 
212
- function success(asset) {
220
+ /**
221
+ *
222
+ * @param {Asset} loaded_asset
223
+ */
224
+ const success = async (loaded_asset) => {
225
+ let asset = loaded_asset;
226
+
227
+ // apply transform chain
228
+ const transformers = this.transformers[type];
229
+ if (transformers !== undefined) {
230
+ const transformer_count = transformers.length;
231
+ for (let i = 0; i < transformer_count; i++) {
232
+ const transformer = transformers[i];
233
+
234
+ const transformed_asset = await transformer.transform(asset);
235
+
236
+ if (typeof transformed_asset !== "object") {
237
+ console.error('Transformer produced invalid result. Ignoring result.', transformer, assetDescription);
238
+ } else {
239
+ asset = transformed_asset;
240
+ }
241
+ }
242
+ }
243
+
213
244
  //link asset description
214
245
  asset.description = assetDescription;
215
246
 
@@ -298,6 +329,71 @@ AssetManager.prototype.getLoaderByType = function (type) {
298
329
  return this.loaders[type];
299
330
  };
300
331
 
332
+ /**
333
+ *
334
+ * @param {string} type
335
+ * @return {AssetDescription[]}
336
+ * @private
337
+ */
338
+ AssetManager.prototype.__getLoadedAssetDescriptorsByType = function (type) {
339
+ const loaded_assets = Array.from(this.assets.keys());
340
+ return loaded_assets.filter(t => t.type === type);
341
+ }
342
+
343
+ /**
344
+ * @template T
345
+ * @param {string} type
346
+ * @param {AssetTransformer<T>} transformer
347
+ */
348
+ AssetManager.prototype.registerTransformer = function (type, transformer) {
349
+ let transformers = this.transformers[type];
350
+
351
+ if (transformers === undefined) {
352
+ transformers = [];
353
+
354
+ this.transformers[type] = transformers;
355
+ }
356
+
357
+ transformers.push(transformer);
358
+
359
+ // check for loaded assets
360
+ const matching_assets = this.__getLoadedAssetDescriptorsByType(type);
361
+
362
+ if (matching_assets.length > 0) {
363
+ console.warn(`Following assets of matching type '${type}' are already loaded and transform is not applied to them:\n\t${matching_assets.join('\n\t')}`);
364
+ }
365
+
366
+ };
367
+
368
+ /**
369
+ * @template T
370
+ * @param {string} type
371
+ * @param {AssetTransformer<T>} transformer
372
+ */
373
+ AssetManager.prototype.unregisterTransformer = function (type, transformer) {
374
+
375
+ const transformers = this.transformers[type];
376
+
377
+ if (transformers === undefined) {
378
+ // not found
379
+ return false;
380
+ }
381
+
382
+ if (!array_remove_element(transformers, 0, transformers.length, transformer)) {
383
+ // not found
384
+ return false;
385
+ }
386
+
387
+ // check for loaded assets
388
+ const matching_assets = this.__getLoadedAssetDescriptorsByType(type);
389
+
390
+ if (matching_assets.length > 0) {
391
+ console.warn(`Following assets of matching type '${type}' are already loaded and transform was probably already applied to them:\n\t${matching_assets.join('\n\t')}`);
392
+ }
393
+
394
+ return true;
395
+ }
396
+
301
397
  /**
302
398
  * @template T
303
399
  * @param {string} type
@@ -0,0 +1,5 @@
1
+ import {Asset} from "./Asset";
2
+
3
+ export class AssetTransformer<A extends Asset<T>, T = any> {
4
+ transform(source: A): Promise<A>
5
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Applies a transformation to an asset. Such as performing mesh simplification for example.
3
+ * Transformation is executed by the {@link AssetManager}
4
+ * @template {Asset<T>} A
5
+ * @template T
6
+ */
7
+ export class AssetTransformer {
8
+ /**
9
+ * @param {A} source
10
+ * @returns {A}
11
+ */
12
+ async transform(source) {
13
+ throw new Error('Not Implemented');
14
+ }
15
+ }
@@ -19,7 +19,6 @@ import { CrossOriginKind } from "../CORS/CrossOriginKind.js";
19
19
  import { computeObjectBoundingSphere } from "./gltf/computeObjectBoundingSphere.js";
20
20
  import { isMesh } from "./gltf/isMesh.js";
21
21
  import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
22
- import { convert_three_object_to_micron } from "../../graphics/micron/convert_three_object_to_micron.js";
23
22
  import { HashSet } from "../../../core/collection/HashSet.js";
24
23
  import { computeGeometryHash } from "./geometry/geometry/computeGeometryHash.js";
25
24
  import { computeGeometryEquality } from "./geometry/geometry/computeGeometryEquality.js";
@@ -173,11 +172,20 @@ export class GLTFAssetLoader extends AssetLoader {
173
172
  this.loader = loader;
174
173
 
175
174
  /**
176
- *
175
+ * Asset optimization flag
176
+ * Whether or not geometry de-duping should be done
177
177
  * @type {boolean}
178
178
  * @private
179
179
  */
180
- this.__enable_micron = true;
180
+ this.__enable_geometry_cache = false;
181
+
182
+ /**
183
+ * Asset optimization flag
184
+ * Whether or not texture de-duping should be done
185
+ * @type {boolean}
186
+ * @private
187
+ */
188
+ this.__enable_texture_cache = false;
181
189
 
182
190
  /**
183
191
  *
@@ -216,7 +224,7 @@ export class GLTFAssetLoader extends AssetLoader {
216
224
  * @param {boolean} v
217
225
  */
218
226
  set is_micron_enabled(v) {
219
- this.__enable_micron = v;
227
+ console.warn('Deprecated. Handled by the MicronRenderPlugin. Remove usage, no further action required');
220
228
  }
221
229
 
222
230
  /**
@@ -224,7 +232,7 @@ export class GLTFAssetLoader extends AssetLoader {
224
232
  * @returns {boolean}
225
233
  */
226
234
  get is_micron_enabled() {
227
- return this.__enable_micron;
235
+ throw new Error('Deprecated. Handled by the MicronRenderPlugin. Remove usage, no further action required. To check for presence of micron, check plugins instead.');
228
236
  }
229
237
 
230
238
  async link(assetManager, engine) {
@@ -275,14 +283,15 @@ export class GLTFAssetLoader extends AssetLoader {
275
283
  alphaTest: object.material.alphaTest
276
284
  });
277
285
 
278
- object.customDepthMaterial = materialCache.acquire(depthMaterial);
286
+ if (this.__enable_texture_cache) {
287
+ object.customDepthMaterial = materialCache.acquire(depthMaterial);
288
+ }
279
289
  }
280
290
  }
281
291
 
282
292
 
283
293
  load(path, success, failure, progress) {
284
294
  const loader = this.loader;
285
- const geometry_cache = this.__geometry_cache;
286
295
  const texture_cache = this.__texture_cache;
287
296
 
288
297
 
@@ -290,19 +299,24 @@ export class GLTFAssetLoader extends AssetLoader {
290
299
  *
291
300
  * @param {THREE.Mesh|THREE.SkinnedMesh} mesh
292
301
  */
293
- async function processMesh(mesh) {
302
+ const processMesh = async (mesh) => {
294
303
  let geometry = mesh.geometry;
295
304
 
296
305
  if (geometry === undefined) {
297
306
  throw new Error(`No geometry found`);
298
307
  }
299
308
 
300
- // replace geometry
301
- geometry = geometry_cache.ensure(geometry);
302
- mesh.geometry = geometry;
309
+ if (this.__enable_geometry_cache) {
310
+ // replace geometry
311
+ geometry = this.__geometry_cache.ensure(geometry);
312
+ mesh.geometry = geometry;
313
+ }
314
+
303
315
 
304
- // replace textures from cache
305
- replace_material_textures_from_cache(mesh.material, texture_cache);
316
+ if (this.__enable_texture_cache) {
317
+ // replace textures from cache
318
+ replace_material_textures_from_cache(mesh.material, texture_cache);
319
+ }
306
320
 
307
321
  const isSkinned = mesh.isSkinnedMesh === true;
308
322
 
@@ -431,18 +445,6 @@ export class GLTFAssetLoader extends AssetLoader {
431
445
  asset.animations = animations;
432
446
  }
433
447
 
434
- // build micron mesh
435
- if (
436
- this.__enable_micron
437
- && (asset.animations === undefined || asset.animations.length === 0)
438
- ) {
439
- // TODO deal with animations
440
- const micron_root = await convert_three_object_to_micron(root.clone());
441
- micron_root.boundingSphere = root.boundingSphere;
442
-
443
- asset.micron = micron_root;
444
- }
445
-
446
448
  success(asset);
447
449
  }, function (xhr) {
448
450
  //dispatch progress callback
@@ -1,7 +1,7 @@
1
1
  import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
2
2
  import { assert } from "../../../../core/assert.js";
3
- import { isArrayEqualStrict } from "../../../../core/collection/array/isArrayEqualStrict.js";
4
3
  import { bitmap2sampler_gl } from "./bitmap2sampler_gl.js";
4
+ import { fastArrayEquals } from "../../../../core/collection/array/fastArrayEquals.js";
5
5
 
6
6
  /**
7
7
  *
@@ -114,5 +114,5 @@ export function computeImageBitmapEquality(a, b) {
114
114
 
115
115
  const b_s = obtainSampler(b, ctx);
116
116
 
117
- return isArrayEqualStrict(a_s.data, b_s.data);
117
+ return fastArrayEquals(a_s.data, b_s.data);
118
118
  }
@@ -1,5 +1,5 @@
1
1
  import { computeImageBitmapEquality } from "./computeImageBitmapEquality.js";
2
- import { isArrayEqualStrict } from "../../../../core/collection/array/isArrayEqualStrict.js";
2
+ import { fastArrayEquals } from "../../../../core/collection/array/fastArrayEquals.js";
3
3
 
4
4
  //
5
5
 
@@ -184,5 +184,5 @@ function textureMipmapEqual(a, b) {
184
184
  return true;
185
185
  }
186
186
 
187
- return isArrayEqualStrict(aData, bData);
187
+ return fastArrayEquals(aData, bData);
188
188
  }
@@ -3,7 +3,6 @@
3
3
  */
4
4
  import Vector2 from '../../../core/geom/Vector2.js';
5
5
  import ObservedBoolean from "../../../core/model/ObservedBoolean.js";
6
- import { BinaryClassSerializationAdapter } from "../storage/binary/BinaryClassSerializationAdapter.js";
7
6
  import { COMPONENT_SERIALIZATION_TRANSIENT_FIELD } from "../storage/COMPONENT_SERIALIZATION_TRANSIENT_FIELD.js";
8
7
  import { assert } from "../../../core/assert.js";
9
8
  import { objectDeepEquals } from "../../../core/model/object/objectDeepEquals.js";
@@ -238,108 +237,3 @@ GUIElement.serializable = true;
238
237
  export default GUIElement;
239
238
 
240
239
 
241
- export class GUIElementSerializationAdapter extends BinaryClassSerializationAdapter {
242
- constructor() {
243
- super();
244
-
245
- this.klass = GUIElement;
246
- this.version = 0;
247
- }
248
-
249
- /**
250
- *
251
- * @param {BinaryBuffer} buffer
252
- * @param {GUIElement} value
253
- */
254
- serialize(buffer, value) {
255
-
256
- if (!value.getFlag(GUIElementFlag.Managed)) {
257
- throw new Error(`Expected 'Managed' flag to be set, instead it was cleared. Cannot serialize un-managed component`);
258
- }
259
-
260
- value.anchor.toBinaryBufferFloat32(buffer);
261
- buffer.writeUTF8String(value.group);
262
-
263
- buffer.writeUint8(value.visible.getValue() ? 1 : 0);
264
-
265
- buffer.writeUTF8String(value.klass);
266
- //write parameters
267
-
268
- const paramKeys = Object.keys(value.parameters);
269
-
270
- const numParamKeys = paramKeys.length;
271
- buffer.writeUintVar(numParamKeys);
272
-
273
- for (let i = 0; i < numParamKeys; i++) {
274
- const paramKey = paramKeys[i];
275
-
276
- buffer.writeUTF8String(paramKey);
277
-
278
- const parameter = value.parameters[paramKey];
279
-
280
- const paramType = typeof parameter;
281
-
282
- if (paramType === "number") {
283
- buffer.writeUint8(1);
284
-
285
- buffer.writeFloat64(parameter);
286
- } else if (paramType === "boolean") {
287
- buffer.writeUint8(2);
288
-
289
- buffer.writeUint8(parameter ? 1 : 0);
290
- } else if (paramType === "string") {
291
- buffer.writeUint8(3);
292
-
293
- buffer.writeUTF8String(parameter);
294
- } else {
295
- throw new TypeError(`Unsupported parameter type ${paramType}`);
296
- }
297
-
298
- }
299
- }
300
-
301
- /**
302
- *
303
- * @param {BinaryBuffer} buffer
304
- * @param {GUIElement} value
305
- */
306
- deserialize(buffer, value) {
307
- value.anchor.fromBinaryBufferFloat32(buffer);
308
-
309
- value.group = buffer.readUTF8String();
310
-
311
- value.visible.set(buffer.readUint8() !== 0);
312
-
313
- value.klass = buffer.readUTF8String();
314
-
315
- const numParamKeys = buffer.readUintVar();
316
-
317
- const params = {};
318
-
319
- for (let i = 0; i < numParamKeys; i++) {
320
- //read key
321
- const paramKey = buffer.readUTF8String();
322
-
323
- //read type flag
324
- const paramTypeHeader = buffer.readUint8();
325
-
326
- let paramValue;
327
- if (paramTypeHeader === 1) {
328
- //number
329
- paramValue = buffer.readFloat64();
330
- } else if (paramTypeHeader === 2) {
331
- //boolean
332
- paramValue = buffer.readUint8() !== 0;
333
- } else if (paramTypeHeader === 3) {
334
- //string
335
- paramValue = buffer.readUTF8String();
336
- } else {
337
- throw new TypeError(`Unknown type header value '${paramTypeHeader}' for parameter key '${paramKey}'`);
338
- }
339
-
340
- params[paramKey] = paramValue;
341
- }
342
-
343
- value.parameters = params;
344
- }
345
- }
@@ -0,0 +1,108 @@
1
+ import { BinaryClassSerializationAdapter } from "../storage/binary/BinaryClassSerializationAdapter.js";
2
+ import GUIElement, { GUIElementFlag } from "./GUIElement.js";
3
+
4
+ export class GUIElementSerializationAdapter extends BinaryClassSerializationAdapter {
5
+ constructor() {
6
+ super();
7
+
8
+ this.klass = GUIElement;
9
+ this.version = 0;
10
+ }
11
+
12
+ /**
13
+ *
14
+ * @param {BinaryBuffer} buffer
15
+ * @param {GUIElement} value
16
+ */
17
+ serialize(buffer, value) {
18
+
19
+ if (!value.getFlag(GUIElementFlag.Managed)) {
20
+ throw new Error(`Expected 'Managed' flag to be set, instead it was cleared. Cannot serialize un-managed component`);
21
+ }
22
+
23
+ value.anchor.toBinaryBufferFloat32(buffer);
24
+ buffer.writeUTF8String(value.group);
25
+
26
+ buffer.writeUint8(value.visible.getValue() ? 1 : 0);
27
+
28
+ buffer.writeUTF8String(value.klass);
29
+ //write parameters
30
+
31
+ const paramKeys = Object.keys(value.parameters);
32
+
33
+ const numParamKeys = paramKeys.length;
34
+ buffer.writeUintVar(numParamKeys);
35
+
36
+ for (let i = 0; i < numParamKeys; i++) {
37
+ const paramKey = paramKeys[i];
38
+
39
+ buffer.writeUTF8String(paramKey);
40
+
41
+ const parameter = value.parameters[paramKey];
42
+
43
+ const paramType = typeof parameter;
44
+
45
+ if (paramType === "number") {
46
+ buffer.writeUint8(1);
47
+
48
+ buffer.writeFloat64(parameter);
49
+ } else if (paramType === "boolean") {
50
+ buffer.writeUint8(2);
51
+
52
+ buffer.writeUint8(parameter ? 1 : 0);
53
+ } else if (paramType === "string") {
54
+ buffer.writeUint8(3);
55
+
56
+ buffer.writeUTF8String(parameter);
57
+ } else {
58
+ throw new TypeError(`Unsupported parameter type ${paramType}`);
59
+ }
60
+
61
+ }
62
+ }
63
+
64
+ /**
65
+ *
66
+ * @param {BinaryBuffer} buffer
67
+ * @param {GUIElement} value
68
+ */
69
+ deserialize(buffer, value) {
70
+ value.anchor.fromBinaryBufferFloat32(buffer);
71
+
72
+ value.group = buffer.readUTF8String();
73
+
74
+ value.visible.set(buffer.readUint8() !== 0);
75
+
76
+ value.klass = buffer.readUTF8String();
77
+
78
+ const numParamKeys = buffer.readUintVar();
79
+
80
+ const params = {};
81
+
82
+ for (let i = 0; i < numParamKeys; i++) {
83
+ //read key
84
+ const paramKey = buffer.readUTF8String();
85
+
86
+ //read type flag
87
+ const paramTypeHeader = buffer.readUint8();
88
+
89
+ let paramValue;
90
+ if (paramTypeHeader === 1) {
91
+ //number
92
+ paramValue = buffer.readFloat64();
93
+ } else if (paramTypeHeader === 2) {
94
+ //boolean
95
+ paramValue = buffer.readUint8() !== 0;
96
+ } else if (paramTypeHeader === 3) {
97
+ //string
98
+ paramValue = buffer.readUTF8String();
99
+ } else {
100
+ throw new TypeError(`Unknown type header value '${paramTypeHeader}' for parameter key '${paramKey}'`);
101
+ }
102
+
103
+ params[paramKey] = paramValue;
104
+ }
105
+
106
+ value.parameters = params;
107
+ }
108
+ }