@woosh/meep-engine 2.49.6 → 2.49.8

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 (85) hide show
  1. package/editor/enableEditor.js +1 -8
  2. package/package.json +1 -1
  3. package/samples/terrain/editor.js +2 -2
  4. package/src/core/cache/Cache.js +1 -1
  5. package/src/core/cache/LoadingCache.d.ts +2 -0
  6. package/src/core/cache/LoadingCache.js +45 -18
  7. package/src/core/collection/HashSet.js +1 -1
  8. package/src/core/collection/table/RowFirstTableSpec.js +110 -92
  9. package/src/core/collection/table/RowFirstTableSpec.spec.js +49 -0
  10. package/src/core/color/Color.d.ts +4 -2
  11. package/src/core/color/Color.js +7 -8
  12. package/src/core/color/Color.spec.js +93 -0
  13. package/src/core/color/hex2rgb.spec.js +10 -0
  14. package/src/core/color/rgb2hex.js +1 -1
  15. package/src/core/color/rgb2hex.spec.js +13 -0
  16. package/src/core/fsm/simple/SimpleStateMachine.spec.js +75 -0
  17. package/src/core/fsm/simple/SimpleStateMachineDescription.js +1 -1
  18. package/src/core/fsm/simple/SimpleStateMachineDescription.spec.js +32 -0
  19. package/src/core/geom/2d/Rectangle.spec.js +51 -0
  20. package/src/core/geom/3d/aabb/aabb3_intersects_ray.spec.js +90 -0
  21. package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.spec.js +61 -0
  22. package/src/core/geom/3d/morton/mortonEncode_magicbits.js +1 -34
  23. package/src/core/geom/3d/morton/split_by_2.js +17 -0
  24. package/src/core/geom/3d/morton/split_by_3.js +16 -0
  25. package/src/core/geom/3d/plane/computePlaneLineIntersection.js +6 -1
  26. package/src/core/geom/3d/sphere/sphere_intersects_ray.spec.js +11 -0
  27. package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.spec.js +8 -0
  28. package/src/core/geom/3d/topology/samples/sampleFloodFill.js +3 -3
  29. package/src/core/geom/3d/topology/struct/binary/io/OrderedEdge.js +1 -1
  30. package/src/core/geom/random/randomPointOnBox.spec.js +57 -0
  31. package/src/core/math/computeGreatestCommonDivisor.spec.js +9 -0
  32. package/src/core/math/statistics/computeStatisticalMean.spec.js +9 -0
  33. package/src/core/math/statistics/halton_sequence.spec.js +6 -1
  34. package/src/core/model/node-graph/node/Port.spec.js +10 -1
  35. package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.js +5 -8
  36. package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.spec.js +41 -0
  37. package/src/core/model/reactive/trigger/BlackboardTrigger.js +5 -0
  38. package/src/core/model/reactive/trigger/BlackboardTrigger.spec.js +24 -0
  39. package/src/core/parser/simple/readBooleanToken.js +38 -0
  40. package/src/core/parser/simple/readHexToken.js +95 -0
  41. package/src/core/parser/simple/readHexToken.spec.js +21 -0
  42. package/src/core/parser/simple/readIdentifierToken.js +43 -0
  43. package/src/core/parser/simple/readIdentifierToken.spec.js +32 -0
  44. package/src/core/parser/simple/readLiteralToken.js +96 -0
  45. package/src/core/parser/simple/readNumberToken.js +73 -0
  46. package/src/core/parser/simple/readNumberToken.spec.js +17 -0
  47. package/src/core/parser/simple/readReferenceToken.js +48 -0
  48. package/src/core/parser/simple/readReferenceToken.spec.js +18 -0
  49. package/src/core/parser/simple/readStringToken.js +94 -0
  50. package/src/core/parser/simple/readStringToken.spec.js +57 -0
  51. package/src/core/parser/simple/{readUnsignedInteger.js → readUnsignedIntegerToken.js} +1 -1
  52. package/src/core/parser/simple/readUnsignedIntegerToken.spec.js +6 -0
  53. package/src/core/process/executor/ConcurrentExecutor.js +147 -234
  54. package/src/engine/Engine.d.ts +4 -2
  55. package/src/engine/Engine.js +62 -41
  56. package/src/engine/Engine.spec.js +11 -0
  57. package/src/engine/InputEngine.js +12 -0
  58. package/src/engine/graphics/GraphicsEngine.js +2 -13
  59. package/src/engine/graphics/ecs/compileAllMaterials.js +1 -1
  60. package/src/engine/graphics/ecs/mesh/createTaskWaitForMeshesToLoad.js +1 -1
  61. package/src/engine/graphics/impostors/octahedral/ImpostorBaker.js +1 -1
  62. package/src/engine/graphics/load_and_set_cubemap_v0.js +21 -0
  63. package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
  64. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +3 -5
  65. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +2 -4
  66. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
  67. package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +1 -1
  68. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +2 -4
  69. package/src/engine/graphics/sh3/prototypeSH3Probe.js +4 -4
  70. package/src/engine/graphics/texture/sampler/copy_Sampler2D_channel_data.js +4 -3
  71. package/src/engine/graphics/texture/virtual/VirtualTexture.js +9 -0
  72. package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +5 -4
  73. package/src/engine/graphics/texture/virtual/tile/TileLoader.js +5 -0
  74. package/src/engine/input/devices/PointerDevice.spec.js +7 -0
  75. package/src/engine/intelligence/blackboard/Blackboard.d.ts +4 -0
  76. package/src/engine/intelligence/blackboard/Blackboard.js +11 -0
  77. package/src/engine/platform/InMemoryEnginePlatform.js +20 -0
  78. package/src/engine/save/Storage.d.ts +7 -7
  79. package/src/engine/save/storage/InMemoryStorage.js +34 -0
  80. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +2 -2
  81. package/src/view/tooltip/gml/parser/readReferenceValueToken.js +2 -2
  82. package/src/core/parser/simple/SimpleParser.js +0 -464
  83. package/src/core/parser/simple/SimpleParser.spec.js +0 -105
  84. /package/src/core/collection/{IteratorUtils.js → collectIteratorValueToArray.js} +0 -0
  85. /package/src/core/color/{ColorUtils.js → parseColor.js} +0 -0
