@woosh/meep-engine 2.48.1 → 2.48.5

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 (75) hide show
  1. package/package.json +1 -1
  2. package/src/core/binary/32BitEncoder.js +11 -3
  3. package/src/core/binary/BinaryBuffer.js +80 -59
  4. package/src/core/binary/int32_to_binary_string.js +32 -7
  5. package/src/core/binary/to_half_float_uint16.js +6 -4
  6. package/src/core/bvh2/visual/convert_bvh_to_dot_format_string.js +1 -1
  7. package/src/core/collection/list/List.js +3 -0
  8. package/src/core/geom/3d/CircleMath.js +13 -2
  9. package/src/core/geom/3d/matrix/m4_make_translation.js +15 -0
  10. package/src/core/geom/3d/triangle/computeTrianglePlaneSide.js +4 -13
  11. package/src/core/geom/Vector3.spec.js +10 -0
  12. package/src/core/graph/convertGraphToDotString.js +13 -3
  13. package/src/core/graph/v2/Graph.js +17 -1
  14. package/src/core/graph/v2/NodeContainer.js +58 -0
  15. package/src/core/model/ModuleRegistry.js +44 -10
  16. package/src/core/model/ResourceAccessKind.js +11 -0
  17. package/src/core/model/ResourceAccessSpecification.js +41 -0
  18. package/src/engine/Engine.js +1 -1
  19. package/src/engine/ecs/EntityEventBinding.js +74 -0
  20. package/src/engine/ecs/EntityManager.js +143 -0
  21. package/src/engine/ecs/System.js +53 -5
  22. package/src/engine/ecs/animation/InverseKinematicsSystem.js +6 -0
  23. package/src/engine/ecs/attachment/AttachmentSystem.js +8 -0
  24. package/src/engine/ecs/dynamic_actions/DynamicActorSystem.js +5 -0
  25. package/src/engine/ecs/fow/FogOfWarRevealerSystem.js +7 -3
  26. package/src/engine/ecs/fow/FogOfWarSystem.js +6 -0
  27. package/src/engine/ecs/gui/GUIElementSystem.js +1 -1
  28. package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +8 -0
  29. package/src/engine/ecs/gui/position/ViewportPositionSystem.js +6 -0
  30. package/src/engine/ecs/speaker/VoiceSystem.js +13 -0
  31. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.js +451 -12
  32. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.spec.js +123 -0
  33. package/src/engine/ecs/system/computeSystemComponentDependencyGraph.js +71 -0
  34. package/src/engine/ecs/systems/RenderSystem.js +6 -0
  35. package/src/engine/ecs/terrain/ecs/Terrain.js +26 -44
  36. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +9 -0
  37. package/src/engine/ecs/terrain/tiles/TerrainTile.js +5 -0
  38. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +26 -6
  39. package/src/engine/ecs/tooltip/TooltipComponentSystem.js +7 -0
  40. package/src/engine/graphics/ecs/animation/animator/AnimationGraphSystem.js +6 -0
  41. package/src/engine/graphics/ecs/camera/CameraSystem.js +6 -0
  42. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +4 -0
  43. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +5 -0
  44. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraLanderSystem.js +6 -0
  45. package/src/engine/graphics/ecs/light/LightSystem.js +8 -0
  46. package/src/engine/graphics/ecs/mesh/MeshSystem.js +8 -1
  47. package/src/engine/graphics/ecs/path/PathDisplaySystem.js +7 -1
  48. package/src/engine/graphics/ecs/trail2d/Trail2DSystem.js +7 -0
  49. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +34 -7
  50. package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +6 -0
  51. package/src/engine/grid/systems/GridPosition2TransformSystem.js +6 -0
  52. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +6 -0
  53. package/src/engine/intelligence/behavior/Behavior.js +11 -0
  54. package/src/engine/intelligence/behavior/composite/CompositeBehavior.js +10 -4
  55. package/src/engine/intelligence/behavior/decorator/AbstractDecoratorBehavior.js +1 -0
  56. package/src/engine/intelligence/behavior/util/behavior_traverse_tree.js +8 -0
  57. package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +8 -0
  58. package/src/engine/network/RemoteController.js +60 -84
  59. package/src/engine/network/remoteEditor.js +108 -2
  60. package/src/engine/sound/SoundEngine.js +81 -79
  61. package/src/engine/sound/ecs/SoundControllerSystem.js +8 -0
  62. package/src/engine/sound/ecs/SoundListenerSystem.js +7 -0
  63. package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +42 -46
  64. package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +15 -2
  65. package/src/engine/sound/ecs/emitter/SoundTrack.js +137 -35
  66. package/src/engine/sound/ecs/emitter/SoundTrackFlags.js +17 -1
  67. package/src/engine/sound/ecs/emitter/SoundTrackNodes.js +2 -4
  68. package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.js +1 -2
  69. package/src/generation/theme/ThemeEngine.js +20 -3
  70. package/src/view/{elements/image → common}/HTMLElementCacheKey.js +5 -5
  71. package/src/view/elements/button/ButtonView.js +10 -2
  72. package/src/view/elements/image/ImageView.js +1 -1
  73. package/src/view/elements/video/VideoView.js +1 -1
  74. package/src/view/interaction/CommandButtonView.js +16 -153
  75. package/src/view/interaction/createInterfaceCommandButton.js +124 -0
