@woosh/meep-engine 2.47.14 → 2.47.16

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.
@@ -117641,78 +117641,90 @@ class MaxRectanglesPacker {
117641
117641
  */
117642
117642
 
117643
117643
  /**
117644
- *
117645
- * @constructor
117644
+ * Pool of unsigned integer IDs, useful when you don't want to just keep incrementing ID counter and want to re-use IDs after they are no longer needed
117645
+ * Main use case is when your IDs are array indices, having compact IDs lets you use fixed size array even as objects are added and removed as you're able to reuse slots in an efficient manner
117646
117646
  */
117647
- function IdPool() {
117647
+ class IdPool {
117648
117648
  /**
117649
117649
  * @private
117650
117650
  * @type {BitSet}
117651
117651
  */
117652
- this.bitSet = new BitSet();
117653
- }
117652
+ #set = new BitSet();
117654
117653
 
117655
- /**
117656
- *
117657
- * @returns {number}
117658
- */
117659
- IdPool.prototype.get = function () {
117660
- const bitIndex = this.bitSet.nextClearBit(0);
117654
+ /**
117655
+ * Looks up next available ID without reserving it
117656
+ * If you want to also reserve the ID - use {@link get} instead
117657
+ * @returns {number}
117658
+ */
117659
+ peek() {
117660
+ return this.#set.nextClearBit(0);
117661
+ }
117661
117662
 
117662
- this.bitSet.set(bitIndex, true);
117663
+ /**
117664
+ *
117665
+ * @returns {number}
117666
+ */
117667
+ get() {
117668
+ const id = this.peek();
117663
117669
 
117664
- return bitIndex;
117665
- };
117670
+ this.#set.set(id, true);
117666
117671
 
117667
- /**
117668
- * Attempt to request a specific ID from the pool.
117669
- * @param {number} id
117670
- * @return {boolean} true if request succeeds, false otherwise
117671
- */
117672
- IdPool.prototype.getSpecific = function (id) {
117673
- if (this.isUsed(id)) {
117674
- return false;
117672
+ return id;
117675
117673
  }
117676
117674
 
117677
- this.bitSet.set(id, true);
117678
- return true;
117679
- };
117675
+ /**
117676
+ * Attempt to request a specific ID from the pool.
117677
+ * @param {number} id
117678
+ * @return {boolean} true if request succeeds, false otherwise
117679
+ */
117680
+ getSpecific(id) {
117681
+ if (this.isUsed(id)) {
117682
+ return false;
117683
+ }
117680
117684
 
117681
- /**
117682
- *
117683
- * @param {number} id
117684
- * @returns {boolean}
117685
- */
117686
- IdPool.prototype.isUsed = function (id) {
117687
- return this.bitSet.get(id);
117688
- };
117685
+ this.#set.set(id, true);
117686
+ return true;
117687
+ }
117689
117688
 
117690
- /**
117691
- * Traverse all IDs currently in use
117692
- * @param {function(id:number)} visitor
117693
- */
117694
- IdPool.prototype.traverseUsed = function (visitor) {
117695
- assert.equal(typeof visitor, 'function', `visitor must be a function, instead was '${typeof visitor}'`);
117689
+ /**
117690
+ *
117691
+ * @param {number} id
117692
+ * @returns {boolean}
117693
+ */
117694
+ isUsed(id) {
117695
+ return this.#set.get(id);
117696
+ }
117696
117697
 
117697
- const bitSet = this.bitSet;
117698
+ /**
117699
+ * Traverse all IDs currently in use
117700
+ * @param {function(id:number)} visitor
117701
+ */
117702
+ traverseUsed(visitor) {
117703
+ assert.isFunction(visitor, "visitor");
117698
117704
 
117699
- for (let i = bitSet.nextSetBit(0); i !== -1; i = bitSet.nextSetBit(i + 1)) {
117700
- visitor(i);
117701
- }
117705
+ const set = this.#set;
117702
117706
 
117703
- };
117707
+ for (let i = set.nextSetBit(0); i !== -1; i = set.nextSetBit(i + 1)) {
117708
+ visitor(i);
117709
+ }
117704
117710
 
117705
- /**
117706
- *
117707
- * @param {number} id
117708
- */
117709
- IdPool.prototype.release = function (id) {
117710
- this.bitSet.clear(id);
117711
- };
117711
+ }
117712
117712
 
117713
- IdPool.prototype.reset = function () {
117714
- this.bitSet.reset();
117715
- };
117713
+ /**
117714
+ *
117715
+ * @param {number} id
117716
+ */
117717
+ release(id) {
117718
+ this.#set.clear(id);
117719
+ }
117720
+
117721
+ /**
117722
+ * Release all used IDs
117723
+ */
117724
+ reset() {
117725
+ this.#set.reset();
117726
+ }
117727
+ }
117716
117728
 
117717
117729
  class AtlasPatch {
117718
117730
  constructor() {
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.47.14",
8
+ "version": "2.47.16",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -7,77 +7,89 @@ import { assert } from "./assert.js";
7
7
  import { BitSet } from "./binary/BitSet.js";
8
8
 
9
9
  /**
10
- *
11
- * @constructor
10
+ * Pool of unsigned integer IDs, useful when you don't want to just keep incrementing ID counter and want to re-use IDs after they are no longer needed
11
+ * Main use case is when your IDs are array indices, having compact IDs lets you use fixed size array even as objects are added and removed as you're able to reuse slots in an efficient manner
12
12
  */
13
- function IdPool() {
13
+ class IdPool {
14
14
  /**
15
15
  * @private
16
16
  * @type {BitSet}
17
17
  */
18
- this.bitSet = new BitSet();
19
- }
18
+ #set = new BitSet();
20
19
 
21
- /**
22
- *
23
- * @returns {number}
24
- */
25
- IdPool.prototype.get = function () {
26
- const bitIndex = this.bitSet.nextClearBit(0);
20
+ /**
21
+ * Looks up next available ID without reserving it
22
+ * If you want to also reserve the ID - use {@link get} instead
23
+ * @returns {number}
24
+ */
25
+ peek() {
26
+ return this.#set.nextClearBit(0);
27
+ }
27
28
 
28
- this.bitSet.set(bitIndex, true);
29
+ /**
30
+ *
31
+ * @returns {number}
32
+ */
33
+ get() {
34
+ const id = this.peek();
29
35
 
30
- return bitIndex;
31
- };
36
+ this.#set.set(id, true);
32
37
 
33
- /**
34
- * Attempt to request a specific ID from the pool.
35
- * @param {number} id
36
- * @return {boolean} true if request succeeds, false otherwise
37
- */
38
- IdPool.prototype.getSpecific = function (id) {
39
- if (this.isUsed(id)) {
40
- return false;
38
+ return id;
41
39
  }
42
40
 
43
- this.bitSet.set(id, true);
44
- return true;
45
- };
41
+ /**
42
+ * Attempt to request a specific ID from the pool.
43
+ * @param {number} id
44
+ * @return {boolean} true if request succeeds, false otherwise
45
+ */
46
+ getSpecific(id) {
47
+ if (this.isUsed(id)) {
48
+ return false;
49
+ }
46
50
 
47
- /**
48
- *
49
- * @param {number} id
50
- * @returns {boolean}
51
- */
52
- IdPool.prototype.isUsed = function (id) {
53
- return this.bitSet.get(id);
54
- };
51
+ this.#set.set(id, true);
52
+ return true;
53
+ }
55
54
 
56
- /**
57
- * Traverse all IDs currently in use
58
- * @param {function(id:number)} visitor
59
- */
60
- IdPool.prototype.traverseUsed = function (visitor) {
61
- assert.equal(typeof visitor, 'function', `visitor must be a function, instead was '${typeof visitor}'`);
55
+ /**
56
+ *
57
+ * @param {number} id
58
+ * @returns {boolean}
59
+ */
60
+ isUsed(id) {
61
+ return this.#set.get(id);
62
+ }
62
63
 
63
- const bitSet = this.bitSet;
64
+ /**
65
+ * Traverse all IDs currently in use
66
+ * @param {function(id:number)} visitor
67
+ */
68
+ traverseUsed(visitor) {
69
+ assert.isFunction(visitor, "visitor");
64
70
 
65
- for (let i = bitSet.nextSetBit(0); i !== -1; i = bitSet.nextSetBit(i + 1)) {
66
- visitor(i);
67
- }
71
+ const set = this.#set;
68
72
 
69
- };
73
+ for (let i = set.nextSetBit(0); i !== -1; i = set.nextSetBit(i + 1)) {
74
+ visitor(i);
75
+ }
70
76
 
71
- /**
72
- *
73
- * @param {number} id
74
- */
75
- IdPool.prototype.release = function (id) {
76
- this.bitSet.clear(id);
77
- };
77
+ }
78
78
 
79
- IdPool.prototype.reset = function () {
80
- this.bitSet.reset();
81
- };
79
+ /**
80
+ *
81
+ * @param {number} id
82
+ */
83
+ release(id) {
84
+ this.#set.clear(id);
85
+ }
86
+
87
+ /**
88
+ * Release all used IDs
89
+ */
90
+ reset() {
91
+ this.#set.reset();
92
+ }
93
+ }
82
94
 
83
95
  export default IdPool;
@@ -12,37 +12,37 @@ export function abstractJSONSerializer(source, serializers, classNames) {
12
12
  return source;
13
13
  }
14
14
 
15
- // parameter is an object
15
+ // parameter is an object
16
16
 
17
- // extract type name
18
- const Klass = source.constructor;
19
- let typeName = classNames.get(Klass);
17
+ // extract type name
18
+ const Klass = source.constructor;
19
+ let typeName = classNames.get(Klass);
20
20
 
21
- if (typeName === undefined) {
22
- // try fallback to "typeName" field on constructor
23
- typeName = Klass.typeName;
24
- }
21
+ if (typeName === undefined) {
22
+ // try fallback to "typeName" field on constructor
23
+ typeName = Klass.typeName;
24
+ }
25
25
 
26
- if (typeName === undefined) {
27
- throw new Error(`Failed to resolve type name. No name found in classNames registry and no .typeName field on the constructor`);
28
- }
26
+ if (typeName === undefined) {
27
+ throw new Error(`Failed to resolve type name. No name found in classNames registry and no .typeName field on the constructor {name: '${Klass.name}}'`);
28
+ }
29
29
 
30
- let serializer = serializers.get(typeName);
31
- let serializerContext = undefined;
30
+ let serializer = serializers.get(typeName);
31
+ let serializerContext = undefined;
32
32
 
33
- if (serializer === undefined) {
34
- serializer = source.toJSON;
35
- serializerContext = source;
36
- }
33
+ if (serializer === undefined) {
34
+ serializer = source.toJSON;
35
+ serializerContext = source;
36
+ }
37
37
 
38
- if (serializer === undefined) {
39
- throw new Error(`Failed to resolve serializer for object type '${typeName}'. No serializer found in serializers registry and no .toJSON method on object itself`);
40
- }
38
+ if (serializer === undefined) {
39
+ throw new Error(`Failed to resolve serializer for object type '${typeName}'. No serializer found in serializers registry and no .toJSON method on object itself`);
40
+ }
41
41
 
42
- return {
43
- type: typeName,
44
- data: serializer.call(serializerContext, source)
45
- };
42
+ return {
43
+ type: typeName,
44
+ data: serializer.call(serializerContext, source)
45
+ };
46
46
 
47
47
 
48
48
  }
@@ -127,6 +127,7 @@ export class NodeGraph {
127
127
  * Merge foreign nodes and associated connections into this graph
128
128
  * New node instances and connections will be created to reflect these inside this graph
129
129
  * NOTE: parameters on merged nodes are shallow copies
130
+ * NOTE: if IDs are available - copied nodes will have the same IDs as the originals
130
131
  * @param {NodeInstance[]} nodes
131
132
  * @param {Connection[]} [connections]
132
133
  * @returns {{connections:Connection[], nodes:NodeInstance[]}} local created instances
@@ -147,12 +148,28 @@ export class NodeGraph {
147
148
  for (let i = 0; i < additional_node_count; i++) {
148
149
  const other_node = nodes[i];
149
150
 
150
- const this_node_id = this.createNode(other_node.description);
151
- this_nodes[other_node.id] = this_node_id;
151
+ const other_node_id = other_node.id;
152
152
 
153
- // copy parameters
154
- const this_node = this.getNode(this_node_id);
153
+ const this_node = new NodeInstance();
154
+ this_node.setDescription(other_node.description);
155
+
156
+
157
+ // attempt to gain the same ID
158
+ const can_use_same_id = this.__idpNodes.isUsed(other_node_id);
159
+
160
+ let this_node_id;
161
+ if (can_use_same_id) {
162
+ this_node_id = other_node_id;
163
+ } else {
164
+ this_node_id = this.__idpNodes.peek();
165
+ }
155
166
 
167
+ this.addNode(this_node);
168
+
169
+
170
+ this_nodes[other_node_id] = this_node_id;
171
+
172
+ // copy parameters
156
173
  this_node.setParameters(other_node.parameters);
157
174
 
158
175
  }
@@ -376,13 +393,13 @@ export class NodeGraph {
376
393
  createNode(node) {
377
394
  const nodeInstance = new NodeInstance();
378
395
 
379
- const id = this.__idpNodes.get();
396
+ const id = this.__idpNodes.peek();
380
397
 
381
398
  nodeInstance.id = id;
382
399
  nodeInstance.setDescription(node);
383
400
 
384
401
  //record the node
385
- this.nodes.add(nodeInstance);
402
+ this.addNode(nodeInstance);
386
403
 
387
404
  return id;
388
405
  }
@@ -11,4 +11,8 @@ export class NodeInstance {
11
11
  readonly endpoints: NodeInstancePortReference[]
12
12
 
13
13
  readonly connections: List<Connection>
14
+
15
+ setDescription(d: NodeDescription): void
16
+
17
+ setParameters(hash: { [key: string]: any }): void
14
18
  }