@woosh/meep-engine 2.47.8 → 2.47.10

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.
@@ -3,7 +3,6 @@
3
3
  */
4
4
 
5
5
 
6
- import BoundedValue from "../../core/model/BoundedValue.js";
7
6
  import { ObservedMap } from "../../core/collection/ObservedMap.js";
8
7
  import { HashMap } from "../../core/collection/HashMap.js";
9
8
  import { extractAssetListFromManager } from "./preloader/extractAssetListFromManager.js";
@@ -18,77 +17,9 @@ import Task from "../../core/process/task/Task.js";
18
17
  import { TaskSignal } from "../../core/process/task/TaskSignal.js";
19
18
  import { AssetRequest, AssetRequestFlags } from "./AssetRequest.js";
20
19
  import FastBinaryHeap from "../../core/collection/heap/FastBinaryHeap.js";
20
+ import { AssetLoadState } from "./AssetLoadState.js";
21
+ import { PendingAsset } from "./PendingAsset.js";
21
22
 
22
- /**
23
- * @enum {number}
24
- */
25
- const AssetLoadState = {
26
- Initial: 0,
27
- Queued: 1,
28
- Loading: 2,
29
- Succeeded: 3,
30
- Failed: 4
31
- };
32
-
33
-
34
- class PendingAsset {
35
- /**
36
- *
37
- * @param {AssetDescription} description
38
- * @constructor
39
- */
40
- constructor(description) {
41
- /**
42
- *
43
- * @type {AssetDescription}
44
- */
45
- this.description = description;
46
-
47
- /**
48
- *
49
- * @type {AssetRequest[]}
50
- */
51
- this.requests = [];
52
-
53
- /**
54
- *
55
- * @type {BoundedValue}
56
- */
57
- this.progress = new BoundedValue(0, 0);
58
-
59
- /**
60
- *
61
- * @type {AssetLoadState|number}
62
- */
63
- this.state = AssetLoadState.Initial;
64
- }
65
-
66
- /**
67
- * Returns aggregated priority of the pending asset based on highest priority of associated requests
68
- * @return {number}
69
- */
70
- get priority() {
71
- let max_priority = 0;
72
-
73
- const requests = this.requests;
74
- const n = requests.length;
75
-
76
- if (n > 0) {
77
- max_priority = requests[0].priority;
78
- }
79
-
80
- for (let i = 1; i < n; i++) {
81
- const request = requests[i];
82
- const priority = request.priority;
83
-
84
- if (priority > max_priority) {
85
- max_priority = request;
86
- }
87
- }
88
-
89
- return max_priority;
90
- }
91
- }
92
23
 