@@ -1,48 +1,487 @@
1
+ import { assert } from "../../../../../core/assert.js";
2
+
3
+ const HEADER_TAG_NATIVE_CLASS = 0;
4
+ const HEADER_TAG_REF_SCHEMA = 1;
5
+ const HEADER_TAG_INLINE_SCHEMA = 2;
6
+
7
+ const HEADER_TAG_NULL = 4;
8
+ const HEADER_TAG_UNDEFINED = 5;
9
+ const HEADER_TAG_BOOLEAN_TRUE = 6;
10
+ const HEADER_TAG_BOOLEAN_FALSE = 7;
11
+ const HEADER_TAG_POSITIVE_INTEGER = 8;
12
+ const HEADER_TAG_NEGATIVE_INTEGER = 9;
13
+ const HEADER_TAG_FLOAT = 20;
14
+ const HEADER_TAG_STRING = 30;
15
+
16
+
17
+ class SchemaRecord {
18
+ address = -1
19
+ /**
20
+ *
21
+ * @type {Object|null}
22
+ */
23
+ schema = null
24
+ /**
25
+ *
26
+ * @type {string|null}
27
+ */
28
+ typeName = null
29
+
30
+ /**
31
+ *
32
+ * @type {{name:string}[]}
33
+ */
34
+ fields = [];
35
+
36
+ /**
37
+ *
38
+ * @param {Object} schema
39
+ */
40
+ fromSchema(schema) {
41
+ this.schema = schema;
42
+
43
+ this.fields.splice(0, this.fields.length);
44
+
45
+ for (const schemaKey in schema) {
46
+ this.fields.push({
47
+ name: schemaKey
48
+ });
49
+ }
50
+ }
51
+
52
+ buildSchema() {
53
+ const schema = {};
54
+
55
+ const fields = this.fields;
56
+ const field_count = fields.length;
57
+ for (let i = 0; i < field_count; i++) {
58
+ const field = fields[i];
59
+
60
+ schema[field.name] = {};
61
+ }
62
+
63
+ this.schema = schema;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Generate a schema from a value object
69
+ * @param {Object} object
70
+ * @returns
71
+ */
72
+ function autoSchema(object) {
73
+ const schema = {};
74
+ for (const objectKey in object) {
75
+ const field_value = object[objectKey];
76
+
77
+ let field_schema;
78
+
79
+ if (typeof field_value === "object") {
80
+ field_schema = autoSchema(field_value);
81
+ } else {
82
+ // no schema for primitives
83
+ field_schema = undefined;
84
+ }
85
+
86
+ schema[objectKey] = field_schema;
87
+ }
88
+
89
+ return schema;
90
+ }
91
+
92
+ class SchemaTable {
93
+ /**
94
+ *
95
+ * @type {Map<number, SchemaRecord>}
96
+ */
97
+ #address_map = new Map();
98
+ /**
99
+ *
100
+ * @type {Map<Object, SchemaRecord>}
101
+ */
102
+ #schema_map = new Map();
103
+
104
+
105
+ reset() {
106
+ this.#address_map.clear();
107
+ this.#schema_map.clear();
108
+ }
109
+
110
+ /**
111
+ *
112
+ * @param {number} address
113
+ * @returns {SchemaRecord|undefined}
114
+ */
115
+ getSchemaAt(address) {
116
+ return this.#address_map.get(address);
117
+ }
118
+
119
+ /**
120
+ *
121
+ * @param {Object} schema
122
+ * @returns {SchemaRecord}
123
+ */
124
+ getRecord(schema) {
125
+ return this.#schema_map.get(schema);
126
+ }
127
+
128
+ /**
129
+ *
130
+ * @param {Object} schema
131
+ * @returns {number} -1 if not found
132
+ */
133
+ getAddress(schema) {
134
+ const record = this.#schema_map.get(schema);
135
+
136
+ if (record === undefined) {
137
+ return -1;
138
+ }
139
+
140
+ return record.address;
141
+ }
142
+
143
+ /**
144
+ *
145
+ * @param {SchemaRecord} record
146
+ */
147
+ add(record) {
148
+ this.#schema_map.set(record.schema, record);
149
+ this.#address_map.set(record.address, record);
150
+ }
151
+ }
152
+
1
153
  export class BinaryObjectSerializationAdapter2 {
2
154
  /**
3
155
  *
4
156
  * @type {BinarySerializationRegistry|null}
5
157
  */
6
- #registry = null
158
+ #adapter_registry = null
159
+ /**
160
+ *
161
+ * @type {ModuleRegistry|null}
162
+ */
163
+ #class_registry = null
164
+
165
+ #schema_table = new SchemaTable();
166
+
167
+ set module_registry(v) {
168
+ this.#class_registry = v;
169
+ }
170
+
171
+ get module_registry() {
172
+ return this.#class_registry;
173
+ }
174
+
175
+ set adapter_registry(v) {
176
+ this.#adapter_registry = v;
177
+ }
178
+
179
+ get adapter_registry() {
180
+ return this.#adapter_registry;
181
+ }
182
+
183
+ reset() {
184
+ this.#schema_table.reset();
185
+ }
7
186
 
8
187
  /**
9
188
  *
10
189
  * @param {BinaryBuffer} buffer
11
- * @param {Object} object
12
190
  * @param {Object} schema
191
+ * @param {string} typeName
192
+ * @returns {SchemaRecord}
193
+ */
194
+ #writeSchema(buffer, schema, typeName) {
195
+ const address = buffer.position;
196
+
197
+ const record = new SchemaRecord();
198
+
199
+ record.typeName = typeName;
200
+ record.address = address;
201
+
202
+ record.fromSchema(schema);
203
+
204
+ // write type name
205
+ buffer.writeUTF8String(typeName);
206
+
207
+ const fields = record.fields;
208
+ const field_count = fields.length;
209
+
210
+ buffer.writeUintVar(field_count);
211
+
212
+ for (let i = 0; i < field_count; i++) {
213
+ // write field
214
+ const field = fields[i];
215
+
216
+ buffer.writeUTF8String(field.name);
217
+ }
218
+
219
+ this.#schema_table.add(record);
220
+
221
+ return record;
222
+ }
223
+
224
+ /**
225
+ *
226
+ * @param {BinaryBuffer} buffer
227
+ * @returns {SchemaRecord}
228
+ */
229
+ #readSchema(buffer) {
230
+ const address = buffer.position;
231
+
232
+ const record = new SchemaRecord();
233
+ record.address = address;
234
+
235
+ // read type name
236
+ const typeName = buffer.readUTF8String();
237
+
238
+ record.typeName = typeName;
239
+
240
+ const field_count = buffer.readUintVar();
241
+
242
+ for (let i = 0; i < field_count; i++) {
243
+ const field_name = buffer.readUTF8String();
244
+
245
+ record.fields[i] = {
246
+ name: field_name
247
+ };
248
+ }
249
+
250
+ record.buildSchema();
251
+
252
+ this.#schema_table.add(record);
253
+
254
+ return record;
255
+ }
256
+
257
+ /**
258
+ *
259
+ * @param {BinaryBuffer} buffer
260
+ * @param {number|string|boolean|null|undefined|object} object
261
+ * @returns {boolean}
262
+ */
263
+ #trySerializePrimitive(buffer, object) {
264
+ if (object === null) {
265
+ // special case
266
+ buffer.writeUint8(HEADER_TAG_NULL);
267
+ return true;
268
+ }
269
+
270
+ const typeOfValue = typeof object;
271
+
272
+ if (typeOfValue === "object") {
273
+ return false;
274
+ }
275
+
276
+
277
+ switch (typeOfValue) {
278
+ case "undefined":
279
+ buffer.writeUint8(HEADER_TAG_UNDEFINED);
280
+ break;
281
+ case "boolean":
282
+ buffer.writeUint8(object ? HEADER_TAG_BOOLEAN_TRUE : HEADER_TAG_BOOLEAN_FALSE);
283
+ break;
284
+ case "number":
285
+ if (Number.isInteger(object)) {
286
+ if (object >= 0) {
287
+ // positive integer
288
+ buffer.writeUint8(HEADER_TAG_POSITIVE_INTEGER);
289
+ buffer.writeUintVar(object);
290
+ } else {
291
+ // negative integer
292
+ buffer.writeUint8(HEADER_TAG_NEGATIVE_INTEGER);
293
+ buffer.writeUintVar(-object);
294
+ }
295
+ } else {
296
+ // float
297
+ buffer.writeUint8(HEADER_TAG_FLOAT);
298
+ buffer.writeFloat64(object);
299
+ }
300
+ break;
301
+ case "string":
302
+ buffer.writeUint8(HEADER_TAG_STRING);
303
+ buffer.writeUTF8String(object);
304
+ break;
305
+ default:
306
+ throw new TypeError(`Unsupported value type '${typeOfValue}'`);
307
+ }
308
+
309
+ return true;
310
+ }
311
+
312
+ /**
313
+ *
314
+ * @param {BinaryBuffer} buffer
315
+ * @param {Object} object
316
+ * @param {Object} [schema]
13
317
  */