@@ -0,0 +1,6 @@
1
+ import { readUnsignedIntegerToken } from "./readUnsignedIntegerToken.js";
2
+
3
+ test("sequence with all digits", () => {
4
+ const token = readUnsignedIntegerToken("1234567890", 0, 10);
5
+ expect(token.value).toEqual(1234567890);
6
+ });
@@ -7,7 +7,6 @@ import { IllegalStateException } from "../../fsm/exceptions/IllegalStateExceptio
7
7
  import { objectKeyByValue } from "../../model/object/objectKeyByValue.js";
8
8
  import { TaskSignal } from "../task/TaskSignal.js";
9
9
  import TaskState from "../task/TaskState.js";
10
- import { clamp } from "../../math/clamp.js";
11
10
 
12
11
  /**
13
12
  *
@@ -22,13 +21,20 @@ function isGroup(t) {
22
21
  * @class
23
22
  */
24
23
  class ConcurrentExecutor {
24
+ #cycle_count = 0;
25
+ /**
26
+ * Handle of the last scheduled `setTimeout`
27
+ * @type {number}
28
+ */
29
+ #timeout_handle = -1;
30
+
25
31
  /**
26
32
  *
27
33
  * @param {number} [quietTime] in milliseconds
28
34
  * @param {number} [workTime] in milliseconds
29
35
  * @constructor
30
36
  */
31
- constructor(quietTime=1, workTime=15) {
37
+ constructor(quietTime = 1, workTime = 15) {
32
38
  /**
33
39
  *
34
40
  * @type {number}
@@ -58,6 +64,8 @@ class ConcurrentExecutor {
58
64
  completed: new Signal()
59
65
  };
60
66
 
67
+ this.busy = false;
68
+
61
69
  /**
62
70
  *
63
71
  * @type {number|SchedulingPolicy}
@@ -298,142 +306,188 @@ class ConcurrentExecutor {
298
306
  }
299
307
 
300
308
  /**
301
- * kicks the scheduler into action, this is an internal method and should not be called from outside
302
- * @private
309
+ *
310
+ * @return {Task|undefined}
303
311
  */
304
- prod() {
305
- const self = this;
312
+ #pick_next_task() {
313
+ const ready = this.queueReady;
314
+
315
+ switch (this.policy) {
316
+ case ConcurrentExecutor.POLICY.ROUND_ROBIN:
317
+ return ready[this.#cycle_count % ready.length];
318
+ default:
319
+ console.warn('Unknown scheduling policy: ', this.policy, 'Defaulting to sequential');
320
+ // fallthrough
321
+ case ConcurrentExecutor.POLICY.SEQUENTIAL:
322
+ return ready[0];
323
+ }
324
+ }
325
+
326
+ /**
327
+ *
328
+ * @param {Task} task
329
+ */
330
+ #complete_task(task) {
331
+ const readyTasks = this.queueReady;
332
+
333
+ const taskIndex = readyTasks.indexOf(task);
334
+
335
+ if (taskIndex !== -1) {
336
+ readyTasks.splice(taskIndex, 1);
337
+ } else {
338
+ console.error("Failed to remove ready task, not found in the ready queue", task, readyTasks.slice());
339
+ }
340
+
306
341
 
307
- let i = 0;
342
+ task.state.set(TaskState.SUCCEEDED);
343
+ task.on.completed.send1(this);
308
344
 
309
345
  this.resolveTasks();
310
346
 
347
+ this.on.task_completed.send1(task);
348
+ // console.warn(`Task complete '${task.name}', cycles=${task.__executedCycleCount}, time=${task.__executedCpuTime}`);
349
+
350
+ }
351
+
352
+ /**
353
+ *
354
+ * @param {Task} task
355
+ * @param {*} [reason]
356
+ */
357
+ #fail_task(task, reason) {
311
358
  const readyTasks = this.queueReady;
312
- let readyTaskCount;
359
+ const taskIndex = readyTasks.indexOf(task);
313
360
 
314
- function updateTaskCount() {
315
- readyTaskCount = readyTasks.length;
361
+ if (taskIndex !== -1) {
362
+ readyTasks.splice(taskIndex, 1);
363
+ } else {
364
+ console.error("Failed to remove ready task, not found in the ready queue", task, readyTasks.slice());
316
365
  }
317
366
 
318
- function pickNextTaskRoundRobin() {
319
- return readyTasks[i++ % readyTaskCount];
320
- }
367
+ task.state.set(TaskState.FAILED);
368
+ task.on.failed.send1(reason);
321
369
 
322
- function pickNextTaskSequential() {
323
- return readyTasks[0];
324
- }
370
+ this.resolveTasks();
325
371
 
326
- /**
327
- * @type {function():Task}
328
- */
329
- let pickNextTask;
372
+ this.on.task_completed.send1(task);
373
+ }
330
374
 
331
- switch (this.policy) {
332
- case ConcurrentExecutor.POLICY.ROUND_ROBIN:
333
- pickNextTask = pickNextTaskRoundRobin;
334
- break;
335
- case ConcurrentExecutor.POLICY.SEQUENTIAL:
336
- pickNextTask = pickNextTaskSequential;
337
- break;
338
- default:
339
- console.warn('Unknown scheduling policy: ', this.policy, 'Defaulting to sequential');
340
- pickNextTask = pickNextTaskSequential;
341
- break;
342
- }
375
+ /**
376
+ *
377
+ * @param {Task} task
378
+ * @param {number} time in milliseconds
379
+ * @param {function} completionCallback
380
+ * @param {function} failureCallback
381
+ */
382
+ #runTaskForTimeMonitored(task, time) {
383
+ let cycle_count = 0;
343
384
 
344
385
  /**
345
386
  *
346
- * @param {Task} task
387
+ * @type {function(): TaskSignal}
347
388
  */
348
- function completeTask(task) {
389
+ const cycle = task.cycle;
349
390
 
350
- const taskIndex = readyTasks.indexOf(task);
391
+ const startTime = performance.now();
351
392
 
352
- if (taskIndex !== -1) {
353
- readyTasks.splice(taskIndex, 1);
354
- } else {
355
- console.error("Failed to remove ready task, not found in the ready queue", task, readyTasks.slice());
356
- }
393
+ const endTime = startTime + time;
357
394
 
395
+ //We use tiny delta to avoid problems with timer accuracy on some systems that result in 0 measured execution time
396
+ let t = startTime + 0.000001;
358
397
 
359
- task.state.set(TaskState.SUCCEEDED);
360
- task.on.completed.send1(self);
398
+ let signal;
361
399
 
362
- self.resolveTasks();
363
- updateTaskCount();
400
+ while (t < endTime) {
401
+ cycle_count++;
364
402
 
365
- self.on.task_completed.send1(task);
366
- // console.warn(`Task complete '${task.name}', cycles=${task.__executedCycleCount}, time=${task.__executedCpuTime}`);
367
- }
403
+ signal = cycle();
404
+ t = performance.now();
368
405
 
369
- /**
370
- *
371
- * @param {Task} task
372
- * @param {*} reason
373
- */
374
- function failTask(task, reason) {
375
- const taskIndex = readyTasks.indexOf(task);
406
+ if (signal === TaskSignal.Continue) {
407
+ continue;
408
+ }
409
+
410
+ if (signal === TaskSignal.Yield) {
411
+ //give up current quanta
412
+ break;
413
+ }
376
414
 
377
- if (taskIndex !== -1) {
378
- readyTasks.splice(taskIndex, 1);
415
+ if (signal === TaskSignal.EndSuccess) {
416
+ break;
417
+ } else if (signal === TaskSignal.EndFailure) {
418
+ break;
379
419
  } else {
380
- console.error("Failed to remove ready task, not found in the ready queue", task, readyTasks.slice());
420
+ throw new Error(`Task '${task.name}' produced unknown signal: ` + signal);
381
421
  }
422
+ }
382
423
 
383
- task.state.set(TaskState.FAILED);
384
- task.on.failed.dispatch(reason);
424
+ const executionDuration = t - startTime;
385
425
 
386
- self.resolveTasks();
387
- updateTaskCount();
426
+ task.__executedCpuTime += executionDuration;
427
+ task.__executedCycleCount += cycle_count;
388
428
 
389
- self.on.task_completed.send1(task);
429
+ if (signal === TaskSignal.EndSuccess) {
430
+ this.#complete_task(task);
431
+ } else if (signal === TaskSignal.EndFailure) {
432
+ this.#fail_task(task, "Task signalled failure");
390
433
  }
391
434
 
392
- function executeTimeSlice() {
393
- let sliceTimeLeft = self.workTime;
435
+ return executionDuration;
436
+ }
394
437
 
395
- let executionTime = 0;
438
+ #bound_executeTimeSlice = this.#executeTimeSlice.bind(this);
396
439
 
397
- while (readyTaskCount > 0) {
398
- const task = pickNextTask();
440
+ #executeTimeSlice() {
441
+ let sliceTimeLeft = this.workTime;
399
442
 
400
- if (task === undefined) {
401
- console.warn('Next task not found, likely result of removing task mid-execution');
402
- break;
403
- }
443
+ let executionTime = 0;
404
444
 
405
- try {
406
- executionTime = runTaskForTimeMonitored(task, sliceTimeLeft, completeTask, failTask);
407
- } catch (e) {
408
- console.error(`Task threw an exception`, task, e);
409
- failTask(task, e);
410
- }
445
+ const queueReady = this.queueReady;
411
446
 
412
- //make sure that execution time that we subtract from current CPU slice is always reducing the slice
413
- sliceTimeLeft -= Math.max(executionTime, 1);
447
+ while (queueReady.length > 0) {
448
+ const task = this.#pick_next_task();
414
449
 
415
- if (sliceTimeLeft <= 0) {
416
- break;
417
- }
450
+ if (task === undefined) {
451
+ console.warn('Next task not found, likely result of removing task mid-execution');
452
+ break;
418
453
  }
419
454
 
420
- //update task count
421
- updateTaskCount();
455
+ try {
456
+ executionTime = this.#runTaskForTimeMonitored(task, sliceTimeLeft);
457
+ } catch (e) {
458
+ console.error(`Task threw an exception`, task, e);
459
+ this.#fail_task(task, e);
460
+ }
422
461
 
423
- if (readyTaskCount > 0) {
424
- //schedule next time slice
425
- setTimeout(executeTimeSlice, self.quietTime);
426
- } else {
427
- self.busy = false;
428
- self.on.completed.send0();
462
+ this.#cycle_count++;
463
+
464
+ //make sure that execution time that we subtract from current CPU slice is always reducing the slice
465
+ sliceTimeLeft -= Math.max(executionTime, 1);
466
+
467
+ if (sliceTimeLeft <= 0) {
468
+ break;
429
469
  }
430
470
  }
431
471
 
432
- updateTaskCount();
472
+ if (this.queueReady.length === 0) {
473
+ this.busy = false;
474
+ this.on.completed.send0();
475
+ } else {
476
+ //schedule next time slice
477
+ this.#timeout_handle = setTimeout(this.#bound_executeTimeSlice, this.quietTime);
478
+ }
479
+ }
480
+
481
+ /**
482
+ * kicks the scheduler into action, this is an internal method and should not be called from outside
483
+ * @private
484
+ */
485
+ prod() {
486
+ this.resolveTasks();
433
487
 
434
- if (!this.busy && readyTaskCount > 0) {
488
+ if (!this.busy && this.queueReady.length > 0) {
435
489
  this.busy = true;
436
- executeTimeSlice();
490
+ this.#executeTimeSlice();
437
491
  }
438
492
 
439
493
  }
@@ -459,147 +513,6 @@ const SchedulingPolicy = {
459
513
 
460
514
  ConcurrentExecutor.POLICY = SchedulingPolicy;
461
515
 
462
- /**
463
- *
464
- * @param {Task} task
465
- * @param {number} time in milliseconds
466
- * @param {function} completionCallback
467
- * @param {function} failureCallback
468
- */
469
- function runTaskForTimeEstimated(task, time, completionCallback, failureCallback) {
470
- let cycle_count = 0;
471
-
472
- /**
473
- *
474
- * @type {function(): TaskSignal}
475
- */
476
- const cycle = task.cycle;
477
-
478
- const startTime = performance.now();
479
-
480
- let signal;
481
-
482
- const cycle_time = task.__executedCpuTime / task.__executedCycleCount;
483
-
484
- const estimated_cycles = clamp(Math.ceil(time / cycle_time), 1, 10000);
485
-
486
- while (cycle_count < estimated_cycles) {
487
- cycle_count++
488
-
489
- signal = cycle();
490
-
491
- if (signal === TaskSignal.Continue) {
492
- continue;
493
- }
494
-
495
- if (signal === TaskSignal.Yield) {
496
- //give up current quanta
497
- break;
498
- }
499
-
500
- if (signal === TaskSignal.EndSuccess) {
501
- break;
502
- } else if (signal === TaskSignal.EndFailure) {
503
- break;
504
- } else {
505
- throw new Error(`Task '${task.name}' produced unknown signal: ` + signal);
506
- }
507
- }
508
-
509
- //We use tiny delta to avoid problems with timer accuracy on some systems that result in 0 measured execution time
510
- const endTime = performance.now() + 0.000001;
511
-
512
- const executionDuration = endTime - startTime;
513
-
514
- task.__executedCpuTime += executionDuration;
515
- task.__executedCycleCount += cycle_count;
516
-
517
- if (signal === TaskSignal.EndSuccess) {
518
- completionCallback(task);
519
- } else if (signal === TaskSignal.EndFailure) {
520
- failureCallback(task, "Task signalled failure");
521
- }
522
-
523
- return executionDuration;
524
- }
525
-
526
- /**
527
- *
528
- * @param {Task} task
529
- * @param {number} time in milliseconds
530
- * @param {function} completionCallback
531
- * @param {function} failureCallback
532
- */
533
- function runTaskForTime2(task, time, completionCallback, failureCallback) {
534
- if (task.__executedCycleCount > 1000) {
535
- return runTaskForTimeEstimated(task, time, completionCallback, failureCallback);
536
- } else {
537
- return runTaskForTimeMonitored(task, time, completionCallback, failureCallback);
538
- }
539
- }
540
-
541
- /**
542
- *
543
- * @param {Task} task
544
- * @param {number} time in milliseconds
545
- * @param {function} completionCallback
546
- * @param {function} failureCallback
547
- */
548
- function runTaskForTimeMonitored(task, time, completionCallback, failureCallback) {
549
- let cycle_count = 0;
550
-
551
- /**
552
- *
553
- * @type {function(): TaskSignal}
554
- */
555
- const cycle = task.cycle;
556
-
557
- const startTime = performance.now();
558
-
559
- const endTime = startTime + time;
560
-
561
- //We use tiny delta to avoid problems with timer accuracy on some systems that result in 0 measured execution time
562
- let t = startTime + 0.000001;
563
-
564
- let signal;
565
-
566
- while (t < endTime) {
567
- cycle_count++;
568
-
569
- signal = cycle();
570
- t = performance.now();
571
-
572
- if (signal === TaskSignal.Continue) {
573
- continue;
574
- }
575
-
576
- if (signal === TaskSignal.Yield) {
577
- //give up current quanta
578
- break;
579
- }
580
-
581
- if (signal === TaskSignal.EndSuccess) {
582
- break;
583
- } else if (signal === TaskSignal.EndFailure) {
584
- break;
585
- } else {
586
- throw new Error(`Task '${task.name}' produced unknown signal: ` + signal);
587
- }
588
- }
589
-
590
- const executionDuration = t - startTime;
591
-
592
- task.__executedCpuTime += executionDuration;
593
- task.__executedCycleCount += cycle_count;
594
-
595
- if (signal === TaskSignal.EndSuccess) {
596
- completionCallback(task);
597
- } else if (signal === TaskSignal.EndFailure) {
598
- failureCallback(task, "Task signalled failure");
599
- }
600
-
601
- return executionDuration;
602
- }
603
516
 
604
517
  const ResolutionType = {
605
518
  READY: 0,
@@ -12,7 +12,9 @@ import {EnginePluginManager} from "./plugin/EnginePluginManager";
12
12
  import ConcurrentExecutor from "../core/process/executor/ConcurrentExecutor";
13
13
 
14
14
  export interface IEngineInitializationOptions {
15
- entityManager?: EntityManager
15
+ entityManager?: EntityManager,
16
+ enableAudio?: boolean
17
+ enableGraphics?: boolean
16
18
  }
17
19
 
18
20
  export default class Engine {
@@ -25,7 +27,7 @@ export default class Engine {
25
27
  public readonly sound: SoundEngine
26
28
  public readonly graphics: GraphicsEngine
27
29
  public readonly devices: { keyboard: KeyboardDevice, pointer: PointerDevice }
28
- public readonly assetManager: AssetManager
30
+ public readonly assetManager: AssetManager<Engine>
29
31
  public readonly ticker: Ticker
30
32
  public readonly plugins: EnginePluginManager
31
33
  public readonly executor: ConcurrentExecutor
@@ -5,7 +5,6 @@
5
5
  import ConcurrentExecutor from '../core/process/executor/ConcurrentExecutor.js';
6
6
 
7
7
  import { AssetManager } from './asset/AssetManager.js';
8
- import InputEngine from './InputEngine.js';
9
8
  import { GraphicsEngine } from './graphics/GraphicsEngine.js';
10
9
  import SoundEngine from './sound/SoundEngine.js';
11
10
  import { PerspectiveCamera as ThreePerspectiveCamera } from 'three';
@@ -49,9 +48,15 @@ class Engine {
49
48
  *
50
49
  * @param {EnginePlatform} platform
51
50
  * @param {EntityManager} [entityManager]
51
+ * @param enableGraphics
52
+ * @param enableAudio
52
53
  * @constructor
53
54
  */
54
- constructor(platform, { entityManager } = {}) {
55
+ constructor(platform, {
56
+ entityManager,
57
+ enableGraphics = true,
58
+ enableAudio = true
59
+ } = {}) {
55
60
  assert.defined(platform, 'platform');
56
61
 
57
62
  /**
@@ -105,7 +110,7 @@ class Engine {
105
110
  * @type {AssetManager<Engine>}
106
111
  */
107
112
  this.assetManager = new AssetManager({
108
- context:this,
113
+ context: this,
109
114
  executor: this.executor
110
115
  });
111
116
 
@@ -159,11 +164,6 @@ class Engine {
159
164
  });
160
165
  }
161
166
 
162
-
163
- this.initialize();
164
- }
165
-
166
- initialize() {
167
167
  // initialize performance metrics
168
168
  this.performance.create({
169
169
  name: METRIC_ID_RENDER
@@ -218,29 +218,39 @@ class Engine {
218
218
  this.camera = new ThreePerspectiveCamera(45, innerWidth / innerHeight, 1, 50);
219
219
 
220
220
 
221
- /**
222
- *
223
- * @type {GraphicsEngine}
224
- */
225
- const ge = this.graphics = new GraphicsEngine(this.camera, this.entityManager);
221
+ if (enableGraphics !== false) {
226
222
 
227
- try {
228
- ge.start();
229
- } catch (e) {
230
- logger.info("Failed to start GraphicEngine: ", e);
231
- }
223
+ const graphicsEngine = new GraphicsEngine(this.camera, this.entityManager);
232
224
 
233
- this.inputEngine = new InputEngine(ge.domElement, window);
225
+ /**
226
+ *
227
+ * @type {GraphicsEngine}
228
+ */
229
+ this.graphics = graphicsEngine;
234
230
 
235
- //sound engine
236
- const soundEngine = new SoundEngine();
237
- soundEngine.volume = 1;
231
+ try {
232
+ graphicsEngine.start();
233
+ } catch (e) {
234
+ logger.info("Failed to start GraphicEngine: ", e);
235
+ }
238
236
 
239
- /**
240
- *
241
- * @type {SoundEngine}
242
- */
243
- this.sound = soundEngine;
237
+ } else {
238
+ logger.info('enableGraphics option is not set, no graphics engine will be created');
239
+ }
240
+
241
+ if (enableAudio !== false) {
242
+ //sound engine
243
+ const soundEngine = new SoundEngine();
244
+ soundEngine.volume = 1;
245
+
246
+ /**
247
+ *
248
+ * @type {SoundEngine}
249
+ */
250
+ this.sound = soundEngine;
251
+ } else {
252
+ logger.info('enableAudio option is not set, no audio engine will be created');
253
+ }
244
254
 
245
255
  /**
246
256
  * Graphical User Interface engine
@@ -281,14 +291,20 @@ class Engine {
281
291
  this.plugins.initialize(this);
282
292
  }
283
293
 
294
+
295
+ get inputEngine() {
296
+ throw new Error('Deprecated, use .devices instead');
297
+ }
298
+
299
+ /**
300
+ * @deprecated
301
+ */
284
302
  get grid() {
285
303
  throw new Error('Deprecated, use systems/components to achieve the same functionality as before');
286
304
  }
287
305
 
288
306
  initializeViews() {
289
307
 
290
- const viewport = this.graphics.viewport;
291
-
292
308
  const gameView = new EmptyView();
293
309
 
294
310
  gameView.addClass('game-view');
@@ -299,23 +315,28 @@ class Engine {
299
315
  position: "absolute",
300
316
  pointerEvents: "none"
301
317
  });
302
-
303
- viewport.css({
304
- pointerEvents: "auto"
305
- });
306
-
307
318
  this.gameView = gameView;
308
319
 
309
- gameView.addChild(viewport);
310
320
 
311
321
  this.viewStack = new ViewStack();
312
- this.viewStack.push(gameView,'game-view');
322
+ this.viewStack.push(gameView, 'game-view');
313
323
 
314
- //bind size of renderer viewport to game view
315
- viewport.bindSignal(gameView.size.onChanged, viewport.size.set.bind(viewport.size));
316
- gameView.on.linked.add(function () {
317
- viewport.size.copy(gameView.size);
318
- });
324
+ if (this.graphics !== undefined) {
325
+
326
+ const viewport = this.graphics.viewport;
327
+
328
+ viewport.css({
329
+ pointerEvents: "auto"
330
+ });
331
+
332
+ gameView.addChild(viewport);
333
+ //bind size of renderer viewport to game view
334
+ viewport.bindSignal(gameView.size.onChanged, viewport.size.set.bind(viewport.size));
335
+ gameView.on.linked.add(function () {
336
+ viewport.size.copy(gameView.size);
337
+ });
338
+
339
+ }
319
340
  }
320
341
 
321
342
  initializeSettings() {
@@ -0,0 +1,11 @@
1
+ import Engine from "./Engine.js";
2
+ import { InMemoryEnginePlatform } from "./platform/InMemoryEnginePlatform.js";
3
+
4
+ test("constructor does not throw", () => {
5
+ const platform = new InMemoryEnginePlatform();
6
+
7
+ expect(() => new Engine(platform, {
8
+ enableAudio: false,
9
+ enableGraphics: false
10
+ })).not.toThrow();
11
+ });
@@ -4,8 +4,20 @@
4
4
  * Time: 20:15
5
5
  */
6
6
  import { KeyCodes } from './input/devices/KeyCodes.js';
7
+ import { assert } from "../core/assert.js";
7
8
 
9
+ /**
10
+ * @deprecated use PointerDevice and KeyboardDevice respectively
11
+ * @param pointerContext
12
+ * @param keyContext
13
+ * @constructor
14
+ */
8
15
  const InputEngine = function (pointerContext, keyContext) {
16
+ assert.defined(pointerContext, 'pointerContext');
17
+ assert.defined(keyContext, 'keyContext');
18
+
19
+ console.warn('deprecated, use PointerDevice and KeyboardDevice instead');
20
+
9
21
  const keyMap = [];
10
22
  const mouseMap = {};
11
23