93
24
  class Response {
94
25
  /**
@@ -119,141 +50,144 @@ function get_pending_asset_priority_score(pending_asset) {
119
50
  export class AssetManager {
120
51
  /**
121
52
  *
122
- * @param {Engine} engine
123
- * @constructor
53
+ * @type {HashMap<AssetDescription, Asset>}
54
+ * @private
124
55
  */
125
- constructor(engine) {
126
- /**
127
- *
128
- * @type {HashMap<AssetDescription, Asset>}
129
- * @private
130
- */
131
- this.assets = new HashMap({
132
- capacity: 1024
133
- });
56
+ assets = new HashMap({
57
+ capacity: 1024
58
+ });
134
59
 
135
- /**
136
- *
137
- * @type {ObservedMap<AssetDescription, PendingAsset>}
138
- * @private
139
- */
140
- this.request_map = new ObservedMap(new HashMap());
60
+ /**
61
+ *
62
+ * @type {ObservedMap<AssetDescription, PendingAsset>}
63
+ */
64
+ request_map = new ObservedMap(new HashMap());
141
65
 
142
- /**
143
- * Waiting queue for assets that haven't yet been scheduled (passed to relevant loader)
144
- * @type {BinaryHeap<PendingAsset>}
145
- * @private
146
- */
147
- this.__pending_asset_wait_queue = new FastBinaryHeap(get_pending_asset_priority_score);
148
- /**
149
- * Assets currently being processed by loaders
150
- * @type {Set<PendingAsset>}
151
- * @private
152
- */
153
- this.__pending_asset_active_load_set = new Set();
66
+ /**
67
+ * Waiting queue for assets that haven't yet been scheduled (passed to relevant loader)
68
+ * @type {BinaryHeap<PendingAsset>}
69
+ * @private
70
+ */
71
+ #pending_asset_wait_queue = new FastBinaryHeap(get_pending_asset_priority_score);
72
+ /**
73
+ * Assets currently being processed by #loaders
74
+ * @type {Set<PendingAsset>}
75
+ * @private
76
+ */
77
+ #pending_asset_active_load_set = new Set();
154
78
 
155
- /**
156
- * Maximum number of requests that can be handled at the same time
157
- * Since most of the requests are handled over the network, this can help you control network concurrency,
158
- * this can be useful to keep some network slots available for high-priority requests such as UI related ones
159
- * TODO currently nested asset requests are not recognized, so if nesting level exceeds concurrency - it will lead to a deadlock
160
- * @type {number}
161
- */
162
- this.load_concurrency = Infinity;
79
+ /**
80
+ * Maximum number of requests that can be handled at the same time
81
+ * Since most of the requests are handled over the network, this can help you control network concurrency,
82
+ * this can be useful to keep some network slots available for high-priority requests such as UI related ones
83
+ * TODO currently nested asset requests are not recognized, so if nesting level exceeds concurrency - it will lead to a deadlock
84
+ * @type {number}
85
+ */
86
+ load_concurrency = Infinity;
163
87
 
164
- /**
165
- * Registered loaders
166
- * @private
167
- * @type {Object<AssetLoader>}
168
- */
169
- this.loaders = {};
88
+ /**
89
+ * Registered #loaders
90
+ * @private
91
+ * @type {Object<AssetLoader>}
92
+ */
93
+ #loaders = {};
170
94
 
171
- /**
172
- * After asset is loaded, a chain of transforms can be applied to it, these are registered here
173
- * Transformers are executed in the order in which they are added
174
- * Identified by asset "type" string
175
- * @type {Object<AssetTransformer[]>}
176
- * @private
177
- */
178
- this.transformers = {};
95
+ /**
96
+ * After asset is loaded, a chain of transforms can be applied to it, these are registered here
97
+ * Transformers are executed in the order in which they are added
98
+ * Identified by asset "type" string
99
+ * @type {Object<AssetTransformer[]>}
100
+ * @private
101
+ */
102
+ #transformers = {};
179
103
 
180
- /**
181
- * Named links to specific assets. Useful to later re-mapping assets and having meaningful names for them
182
- * @type {Map<string, AssetDescription>}
183
- * @private
184
- */
185
- this.aliases = new Map();
104
+ /**
105
+ * Named links to specific assets. Useful to later re-mapping assets and having meaningful names for them
106
+ * @type {Map<string, AssetDescription>}
107
+ * @private
108
+ */
109
+ #aliases = new Map();
186
110
 
187
- /**
188
- * This will be added to asset path for actual network resolution
189
- * @type {string}
190
- * @private
191
- */
192
- this.rootPath = '';
111
+ /**
112
+ * This will be added to asset path for actual network resolution
113
+ * @type {string}
114
+ * @private
115
+ */
116
+ rootPath = '';
193
117
 
194
- /**
195
- *
196
- * @type {Engine}
197
- * @private
198
- */
199
- this.__engine = engine;
118
+ /**
119
+ *
120
+ * @type {CrossOriginConfig}
121
+ */
122
+ crossOriginConfig = new CrossOriginConfig();
200
123
 
201
- /**
202
- *
203
- * @type {CrossOriginConfig}
204
- */
205
- this.crossOriginConfig = new CrossOriginConfig();
124
+ /**
125
+ *
126
+ * @type {HashSet<AssetDescription>}
127
+ * @private
128
+ */
129
+ #failures = new HashSet();
206
130
 
207
- /**
208
- *
209
- * @type {HashSet<AssetDescription>}
210
- * @private
211
- */
212
- this.failures = new HashSet();
131
+ /**
132
+ * Queue of responses that are waiting to be dispatched
133
+ * @type {Deque<Response>}
134
+ * @private
135
+ */
136
+ #response_queue = new Deque();
213
137
 
214
- /**
215
- * Queue of responses that are waiting to be dispatched
216
- * @type {Deque<Response>}
217
- * @private
218
- */
219
- this.__response_queue = new Deque();
138
+ /**
139
+ *
140
+ * @type {Task}
141
+ * @private
142
+ */
143
+ #response_processor = new Task({
144
+ name: "Asset Manager Response processor",
145
+ cycleFunction: () => {
146
+ if (this.#response_queue.isEmpty()) {
147
+ return TaskSignal.Yield;
148
+ }
220
149
 
221
- /**
222
- *
223
- * @type {Task}
224
- * @private
225
- */
226
- this.__response_processor = new Task({
227
- name: "Asset Manager Response processor",
228
- cycleFunction: () => {
229
- if (this.__response_queue.isEmpty()) {
230
- return TaskSignal.Yield;
231
- }
150
+ const response = this.#response_queue.removeFirst();
232
151
 
233
- const response = this.__response_queue.removeFirst();
152
+ this.#process_response(response);
234
153
 
235
- this.__process_response(response);
154
+ return TaskSignal.Continue;
155
+ }
156
+ });
236
157
 
237
- return TaskSignal.Continue;
238
- }
239
- });
158
+ /**
159
+ *
160
+ * @type {boolean}
161
+ * @private
162
+ */
163
+ #is_running = false;
164
+
165
+ /**
166
+ *
167
+ * @type {Engine|null}
168
+ * @private
169
+ */
170
+ #engine = null;
171
+
172
+ /**
173
+ *
174
+ * @param {Engine} engine
175
+ * @constructor
176
+ */
177
+ constructor(engine) {
178
+
179
+ this.#engine = engine;
240
180
 
241
- /**
242
- *
243
- * @type {boolean}
244
- * @private
245
- */
246
- this.__is_running = false;
247
181
  }