14
318
  serialize(buffer, object, schema) {
15
- const typeName = object.constructor.typeName;
319
+ if (this.#trySerializePrimitive(buffer, object)) {
320
+ // was primitive, serialized
321
+ return;
322
+ }
323
+
324
+ const ctor = object.constructor;
325
+
326
+ const associatedNames = this.#class_registry.findNamesByModule(ctor);
16
327
 
17
- const nativeAdapter = this.#registry.getAdapter(typeName);
328
+ let typeName;
18
329
 
19
- // TODO write a header so we can reconstruct the serialization schema on the other side
330
+ if (associatedNames.length === 1) {
331
+ typeName = associatedNames[0];
332
+ } else {
333
+ // ambiguous, use type name from constructor
334
+ typeName = ctor.typeName
335
+ }
336
+
337
+ assert.isString(typeName, 'typeName');
338
+
339
+ const nativeAdapter = this.#adapter_registry.getAdapter(typeName);
340
+
341
+ const using_native_serializer = nativeAdapter !== undefined;
342
+
343
+ if (using_native_serializer) {
344
+
345
+ // write header indicating that native serializer is being used
346
+ buffer.writeUint8(HEADER_TAG_NATIVE_CLASS);
347
+
348
+ // name of the type
349
+ buffer.writeUTF8String(typeName);
20
350
 
21
- if (nativeAdapter !== undefined) {
22
351
  // serialize with native
23
352
  nativeAdapter.serialize(buffer, object);
24
353
  return;
25
354
  }
26
355
 
27
- for (const property in schema) {
28
356
 
29
- const field_schema = schema[property];
357
+ if (schema === undefined) {
358
+ // no schema specified, generate one
359
+ schema = autoSchema(object);
360
+ }
361
+
362
+
363
+ let record = this.#schema_table.getRecord(schema);
364
+
365
+ if (record === undefined) {
366
+ // no record
367
+
368
+ // indicating that the full schema follows
369
+ buffer.writeUint8(HEADER_TAG_INLINE_SCHEMA);
370
+
371
+ record = this.#writeSchema(buffer, schema, typeName);
372
+
373
+
374
+ } else {
375
+ buffer.writeUint8(HEADER_TAG_REF_SCHEMA);
376
+ // write address of schema
377
+ buffer.writeUintVar(record.address);
378
+ }
379
+
380
+
381
+ // write data according to schema
30
382
 
31
- const actual_value = object[field_schema];
383
+ const fields = record.fields;
384
+ const field_count = fields.length;
32
385
 
33
- this.serialize(buffer, actual_value, field_schema);
386
+ for (let i = 0; i < field_count; i++) {
387
+ const field = fields[i];
388
+
389
+ const field_name = field.name;
390
+
391
+ const actual_value = object[field_name];
392
+
393
+ this.serialize(buffer, actual_value, schema[field_name]);
34
394
  }
35
395
 
36
396
  }
37
397
 
38
398
  /**
39
399
  *
400
+ * @template T
40
401
  * @param {BinaryBuffer} buffer
41
- * @param {Object} object
402
+ * @param {number} tag
403
+ * @returns {T}
404
+ */
405
+ #deserializeObject(buffer, tag) {
406
+ let record;
407
+
408
+ if (tag === HEADER_TAG_INLINE_SCHEMA) {
409
+ // read full schema here
410
+ record = this.#readSchema(buffer);
411
+
412
+ } else if (tag === HEADER_TAG_REF_SCHEMA) {
413
+ // reference to the schema else-where
414
+ const schema_address = buffer.readUintVar();
415
+
416
+ record = this.#schema_table.getRecord(schema_address);
417
+ }
418
+
419
+ const typeName = record.typeName;
420
+
421
+ const Klass = this.#class_registry.get(typeName);
422
+
423
+ const object = new Klass();
424
+
425
+ const fields = record.fields;
426
+ const field_count = fields.length;
427
+
428
+ for (let i = 0; i < field_count; i++) {
429
+ const field = fields[i];
430
+
431
+ object[field.name] = this.deserialize(buffer);
432
+ }
433
+
434
+ return object;
435
+ }
436
+
437
+ /**
438
+ * @template T
439
+ * @param {BinaryBuffer} buffer
440
+ * @returns {T}
42
441
  */
43
- deserialize(buffer, object) {
442
+ deserialize(buffer) {
44
443
 
45
444
  // read header
445
+ const header = buffer.readUint8();
446
+
447
+ switch (header) {
448
+ case HEADER_TAG_NATIVE_CLASS:
449
+ // native serializer being used
450
+ const typeName = buffer.readUTF8String();
451
+
452
+ const adapter = this.#adapter_registry.getAdapter(typeName);
453
+
454
+ const Klass = this.#class_registry.get(typeName);
455
+
456
+ const object = new Klass();
457
+
458
+ adapter.deserialize(buffer, object);
459
+
460
+ return object;
461
+ case HEADER_TAG_INLINE_SCHEMA:
462
+ case HEADER_TAG_REF_SCHEMA:
463
+ return this.#deserializeObject(buffer, header);
464
+
465
+ case HEADER_TAG_NULL:
466
+ return null;
467
+ case HEADER_TAG_UNDEFINED:
468
+ return undefined;
469
+ case HEADER_TAG_BOOLEAN_TRUE:
470
+ return true;
471
+ case HEADER_TAG_BOOLEAN_FALSE:
472
+ return false;
473
+ case HEADER_TAG_POSITIVE_INTEGER:
474
+ return buffer.readUintVar();
475
+ case HEADER_TAG_NEGATIVE_INTEGER:
476
+ return -buffer.readUintVar();
477
+ case HEADER_TAG_FLOAT:
478
+ return buffer.readFloat64();
479
+ case HEADER_TAG_STRING:
480
+ return buffer.readUTF8String();
481
+ default:
482
+ throw new Error(`Unsupported tag '${header}'`);
483
+ }
484
+
46
485
 
47
486
  }
48
487
  }
@@ -0,0 +1,123 @@
1
+ import { BinaryObjectSerializationAdapter2 } from "./BinaryObjectSerializationAdapter2.js";
2
+ import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
3
+ import { BinarySerializationRegistry } from "../BinarySerializationRegistry.js";
4
+ import { ModuleRegistry } from "../../../../../core/model/ModuleRegistry.js";
5
+
6
+
7
+ /**
8
+ *
9
+ * @returns {BinaryObjectSerializationAdapter2}
10
+ */
11
+ function sampleAdapter() {
12
+
13
+ const adapter = new BinaryObjectSerializationAdapter2();
14
+
15
+ adapter.adapter_registry = new BinarySerializationRegistry();
16
+ adapter.module_registry = new ModuleRegistry();
17
+
18
+ adapter.module_registry.add('object', Object);
19
+
20
+ return adapter;
21
+ }
22
+
23
+ test("primitive value", () => {
24
+
25
+ const adapter = sampleAdapter();
26
+
27
+ const bin = new BinaryBuffer();
28
+
29
+ function check(expected) {
30
+ // rewind
31
+ bin.position = 0;
32
+
33
+ adapter.serialize(bin, expected);
34
+
35
+ // rewind
36
+ bin.position = 0;
37
+
38
+ const actual = adapter.deserialize(bin);
39
+
40
+ expect(actual).toEqual(expected);
41
+ }
42
+
43
+ check(0);
44
+ check(1);
45
+ check(-1);
46
+ check(42.1);
47
+ check(true);
48
+ check(false);
49
+ check("hello");
50
+ check(undefined);
51
+ check(null);
52
+ });
53
+
54
+ test("empty object", () => {
55
+
56
+ const adapter = sampleAdapter();
57
+
58
+ const bin = new BinaryBuffer();
59
+
60
+ adapter.serialize(bin, {});
61
+
62
+ // rewind
63
+ bin.position = 0;
64
+
65
+ const result = adapter.deserialize(bin);
66
+
67
+ expect(typeof result).toBe("object");
68
+ expect(Object.keys(result)).toEqual([]);
69
+ });
70
+
71
+ test("multi-key flat object with different primitive values", () => {
72
+
73
+ const adapter = sampleAdapter();
74
+
75
+ const bin = new BinaryBuffer();
76
+
77
+ const expected = {
78
+ "test": undefined,
79
+ "hello": null,
80
+ "zero": 0,
81
+ "negative integer": -1,
82
+ "unsigned integer": 1,
83
+ "float": 0.01,
84
+ "empty string": "",
85
+ "string": "hello kitty",
86
+ "utf-8": "Ḽơᶉëᶆ ȋṕšᶙṁ",
87
+ "boolean true": true,
88
+ "boolean false": false,
89
+ };
90
+
91
+ adapter.serialize(bin, expected);
92
+
93
+ // rewind
94
+ bin.position = 0;
95
+
96
+ const actual = adapter.deserialize(bin);
97
+
98
+ expect(typeof actual).toBe("object");
99
+ expect(actual).toEqual(expected);
100
+ });
101
+
102
+
103
+ test("nested objects", () => {
104
+
105
+ const adapter = sampleAdapter();
106
+ const bin = new BinaryBuffer();
107
+
108
+ const expected = {
109
+ second: {
110
+ value: "hello there Mr bear"
111
+ }
112
+ };
113
+
114
+ adapter.serialize(bin, expected);
115
+
116
+ // rewind
117
+ bin.position = 0;
118
+
119
+ const actual = adapter.deserialize(bin);
120
+
121
+ expect(typeof actual).toBe("object");
122
+ expect(actual).toEqual(expected);
123
+ });
@@ -0,0 +1,71 @@
1
+ import { Graph } from "../../../core/graph/v2/Graph.js";
2
+ import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
3
+ import { EdgeDirectionType } from "../../../core/graph/Edge.js";
4
+
5
+ /**
6
+ *
7
+ * @param {number} system_count
8
+ * @param {System[]} systems
9
+ * @return {Graph}
10
+ */
11
+ export function computeSystemComponentDependencyGraph(system_count, systems) {
12
+ const dependency_graph = new Graph();
13
+
14
+ for (let i = 0; i < system_count; i++) {
15
+ const system = systems[i];
16
+
17
+ const components = system.referenced_components;
18
+ const component_count = components.length;
19
+
20
+ // ensure that all components are registered
21
+ for (let j = 0; j < component_count; j++) {
22
+ const component = components[j];
23
+
24
+ dependency_graph.addNode(component)
25
+ }
26
+
27
+ for (let j = 0; j < component_count; j++) {
28
+ const component_a = components[j];
29
+
30
+ const access_a = system.getAccessForComponent(component_a);
31
+
32
+ if ((access_a & (ResourceAccessKind.Write | ResourceAccessKind.Create)) !== 0) {
33
+ // writing resource, create dependency on read resources
34
+
35
+
36
+ for (let k = 0; k < component_count; k++) {
37
+
38
+ if (j === k) {
39
+ // skip self
40
+ continue;
41
+ }
42
+
43
+ const component_b = components[k];
44
+
45
+ const access_b = system.getAccessForComponent(component_b);
46
+
47
+ if ((access_b & ResourceAccessKind.Read) !== 0) {
48
+ // read access
49
+
50
+ if (dependency_graph.getAnyDirectedEdge(component_a, component_b) === undefined) {
51
+
52
+ dependency_graph.createEdge(component_a, component_b, EdgeDirectionType.Forward);
53
+
54
+ }
55
+
56
+ }
57
+ }
58
+
59
+ }
60
+
61
+ }
62
+
63
+ }
64
+
65
+
66
+ // console.log("DEPENDENCY_GRAPH:", convertGraphToDotString({
67
+ // graph: dependency_graph, nodeToDot: (node) => `[label="${node.typeName}"]`
68
+ // }));
69
+
70
+ return dependency_graph;
71
+ }
@@ -9,6 +9,8 @@ import { RenderableFlags } from "../components/RenderableFlags.js";
9
9
  import { rootObject3DFastMatrixUpdate } from "../../graphics/ecs/mesh/rootObject3DFastMatrixUpdate.js";
10
10
  import { updateNodeByTransformAndBBB } from "../../graphics/ecs/mesh/updateNodeByTransformAndBBB.js";
11
11
  import { three_computeObjectBoundingBox } from "../../graphics/three/three_computeObjectBoundingBox.js";
12
+ import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js";
13
+ import { ResourceAccessKind } from "../../../core/model/ResourceAccessKind.js";
12
14
 
13
15
 
14
16
  /**
@@ -30,6 +32,10 @@ class RenderSystem extends System {
30
32
 
31
33
  this.dependencies = [Renderable, Transform];
32
34
 
35
+ this.components_used = [
36
+ ResourceAccessSpecification.from(Renderable, ResourceAccessKind.Read | ResourceAccessKind.Write)
37
+ ];
38
+
33
39
  this.entityData = [];
34
40
 
35
41
  /**