@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
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.48.1",
8
+ "version": "2.48.5",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1,11 +1,15 @@
1
+ import { FunctionCompiler } from "../function/FunctionCompiler.js";
2
+ import { assert } from "../assert.js";
3
+
1
4
  /**
2
5
  *
3
6
  * @param {number[]} bitCounts
4
7
  * @returns {{encode: function(...number):number, decode: function(value:number, result:number[]):void}}
5
8
  */
6
- import { FunctionCompiler } from "../function/FunctionCompiler.js";
7
-
8
9
  export function create32BitCodec(bitCounts) {
10
+ assert.isArray(bitCounts, 'bitCounts');
11
+ assert.lessThanOrEqual(bitCounts.length, 32, `at most 32 groups are supported (1 bit each), instead ${bitCounts} was requested`);
12
+
9
13
  const layout = [];
10
14
 
11
15
  const encoderFunctionBody = [];
@@ -15,10 +19,14 @@ export function create32BitCodec(bitCounts) {
15
19
 
16
20
  let offsetCursor = 0;
17
21
 
22
+ const group_count = bitCounts.length;
18
23
 
19
- for (let i = 0, numVariables = bitCounts.length; i < numVariables; i++) {
24
+ for (let i = 0, numVariables = group_count; i < numVariables; i++) {
20
25
  const size = bitCounts[i];
21
26
 
27
+ assert.isNonNegativeInteger(size, `size[${i}]`);
28
+ assert.greaterThan(size, 0, `size[${i}] bust be greater than 0, instead was ${size}`);
29
+
22
30
  const offset = offsetCursor;
23
31
 
24
32
  layout.push({ offset, size });
@@ -26,64 +26,70 @@ const MIN_GROWTH_STEP = 1024;
26
26
  */
27
27
  const MAX_SAFE_UINT_VAR = 2147483647;
28
28
 
29
+ /**
30
+ * @readonly
31
+ * @type {number}
32
+ */
33
+ const DEFAULT_INITIAL_SIZE = 1024;
34
+
35
+
36
+ /**
37
+ * Utility for reading/writing binary data
38
+ * Mostly useful for serialization/deserialization tasks
39
+ */
29
40
  export class BinaryBuffer {
41
+
30
42
  /**
31
43
  *
32
- * @constructor
33
- */
34
- constructor() {
35
- /**
36
- *
37
- * @type {EndianType|boolean}
38
- */
39
- this.endianness = EndianType.BigEndian;
40
-
41
- /**
42
- *
43
- * @type {number}
44
- */
45
- this.position = 0;
44
+ * @type {EndianType|boolean}
45
+ */
46
+ endianness = EndianType.BigEndian;
46
47
 
47
- /**
48
- *
49
- * @type {number}
50
- */
51
- this.length = 0;
52
-
53
- /**
54
- *
55
- * @type {number}
56
- */
57
- this.capacity = 0;
58
-
59
- /**
60
- *
61
- * @type {ArrayBuffer}
62
- * @private
63
- */
64
- this.data = new ArrayBuffer(0);
65
-
66
- /**
67
- *
68
- * @type {DataView}
69
- * @private
70
- */
71
- this.dataView = new DataView(this.data);
48
+ /**
49
+ *
50
+ * @type {number}
51
+ */
52
+ position = 0;
72
53
 
73
- /**
74
- *
75
- * @type {Uint8Array}
76
- * @private
77
- */
78
- this.__data_uint8 = new Uint8Array(0);
54
+ /**
55
+ * @deprecated
56
+ * @type {number}
57
+ */
58
+ length = 0;
79
59
 
80
- /**
81
- *
82
- * @type {number}
83
- * @private
84
- */
85
- this.__growFactor = 1.1;
86
- }
60
+ /**
61
+ *
62
+ * @type {number}
63
+ */
64
+ capacity = DEFAULT_INITIAL_SIZE;
65
+
66
+ /**
67
+ *
68
+ * @type {ArrayBuffer}
69
+ * @private
70
+ */
71
+ data = new ArrayBuffer(DEFAULT_INITIAL_SIZE);
72
+
73
+ /**
74
+ *
75
+ * @type {DataView}
76
+ * @private
77
+ */
78
+ dataView = new DataView(this.data);
79
+
80
+ /**
81
+ *
82
+ * @type {Uint8Array}
83
+ * @private
84
+ */
85
+ __data_uint8 = new Uint8Array(this.data);
86
+
87
+ /**
88
+ *
89
+ * @type {number}
90
+ * @private
91
+ */
92
+ __growFactor = 1.1;
87
93
 
88
94
  /**
89
95
  * Access raw underlying bytes attached to the buffer
@@ -94,21 +100,24 @@ export class BinaryBuffer {
94
100
  }
95
101
 
96
102
  /**
97
- * @param {ArrayBuffer} arrayBuffer
103
+ * @param {ArrayBuffer} data
98
104
  */
99
- fromArrayBuffer(arrayBuffer) {
100
- this.data = arrayBuffer;
101
- this.dataView = new DataView(arrayBuffer);
102
- this.__data_uint8 = new Uint8Array(arrayBuffer);
105
+ fromArrayBuffer(data) {
106
+ assert.defined(data, 'data');
107
+ assert.notNull(data, 'data');
103
108
 
104
- this.capacity = arrayBuffer.byteLength;
109
+ this.data = data;
110
+ this.dataView = new DataView(data);
111
+ this.__data_uint8 = new Uint8Array(data);
112
+
113
+ this.capacity = data.byteLength;
105
114
  //assume that all the data is useful
106
115
  this.length = this.capacity;
107
116
  this.position = 0;
108
117
  }
109
118
 
110
119
  /**
111
- *
120
+ * Set capacity to contain data only up to current position
112
121
  * @returns {BinaryBuffer}
113
122
  */
114
123
  trim() {
@@ -122,6 +131,12 @@ export class BinaryBuffer {
122
131
  * @param {number} capacity
123
132
  */
124
133
  setCapacity(capacity) {
134
+ assert.isNonNegativeInteger(capacity, 'capacity');
135
+
136
+ if (capacity < this.position) {
137
+ throw new Error(`Attempting to set capacity(=${capacity}) below current position(=${this.position})`);
138
+ }
139
+
125
140
  const oldData = this.__data_uint8;
126
141
  const newData = new Uint8Array(capacity);
127
142
 
@@ -1117,3 +1132,9 @@ export class BinaryBuffer {
1117
1132
  return temp;
1118
1133
  }
1119
1134
  }
1135
+
1136
+ /**
1137
+ * @readonly
1138
+ * @type {boolean}
1139
+ */
1140
+ BinaryBuffer.prototype.isBinaryBuffer = true;
@@ -1,3 +1,19 @@
1
+
2
+
3
+ const RX = /\B(?=(.{8})+(?!.))/g;
4
+
5
+ /**
6
+ * 2147483647
7
+ * @type {number}
8
+ */
9
+ const MAX_VALUE = 2 ** 31 - 1;
10
+
11
+ /**
12
+ * -2147483648
13
+ * @type {number}
14
+ */
15
+ const MIN_VALUE = -1 * (2 ** 31);
16
+
1
17
  /**
2
18
  * @see https://stackoverflow.com/questions/9939760/how-do-i-convert-an-integer-to-binary-in-javascript
3
19
  * @example 1024 -> "00000000 00000000 00000100 00000000"
@@ -7,12 +23,21 @@
7
23
  */
8
24
  export function int32_to_binary_string(nMask) {
9
25
  // nMask must be between -2147483648 and 2147483647
10
- if (nMask > 2 ** 31 - 1)
11
- throw "number too large. number shouldn't be > 2**31-1"; //added
12
- if (nMask < -1 * (2 ** 31))
13
- throw "number too far negative, number shouldn't be < 2**31" //added
14
- for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32;
15
- nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1) ;
16
- sMask = sMask.replace(/\B(?=(.{8})+(?!.))/g, " ") // added
26
+ if (nMask > MAX_VALUE) {
27
+ throw "number too large. number shouldn't be > 2**31-1";//added
28
+ }
29
+ if (nMask < MIN_VALUE) {
30
+ throw "number too far negative, number shouldn't be < 2**31"//added
31
+ }
32
+
33
+ let nFlag = 0, nShifted = nMask, sMask = '';
34
+
35
+ for (; nFlag < 32;
36
+ nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1
37
+ ) {
38
+ }
39
+
40
+ sMask = sMask.replace(RX, " ") // added
41
+
17
42
  return sMask;
18
43
  }
@@ -8,11 +8,13 @@ const _int32View = new Int32Array(_floatView.buffer);
8
8
  * @returns {number}
9
9
  */
10
10
  export function to_half_float_uint16(val) {
11
- if (val > 65504) {
11
+ let _val = val;
12
12
 
13
- console.warn('THREE.DataUtils.toHalfFloat(): value exceeds 65504.');
13
+ if (_val > 65504) {
14
14
 
15
- val = 65504; // maximum representable value in float16
15
+ console.warn('to_half_float_uint16(): value exceeds 65504.');
16
+
17
+ _val = 65504; // maximum representable value in float16
16
18
 
17
19
  }
18
20
 
@@ -22,7 +24,7 @@ export function to_half_float_uint16(val) {
22
24
  * used, eg. in Ogre), with the additional benefit of rounding, inspired
23
25
  * by James Tursa?s half-precision code. */
24
26
 
25
- _floatView[0] = val;
27
+ _floatView[0] = _val;
26
28
  const x = _int32View[0];
27
29
 
28
30
  let bits = (x >> 16) & 0x8000; /* Get the sign */
@@ -46,5 +46,5 @@ export function bvh_to_graph(bvh) {
46
46
  */
47
47
  export function convert_bvh_to_dot_format_string(bvh) {
48
48
  const graph = bvh_to_graph(bvh);
49
- return convertGraphToDotString(graph);
49
+ return convertGraphToDotString({ graph: graph });
50
50
  }
@@ -753,6 +753,9 @@ List.prototype.toJSON = function () {
753
753
  */
754
754
  List.prototype.fromJSON = function (json, constructor) {
755
755
  this.reset();
756
+
757
+ assert.isArray(json,'json');
758
+
756
759
  if (typeof constructor === "function") {
757
760
  this.addAll(json.map(function (elJSON) {
758
761
  const el = new constructor();
@@ -1,6 +1,7 @@
1
1
  import { v3_angle_between } from "../v3_angle_between.js";
2
2
 
3
3
  /**
4
+ * Compute 3d bounds of a circle in 3d space
4
5
  * NOTE: based on https://stackoverflow.com/questions/2592011/bounding-boxes-for-circle-and-arcs-in-3d
5
6
  * @param {AABB3} result
6
7
  * @param {number} centerX
@@ -11,7 +12,13 @@ import { v3_angle_between } from "../v3_angle_between.js";
11
12
  * @param {number} normalZ orientation of the circle
12
13
  * @param {number} radius
13
14
  */
14
- export function computeCircleBoundingBox(result, centerX, centerY, centerZ, normalX, normalY, normalZ, radius) {
15
+ export function computeCircleBoundingBox(
16
+ result,
17
+ centerX, centerY, centerZ,
18
+ normalX, normalY, normalZ,
19
+ radius
20
+ ) {
21
+
15
22
  const ax = v3_angle_between(normalX, normalY, normalZ, 1, 0, 0);
16
23
  const ay = v3_angle_between(normalX, normalY, normalZ, 0, 1, 0);
17
24
  const az = v3_angle_between(normalX, normalY, normalZ, 0, 0, 1);
@@ -20,5 +27,9 @@ export function computeCircleBoundingBox(result, centerX, centerY, centerZ, norm
20
27
  const rY = Math.sin(ay) * radius;
21
28
  const rZ = Math.sin(az) * radius;
22
29
 
23
- result.setBounds(centerX - rX, centerY - rY, centerZ - rZ, centerX + rX, centerY + rY, centerZ + rZ);
30
+ result.setBounds(
31
+ centerX - rX, centerY - rY, centerZ - rZ,
32
+ centerX + rX, centerY + rY, centerZ + rZ
33
+ );
34
+
24
35
  }
@@ -0,0 +1,15 @@
1
+ import { array_copy } from "../../../collection/array/copyArray.js";
2
+ import { MATRIX_4_IDENTITY } from "./MATRIX_4_IDENTITY.js";
3
+
4
+ /**
5
+ * Create a 4x4 matrix that corresponds to translation transform
6
+ * @param {ArrayLike<number>} output
7
+ * @param {ArrayLike<number>} translation 3d vector
8
+ */
9
+ export function m4_make_translation(output, translation) {
10
+ array_copy(MATRIX_4_IDENTITY, 0, output, 0, 16);
11
+
12
+ output[12] = translation[0];
13
+ output[13] = translation[1];
14
+ output[14] = translation[2];
15
+ }
@@ -19,19 +19,10 @@ import { v3_dot } from "../../v3_dot.js";
19
19
  * @returns {number}
20
20
  */
21
21
  export function computeTrianglePlaneSide(
22
- plane_normal_x,
23
- plane_normal_y,
24
- plane_normal_z,
25
- plane_constant,
26
- ax,
27
- ay,
28
- az,
29
- bx,
30
- by,
31
- bz,
32
- cx,
33
- cy,
34
- cz
22
+ plane_normal_x, plane_normal_y, plane_normal_z, plane_constant,
23
+ ax, ay, az,
24
+ bx, by, bz,
25
+ cx, cy, cz
35
26
  ) {
36
27
  let result = 0;
37
28
 
@@ -35,3 +35,13 @@ test('slerp', () => {
35
35
  expect(v.y).toBeCloseTo(0.7071067811865475);
36
36
  expect(v.z).toBeCloseTo(0);
37
37
  });
38
+
39
+ test('addVectors', () => {
40
+ const ut = new Vector3();
41
+
42
+ ut.addVectors(new Vector3(1, 3, 5), new Vector3(-7, 11, 13));
43
+
44
+ expect(ut.x).toBe(-6);
45
+ expect(ut.y).toBe(14);
46
+ expect(ut.z).toBe(18);
47
+ });
@@ -1,12 +1,22 @@
1
1
  import LineBuilder from "../codegen/LineBuilder.js";
2
2
  import { EdgeDirectionType } from "./Edge.js";
3
3
 
4
+
5
+ function defaultNodeToDot(node){
6
+ return `[label="${node.toString()}"]`;
7
+ }
8
+
4
9
  /**
10
+ * @template Node
5
11
  * Build a Graphviz DOT representation of the graph
6
- * @param {Graph} graph
12
+ * @param {Graph<Node>} graph
13
+ * @param {function(Node):string} nodeToDot
7
14
  * @returns {string}
8
15
  */
9
- export function convertGraphToDotString(graph) {
16
+ export function convertGraphToDotString({
17
+ graph,
18
+ nodeToDot=defaultNodeToDot
19
+ }) {
10
20
  const lb = new LineBuilder();
11
21
 
12
22
  lb.add('strict digraph Graph {');
@@ -24,7 +34,7 @@ export function convertGraphToDotString(graph) {
24
34
 
25
35
  const node = nodes[i];
26
36
 
27
- lb.add(`${nodeId(i)} [label="${node.toString()}"];`);
37
+ lb.add(`${nodeId(i)} ${nodeToDot(node)};`);
28
38
 
29
39
  }
30
40
 
@@ -62,7 +62,7 @@ export class Graph {
62
62
  /**
63
63
  *
64
64
  * @param {N} node
65
- * @returns {boolean}
65
+ * @returns {boolean} true if node was added, false if node already exists
66
66
  */
67
67
  addNode(node) {
68
68
  if (this.hasNode(node)) {
@@ -328,6 +328,22 @@ export class Graph {
328
328
  return context_a.getAnyEdgeWith(b);
329
329
  }
330
330
 
331
+ /**
332
+ *
333
+ * @param {N} from
334
+ * @param {N} to
335
+ * @returns {Edge<N>|undefined}
336
+ */
337
+ getAnyDirectedEdge(from, to){
338
+ const ctx_a = this.__nodes.get(from);
339
+
340
+ if(ctx_a === undefined){
341
+ return undefined;
342
+ }
343
+
344
+ return ctx_a.getAnyDirectionEdgeTo(to);
345
+ }
346
+
331
347
  /**
332
348
  *
333
349
  * @param {Edge<N>[]} result
@@ -1,3 +1,5 @@
1
+ import { EdgeDirectionType } from "../Edge.js";
2
+
1
3
  export class NodeContainer {
2
4
  /**
3
5
  * @template N
@@ -40,6 +42,31 @@ export class NodeContainer {
40
42
  return this.__edges;
41
43
  }
42
44
 
45
+ /**
46
+ *
47
+ * @return {number}
48
+ */
49
+ getIncomingEdgeCount() {
50
+ let r = 0;
51
+
52
+ const edges = this.__edges;
53
+ const edge_count = edges.length;
54
+
55
+ for (let i = 0; i < edge_count; i++) {
56
+ const edge = edges[i];
57
+
58
+ if (
59
+ (edge.first === this.node && edge.direction === EdgeDirectionType.Forward)
60
+ || (edge.second === this.node && edge.direction === EdgeDirectionType.Backward)
61
+
62
+ ) {
63
+ r++;
64
+ }
65
+ }
66
+
67
+ return r;
68
+ }
69
+
43
70
 
44
71
  /**
45
72
  *
@@ -101,6 +128,37 @@ export class NodeContainer {
101
128
  return undefined;
102
129
  }
103
130
 
131
+ /**
132
+ * Undirected edges don't count
133
+ * @param {N} other
134
+ * @returns {Edge<N>|undefined}
135
+ */
136
+ getAnyDirectionEdgeTo(other) {
137
+
138
+ /**
139
+ *
140
+ * @type {Edge[]}
141
+ */
142
+ const edges = this.__edges;
143
+
144
+ const n = edges.length;
145
+
146
+ for (let i = 0; i < n; i++) {
147
+ const edge = edges[i];
148
+
149
+ if (
150
+ (edge.second === other && edge.direction === EdgeDirectionType.Forward)
151
+ || (edge.first === other && edge.direction === EdgeDirectionType.Backward)
152
+
153
+ ) {
154
+ return edge;
155
+ }
156
+ }
157
+
158
+ // not found
159
+ return undefined;
160
+ }
161
+
104
162
  /**
105
163
  *
106
164
  * @param {Edge} e
@@ -1,12 +1,19 @@
1
1
  import { assert } from "../assert.js";
2
2
 
3
3
  export class ModuleRegistry {
4
+
5
+ /**
6
+ *
7
+ * @type {Map<string, *>}
8
+ */
9
+ #modules = new Map();
10
+ /**
11
+ *
12
+ * @type {Map<*,string[]>}
13
+ */
14
+ #reverse_lookup = new Map();
15
+
4
16
  constructor() {
5
- /**
6
- *
7
- * @type {Map<string, *>}
8
- */
9
- this.__elements = new Map();
10
17
 
11
18
  const self = this;
12
19
 
@@ -19,7 +26,7 @@ export class ModuleRegistry {
19
26
  * @returns {Class}
20
27
  */
21
28
  get(target, p, receiver) {
22
- const module = self.__elements.get(p);
29
+ const module = self.get(p);
23
30
 
24
31
  if (module === undefined) {
25
32
  throw new Error(`Module '${p}' not found in the registry`);
@@ -35,7 +42,7 @@ export class ModuleRegistry {
35
42
  * @param {(name:string, module:*)=>void} visitor
36
43
  */
37
44
  traverse(visitor) {
38
- this.__elements.forEach((klass, name) => visitor(name, klass));
45
+ this.#modules.forEach((klass, name) => visitor(name, klass));
39
46
  }
40
47
 
41
48
 
@@ -45,7 +52,7 @@ export class ModuleRegistry {
45
52
  * @returns {T}
46
53
  */
47
54
  get(name) {
48
- return this.__elements.get(name);
55
+ return this.#modules.get(name);
49
56
  }
50
57
 
51
58
  /**
@@ -54,7 +61,7 @@ export class ModuleRegistry {
54
61
  * @returns {boolean}
55
62
  */
56
63
  has(name) {
57
- return this.__elements.has(name);
64
+ return this.#modules.has(name);
58
65
  }
59
66
 
60
67
  /**
@@ -75,11 +82,38 @@ export class ModuleRegistry {
75
82
  return false;
76
83
  }
77
84
 
78
- this.__elements.set(name, module);
85
+ this.#modules.set(name, module);
86
+
87
+ let names = this.#reverse_lookup.get(module);
88
+
89
+ if (names === undefined) {
90
+ names = [];
91
+ this.#reverse_lookup.set(module, names);
92
+ }
93
+
94
+ names.push(name);
79
95
 
80
96
  return true;
81
97
  }
82
98
 
99
+ /**
100
+ * Find all names associated with the given module
101
+ * @template T
102
+ * @param {T} module
103
+ * @returns {string[]}
104
+ * @throws if module is not registered
105
+ */
106
+ findNamesByModule(module) {
107
+
108
+ const names = this.#reverse_lookup.get(module);
109
+
110
+ if (names === undefined) {
111
+ throw new Error('Module not found');
112
+ } else {
113
+ return names;
114
+ }
115
+ }
116
+
83
117
  initialize() {
84
118
 
85
119
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Note that values correspond to shifted specific 1 bit mask,
3
+ * this is intentional, to allow you to encode complex access pattern into a single integer value
4
+ * @readonly
5
+ * @enum {number}
6
+ */
7
+ export const ResourceAccessKind = {
8
+ Read: 1,
9
+ Write: 2,
10
+ Create: 4
11
+ };