248
182
 
249
183
  startup() {
250
- if (this.__is_running) {
184
+ if (this.#is_running) {
251
185
  return;
252
186
  }
253
187
 
254
- this.__engine.executor.run(this.__response_processor);
188
+ this.#engine.executor.run(this.#response_processor);
255
189
 
256
- this.__is_running = true;
190
+ this.#is_running = true;
257
191
  }
258
192
 
259
193
  /**
@@ -262,18 +196,18 @@ export class AssetManager {
262
196
  * @return {Promise<void>}
263
197
  */
264
198
  async shutdown(immediate = false) {
265
- if (!this.__is_running) {
199
+ if (!this.#is_running) {
266
200
  return;
267
201
  }
268
202
 
269
203
  if (!immediate) {
270
204
  // wait until all responses have been processed
271
- await Promise.allSettled([Task.promise(this.__response_processor)]);
205
+ await Promise.allSettled([Task.promise(this.#response_processor)]);
272
206
  }
273
207
 
274
- this.__engine.executor.removeTask(this.__response_processor);
208
+ this.#engine.executor.removeTask(this.#response_processor);
275
209
 
276
- this.__is_running = false;
210
+ this.#is_running = false;
277
211
  }
278
212
 
279
213
  /**
@@ -362,6 +296,8 @@ export class AssetManager {
362
296
  console.warn(`Another asset under ${assetDescription} already exists and will be replaced`);
363
297
  }
364
298
 
299
+ // TODO check for assets in-flight
300
+
365
301
  this.assets.set(assetDescription, asset);
366
302
  }
367
303
 
@@ -370,7 +306,7 @@ export class AssetManager {
370
306
  * @param {Response} response
371
307
  * @private
372
308
  */
373
- __process_response(response) {
309
+ #process_response(response) {
374
310
 
375
311
  try {
376
312
  response.request.successCallback(response.asset);
@@ -385,8 +321,8 @@ export class AssetManager {
385
321
  * @param {AssetRequest} request
386
322
  * @private
387
323
  */
388
- __schedule_response(asset, request) {
389
- this.__response_queue.add(new Response(asset, request));
324
+ #schedule_response(asset, request) {
325
+ this.#response_queue.add(new Response(asset, request));
390
326
  }
391
327
 
392
328
  /**
@@ -394,11 +330,11 @@ export class AssetManager {
394
330
  * @param {PendingAsset} asset
395
331
  * @private
396
332
  */
397
- __schedule_load(asset) {
398
- if (this.__pending_asset_active_load_set.size < this.load_concurrency) {
399
- this.__dispatch_pending_asset(asset);
333
+ #schedule_load(asset) {
334
+ if (this.#pending_asset_active_load_set.size < this.load_concurrency) {
335
+ this.#dispatch_pending_asset(asset);
400
336
  } else {
401
- this.__pending_asset_wait_queue.push(asset);
337
+ this.#pending_asset_wait_queue.push(asset);
402
338
  }
403
339
  }
404
340
 
@@ -407,17 +343,17 @@ export class AssetManager {
407
343
  * @param {PendingAsset} asset
408
344
  * @private
409
345
  */
410
- __force_load(asset) {
346
+ #force_load(asset) {
411
347
  // check if the asset is already being loaded
412
- if (this.__pending_asset_active_load_set.has(asset)) {
348
+ if (this.#pending_asset_active_load_set.has(asset)) {
413
349
  return;
414
350
  }
415
351
 
416
352
  // remove from queue
417
- this.__pending_asset_wait_queue.delete(asset);
353
+ this.#pending_asset_wait_queue.delete(asset);
418
354
 
419
355
  // dispatch
420
- this.__dispatch_pending_asset(asset);
356
+ this.#dispatch_pending_asset(asset);
421
357
 
422
358
  }
423
359
 
@@ -426,21 +362,21 @@ export class AssetManager {
426
362
  * @param {PendingAsset} pending_asset
427
363
  * @private
428
364
  */
429
- __handle_asset_resolved(pending_asset) {
365
+ #handle_asset_resolved(pending_asset) {
430
366
  // console.log(`Asset resolved ${pending_asset.description}`); // DEBUG
431
367
 
432
- const active_set = this.__pending_asset_active_load_set;
368
+ const active_set = this.#pending_asset_active_load_set;
433
369
 
434
370
  this.request_map.delete(pending_asset.description);
435
371
  active_set.delete(pending_asset);
436
372
 
437
- const queue = this.__pending_asset_wait_queue;
373
+ const queue = this.#pending_asset_wait_queue;
438
374
 
439
375
  // schedule more if possible
440
376
  while (!queue.isEmpty() && active_set.size < this.load_concurrency) {
441
377
  const load = queue.pop();
442
378
 
443
- this.__dispatch_pending_asset(load);
379
+ this.#dispatch_pending_asset(load);
444
380
  }
445
381
  }
446
382
 
@@ -449,7 +385,7 @@ export class AssetManager {
449
385
  * @param {PendingAsset} pendingAsset
450
386
  * @private
451
387
  */
452
- __dispatch_pending_asset(pendingAsset) {
388
+ #dispatch_pending_asset(pendingAsset) {
453
389
  // console.log(`Asset load dispatched ${pendingAsset.description}`); // DEBUG
454
390
 
455
391
  const requests = pendingAsset.requests;
@@ -457,7 +393,7 @@ export class AssetManager {
457
393
  const type = assetDescription.type;
458
394
  const path = assetDescription.path;
459
395
 
460
- const loader = this.loaders[type];
396
+ const loader = this.#loaders[type];
461
397
 
462
398
  if (loader === undefined) {
463
399
  let reported_error = false;
@@ -466,7 +402,7 @@ export class AssetManager {
466
402
  const assetRequest = requests[i];
467
403
 
468
404
  if (typeof assetRequest.failureCallback === "function") {
469
- assetRequest.failureCallback(`no loader exists for asset type '${type}', valid types are: ${Object.keys(this.loaders).join(', ')}`);
405
+ assetRequest.failureCallback(`no loader exists for asset type '${type}', valid types are: ${Object.keys(this.#loaders).join(', ')}`);
470
406
  } else {
471
407
  //uncaught
472
408
  if (!reported_error) {
@@ -476,16 +412,16 @@ export class AssetManager {
476
412
  }
477
413
  }
478
414
 
479
- this.__handle_asset_resolved(pendingAsset);
415
+ this.#handle_asset_resolved(pendingAsset);
480
416
 
481
417
  return;
482
418
  }
483
419
 
484
420
  // mark as being loaded
485
- this.__pending_asset_active_load_set.add(pendingAsset);
421
+ this.#pending_asset_active_load_set.add(pendingAsset);
486
422
 
487
423
  const assets = this.assets;
488
- const failures = this.failures;
424
+ const failures = this.#failures;
489
425
 
490
426
 
491
427
  /**
@@ -509,7 +445,7 @@ export class AssetManager {
509
445
  let asset = loaded_asset;
510
446
 
511
447
  // apply transform chain
512
- const transformers = this.transformers[type];
448
+ const transformers = this.#transformers[type];
513
449
  if (transformers !== undefined) {
514
450
  const transformer_count = transformers.length;
515
451
  for (let i = 0; i < transformer_count; i++) {
@@ -532,13 +468,13 @@ export class AssetManager {
532
468
  assets.set(assetDescription, asset);
533
469
 
534
470
  //clear callbacks etc.
535
- this.__handle_asset_resolved(pendingAsset);
471
+ this.#handle_asset_resolved(pendingAsset);
536
472
 
537
473
 
538
474
  // process callbacks
539
475
  for (let i = 0; i < requests.length; i++) {
540
476
  const request = requests[i];
541
- this.__schedule_response(asset, request);
477
+ this.#schedule_response(asset, request);
542
478
  }
543
479
 
544
480
  }
@@ -566,7 +502,7 @@ export class AssetManager {
566
502
  }
567
503
 
568
504
  //clear callbacks etc.
569
- this.__handle_asset_resolved(pendingAsset);
505
+ this.#handle_asset_resolved(pendingAsset);
570
506
 
571
507
  // record failure
572
508
  failures.add(assetDescription);
@@ -632,15 +568,15 @@ export class AssetManager {
632
568
 
633
569
  if (shouldSchedule) {
634
570
  // not loading yet, lets create a load container and schedule it
635
- this.__schedule_load(pendingAsset);
571
+ this.#schedule_load(pendingAsset);
636
572
  } else {
637
573
  // update priority queue if necessary
638
- this.__pending_asset_wait_queue.updateElementScore(pendingAsset);
574
+ this.#pending_asset_wait_queue.updateElementScore(pendingAsset);
639
575
  }
640
576
 
641
577
 
642
578
  if (request.getFlag(AssetRequestFlags.SkipQueue)) {
643
- this.__force_load(pendingAsset);
579
+ this.#force_load(pendingAsset);
644
580
  }
645
581
  }
646
582
 
@@ -662,7 +598,7 @@ export class AssetManager {
662
598
  getLoaderByType(type) {
663
599
  assert.isString(type, 'type');
664
600
 
665
- return this.loaders[type];
601
+ return this.#loaders[type];
666
602
  }
667
603
 
668
604
  /**
@@ -671,7 +607,7 @@ export class AssetManager {
671
607
  * @return {AssetDescription[]}
672
608
  * @private
673
609
  */
674
- __getLoadedAssetDescriptorsByType(type) {
610
+ #getLoadedAssetDescriptorsByType(type) {
675
611
  const loaded_assets = Array.from(this.assets.keys());
676
612
  return loaded_assets.filter(t => t.type === type);
677
613
  }
@@ -682,18 +618,18 @@ export class AssetManager {
682
618
  * @param {AssetTransformer<T>} transformer
683
619
  */
684
620
  registerTransformer(type, transformer) {
685
- let transformers = this.transformers[type];
621
+ let transformers = this.#transformers[type];
686
622
 
687
623
  if (transformers === undefined) {
688
624
  transformers = [];
689
625
 
690
- this.transformers[type] = transformers;
626
+ this.#transformers[type] = transformers;
691
627
  }
692
628
 
693
629
  transformers.push(transformer);
694
630
 
695
631
  // check for loaded assets
696
- const matching_assets = this.__getLoadedAssetDescriptorsByType(type);
632
+ const matching_assets = this.#getLoadedAssetDescriptorsByType(type);
697
633
 
698
634
  if (matching_assets.length > 0) {
699
635
  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')}`);
@@ -708,7 +644,7 @@ export class AssetManager {
708
644
  */
709
645
  unregisterTransformer(type, transformer) {
710
646
 
711
- const transformers = this.transformers[type];
647
+ const transformers = this.#transformers[type];
712
648
 
713
649
  if (transformers === undefined) {
714
650
  // not found
@@ -721,7 +657,7 @@ export class AssetManager {
721
657
  }
722
658
 
723
659
  // check for loaded assets
724
- const matching_assets = this.__getLoadedAssetDescriptorsByType(type);
660
+ const matching_assets = this.#getLoadedAssetDescriptorsByType(type);
725
661
 
726
662
  if (matching_assets.length > 0) {
727
663
  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')}`);
@@ -760,11 +696,11 @@ export class AssetManager {
760
696
 
761
697
  } else {
762
698
 
763
- await loader.link(this, this.__engine);
699
+ await loader.link(this, this.#engine);
764
700
 
765
701
  }
766
702
 
767
- this.loaders[type] = loader;
703
+ this.#loaders[type] = loader;
768
704
 
769
705
  return loader;
770
706
  }
@@ -783,7 +719,7 @@ export class AssetManager {
783
719
  }
784
720
 
785
721
  // first remove the loader from registry so no further asset requests can be made
786
- delete this.loaders[type];
722
+ delete this.#loaders[type];
787
723
 
788
724
  // TODO address all pending requests, possibly waiting for all of them to finalize
789
725
 
@@ -819,7 +755,7 @@ export class AssetManager {
819
755
  isFailed(path, type) {
820
756
  const ad = new AssetDescription(path, type);
821
757
 
822
- return this.failures.has(ad);
758
+ return this.#failures.has(ad);
823
759
  }
824
760
 
825
761
  /**
@@ -831,7 +767,7 @@ export class AssetManager {
831
767
  assert.typeOf(alias, 'string', 'alias');
832
768
 
833
769
  // resolve alias
834
- const assetDescription = this.aliases.get(alias);
770
+ const assetDescription = this.#aliases.get(alias);
835
771
 
836
772
  if (assetDescription === undefined) {
837
773
  return new Promise.reject(`Alias '${alias}' not found`);
@@ -849,7 +785,7 @@ export class AssetManager {
849
785
 
850
786
  // todo consider cloning result to protect against mutation
851
787
 
852
- return this.aliases.get(alias);
788
+ return this.#aliases.get(alias);
853
789
 
854
790
  }
855
791
 
@@ -866,7 +802,7 @@ export class AssetManager {
866
802
 
867
803
  const assetDescription = new AssetDescription(path, type);
868
804
 
869
- this.aliases.set(alias, assetDescription);
805
+ this.#aliases.set(alias, assetDescription);
870
806
  }
871
807
  }
872
808