@woosh/meep-engine 2.47.23 → 2.47.26

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 (31) hide show
  1. package/build/meep.cjs +544 -342
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +544 -342
  4. package/editor/tools/SelectionTool.js +17 -17
  5. package/editor/view/EditorView.js +4 -5
  6. package/editor/view/ecs/EntityList.js +0 -2
  7. package/package.json +1 -1
  8. package/src/core/geom/3d/topology/samples/sampleFloodFill.js +8 -8
  9. package/src/core/json/abstractJSONSerializer.js +1 -1
  10. package/src/engine/ecs/EntityComponentDataset.js +28 -3
  11. package/src/engine/ecs/EntityManager.js +264 -221
  12. package/src/engine/ecs/System.d.ts +2 -0
  13. package/src/engine/ecs/System.js +37 -30
  14. package/src/engine/ecs/gui/menu/radial/RadialContextMenu.js +0 -4
  15. package/src/engine/ecs/systems/TimerSystem.js +61 -41
  16. package/src/engine/ecs/terrain/util/obtainTerrain.js +2 -3
  17. package/src/engine/graphics/GraphicsEngine.js +4 -3
  18. package/src/engine/graphics/ecs/camera/Camera.js +37 -0
  19. package/src/engine/graphics/ecs/camera/filter/setup_filtered_camera_controller.js +78 -0
  20. package/src/engine/graphics/ecs/camera/pp/NOTES.md +48 -0
  21. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +164 -0
  22. package/src/engine/graphics/ecs/camera/pp/Perfect_Panning.png +0 -0
  23. package/src/engine/graphics/ecs/camera/pp/Zooming.png +0 -0
  24. package/src/engine/graphics/ecs/camera/pp/pan_a.png +0 -0
  25. package/src/engine/graphics/ecs/camera/pp/pan_b.png +0 -0
  26. package/src/engine/graphics/ecs/mesh/MeshSystem.js +1 -1
  27. package/src/engine/graphics/make_ray_from_viewport_position.js +28 -0
  28. package/src/engine/input/devices/PointerDevice.js +32 -0
  29. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.js +17 -8
  30. package/src/engine/intelligence/behavior/decorator/RepeatBehaviorSerializationAdapter.js +2 -2
  31. package/src/engine/intelligence/behavior/primitive/SucceedingBehavior.js +9 -5
@@ -70580,33 +70580,32 @@ function array_copy_unique(source, source_position, destination, destination_pos
70580
70580
  * @template C
70581
70581
  */
70582
70582
  class System {
70583
- constructor() {
70584
70583
 
70585
- /**
70586
- *
70587
- * @type {EntityManager}
70588
- */
70589
- this.entityManager = null;
70584
+ /**
70585
+ * @protected
70586
+ * @type {EntityManager}
70587
+ */
70588
+ entityManager = null;
70590
70589
 
70591
- /**
70592
- *
70593
- * @type {ObservedValue.<System.State>}
70594
- */
70595
- this.state = new ObservedValue(System.State.INITIAL);
70590
+ /**
70591
+ * @readonly
70592
+ * @type {ObservedValue.<System.State>}
70593
+ */
70594
+ state = new ObservedValue(System.State.INITIAL);
70596
70595
 
70597
- /**
70598
- * Other components which have to be present before the system links component
70599
- * @type {Array}
70600
- */
70601
- this.dependencies = [];
70596
+ /**
70597
+ * Other components which have to be present before the system links component
70598
+ * @type {Array}
70599
+ */
70600
+ dependencies = [];
70601
+
70602
+ /**
70603
+ * Component types that are used internally by the system
70604
+ * Declaring this helps EntityManager to ensure that all relevant component types are properly registered for the system
70605
+ * @type {Array}
70606
+ */
70607
+ components_used = [];
70602
70608
 
70603
- /**
70604
- * Component types that are used internally by the system
70605
- * Declaring this helps EntityManager to ensure that all relevant component types are properly registered for the system
70606
- * @type {Array}
70607
- */
70608
- this.components_used = [];
70609
- }
70610
70609
 
70611
70610
  /**
70612
70611
  * @returns {[]}
@@ -70637,15 +70636,22 @@ class System {
70637
70636
 
70638
70637
  }
70639
70638
 
70640
- /**
70641
- *
70642
- * @param {number} timeDelta Time in seconds
70643
- */
70644
- update(timeDelta) {
70645
-
70646
- }
70647
70639
  }
70648
70640
 
70641
+ /**
70642
+ * Fixed update function, every step happens with the same exact time increment
70643
+ * useful for systems that must have a fixed time step to be predictable and stable, such as physics
70644
+ * @param {number} timeDelta in seconds
70645
+ */
70646
+ System.prototype.fixedUpdate = noop; // by assigning NO-OP we enable a simple check, whether running the update would be useful
70647
+
70648
+
70649
+ /**
70650
+ * This update is generally synchronized with the render loop
70651
+ * @param {number} timeDelta Time in seconds
70652
+ */
70653
+ System.prototype.update = noop; // by assigning NO-OP we enable a simple check, whether running the update would be useful
70654
+
70649
70655
  Object.defineProperties(System.prototype, {
70650
70656
  /**
70651
70657
  * @deprecated
@@ -70995,6 +71001,113 @@ const ProjectionType = {
70995
71001
  Orthographic: "orthographic"
70996
71002
  };
70997
71003
 
71004
+ /**
71005
+ * Created by Alex on 20/02/2017.
71006
+ */
71007
+
71008
+ /**
71009
+ *
71010
+ * @param {Vector3} out Result will be written here
71011
+ * @param {number} originX Ray origin
71012
+ * @param {number} originY Ray origin
71013
+ * @param {number} originZ Ray origin
71014
+ * @param {number} directionX Ray direction
71015
+ * @param {number} directionY Ray direction
71016
+ * @param {number} directionZ Ray direction
71017
+ * @param {number} normalX Plane normal
71018
+ * @param {number} normalY Plane normal
71019
+ * @param {number} normalZ Plane normal
71020
+ * @param {number} dist Plane distance
71021
+ * @returns {boolean} true if intersection is found, false otherwise
71022
+ */
71023
+ function computePlaneRayIntersection(out, originX, originY, originZ, directionX, directionY, directionZ, normalX, normalY, normalZ, dist) {
71024
+ const denom = v3_dot(directionX, directionY, directionZ, normalX, normalY, normalZ);
71025
+
71026
+ const p = v3_dot(normalX, normalY, normalZ, originX, originY, originZ) + dist;
71027
+
71028
+ if (denom !== 0) {
71029
+
71030
+ const t = -p / denom;
71031
+
71032
+ if (t < 0) {
71033
+ return false;
71034
+ }
71035
+
71036
+ out.set(
71037
+ directionX * t + originX,
71038
+ directionY * t + originY,
71039
+ directionZ * t + originZ
71040
+ );
71041
+
71042
+ return true;
71043
+
71044
+ } else {
71045
+
71046
+ if (p === 0) {
71047
+
71048
+ out.set(originX, originY, originZ);
71049
+
71050
+ return true;
71051
+
71052
+ } else {
71053
+
71054
+ //no intersection
71055
+ return false;
71056
+
71057
+ }
71058
+
71059
+ }
71060
+ }
71061
+
71062
+ /**
71063
+ *
71064
+ * @param {Float32Array|number[]|vec3} result
71065
+ * @param {number} result_offset
71066
+ * @param {number} x0
71067
+ * @param {number} y0
71068
+ * @param {number} z0
71069
+ * @param {number} x1
71070
+ * @param {number} y1
71071
+ * @param {number} z1
71072
+ * @param {number} normalX
71073
+ * @param {number} normalY
71074
+ * @param {number} normalZ
71075
+ * @param {number} dist
71076
+ * @returns {boolean}
71077
+ */
71078
+ function plane3_computeLineSegmentIntersection(
71079
+ result, result_offset,
71080
+ x0, y0, z0,
71081
+ x1, y1, z1,
71082
+ normalX, normalY, normalZ, dist
71083
+ ) {
71084
+
71085
+ const directionX = x1 - x0;
71086
+ const directionY = y1 - y0;
71087
+ const directionZ = z1 - z0;
71088
+
71089
+ const denom = v3_dot(directionX, directionY, directionZ, normalX, normalY, normalZ);
71090
+
71091
+ if (denom === 0) {
71092
+ return false;
71093
+ }
71094
+
71095
+ const p = v3_dot(normalX, normalY, normalZ, x0, y0, z0) + dist;
71096
+
71097
+ const t = -p / denom;
71098
+
71099
+ if (t < 0 || t > 1) {
71100
+ return false;
71101
+ }
71102
+
71103
+ result[result_offset] = directionX * t + x0;
71104
+ result[result_offset + 1] = directionY * t + y0;
71105
+ result[result_offset + 2] = directionZ * t + z0;
71106
+
71107
+ return true;
71108
+
71109
+ }
71110
+
70998
71111
  /**
70999
71112
  * Created by Alex on 31/12/2014.
71000
71113
  */
@@ -71206,6 +71319,42 @@ class Camera {
71206
71319
  return true;
71207
71320
  }
71208
71321
 
71322
+ /**
71323
+ *
71324
+ * @param {Vector3} out
71325
+ * @param {number} origin_x
71326
+ * @param {number} origin_y
71327
+ * @param {number} origin_z
71328
+ * @param {number} direction_x
71329
+ * @param {number} direction_y
71330
+ * @param {number} direction_z
71331
+ * @param {number} plane_index
71332
+ */
71333
+ rayPlaneIntersection(
71334
+ out,
71335
+ origin_x, origin_y, origin_z,
71336
+ direction_x, direction_y, direction_z,
71337
+ plane_index
71338
+ ) {
71339
+
71340
+ assert.isNonNegativeInteger(plane_index, 'plane_index');
71341
+ assert.lessThanOrEqual(plane_index, 5, `plane_index must be <= 5, was ${plane_index}`);
71342
+
71343
+ frustum_from_camera(this.object, scratch_frustum$1);
71344
+
71345
+ const plane = scratch_frustum$1.planes[plane_index];
71346
+
71347
+ assert.defined(plane, 'plane');
71348
+
71349
+ computePlaneRayIntersection(
71350
+ out,
71351
+ origin_x, origin_y, origin_z,
71352
+ direction_x, direction_y, direction_z,
71353
+ plane.normal.x, plane.normal.y, plane.normal.z,
71354
+ plane.constant
71355
+ );
71356
+ }
71357
+
71209
71358
  /**
71210
71359
  *
71211
71360
  * @param {number} x
@@ -73859,26 +74008,25 @@ const EntityManagerState = {
73859
74008
  */
73860
74009
  function EntityManager() {
73861
74010
  /**
73862
- *
73863
- * @type {Array.<System>}
74011
+ * @readonly
74012
+ * @type {System[]}
73864
74013
  */
73865
74014
  this.systems = [];
73866
74015
 
73867
74016
  /**
73868
- *
73869
- * @type {Array<EntityObserver>}
74017
+ * @readonly
74018
+ * @type {EntityObserver[]}
73870
74019
  */
73871
74020
  this.systemObservers = [];
73872
74021
 
74022
+ /**
74023
+ * @readonly
74024
+ */
73873
74025
  this.on = {
73874
74026
  systemStarted: new Signal(),
73875
74027
  systemStopped: new Signal(),
73876
74028
  systemAdded: new Signal(),
73877
74029
  systemRemoved: new Signal(),
73878
- /**
73879
- * @deprecated
73880
- */
73881
- reset: new Signal()
73882
74030
  };
73883
74031
 
73884
74032
  /**
@@ -73887,6 +74035,19 @@ function EntityManager() {
73887
74035
  */
73888
74036
  this.state = EntityManagerState.Initial;
73889
74037
 
74038
+ /**
74039
+ * @private
74040
+ * @readonly
74041
+ * @type {Map<System, number>}
74042
+ */
74043
+ this.systemAccumulatedFixedStepTime = new Map();
74044
+
74045
+ /**
74046
+ * In seconds
74047
+ * @type {number}
74048
+ */
74049
+ this.fixedUpdateStepSize = 0.015;
74050
+
73890
74051
  /**
73891
74052
  *
73892
74053
  * @type {EntityComponentDataset}
@@ -73961,170 +74122,6 @@ EntityManager.prototype.attachDataSet = function (dataset) {
73961
74122
  });
73962
74123
  };
73963
74124
 
73964
- /**
73965
- * @deprecated
73966
- * @returns {number}
73967
- */
73968
- EntityManager.prototype.createEntity = function () {
73969
- console.warn("EntityManager.createEntity is deprecated");
73970
-
73971
- return this.dataset.createEntity();
73972
- };
73973
-
73974
- /**
73975
- * @deprecated
73976
- * @param id
73977
- */
73978
- EntityManager.prototype.createEntitySpecific = function (id) {
73979
- console.warn("EntityManager.createEntitySpecific is deprecated");
73980
- this.dataset.createEntitySpecific(id);
73981
- };
73982
-
73983
-
73984
- /**
73985
- * @deprecated
73986
- * Remove association of specified component type from entity
73987
- * @param {Number} entityId
73988
- * @param {Number} componentType
73989
- */
73990
- EntityManager.prototype.removeComponentFromEntity = function (entityId, componentType) {
73991
- console.warn("EntityManager.removeComponentFromEntity is deprecated");
73992
-
73993
- this.dataset.removeComponentFromEntityByIndex(entityId, componentType);
73994
- };
73995
-
73996
- /**
73997
- * @deprecated use dataset directly
73998
- * Retrieves component instance associated with entity
73999
- * @template T
74000
- * @param {Number} entityId
74001
- * @param {class.<T>} componentClass
74002
- * @returns {T|null}
74003
- * @nosideeffects
74004
- */
74005
- EntityManager.prototype.getComponent = function (entityId, componentClass) {
74006
- return this.dataset.getComponent(entityId, componentClass);
74007
- };
74008
-
74009
- /**
74010
- *
74011
- * @param {number} entityIndex
74012
- * @returns {boolean}
74013
- */
74014
- EntityManager.prototype.entityExists = function (entityIndex) {
74015
- if (this.dataset === null) {
74016
- //no dataset - no entities
74017
- return false;
74018
- }
74019
- return this.dataset.entityExists(entityIndex);
74020
- };
74021
-
74022
- /**
74023
- * same as getComponent when component exists, if component is not associated with the entity, callback will be invoked once when it is added.
74024
- * @param {Number} entityId
74025
- * @param {Class} componentClass
74026
- * @param {function} callback
74027
- * @param {*} [thisArg]
74028
- */
74029
- EntityManager.prototype.getComponentAsync = function (entityId, componentClass, callback, thisArg) {
74030
- const self = this;
74031
- const component = this.getComponent(entityId, componentClass);
74032
-
74033
- function handler(options) {
74034
- if (options.klass === componentClass) {
74035
- self.removeEntityEventListener(entityId, EventType.ComponentAdded, handler);
74036
- callback.call(thisArg, options.instance);
74037
- }
74038
- }
74039
-
74040
- if (component === void 0 || component === null) {
74041
- this.addEntityEventListener(entityId, EventType.ComponentAdded, handler);
74042
- } else {
74043
- callback.call(thisArg, component);
74044
- }
74045
- };
74046
-
74047
- /**
74048
- * @deprecated Use {@link EntityManager#dataset} direction
74049
- * @param entity
74050
- * @returns {Array}
74051
- */
74052
- EntityManager.prototype.getComponents = function (entity) {
74053
- console.warn("EntityManager.getComponents is deprecated");
74054
-
74055
- return this.dataset.getAllComponents(entity);
74056
- };
74057
-
74058
- /**
74059
- * @deprecated
74060
- * Retrieves component instance associated with entity
74061
- * @param {Number} entityId
74062
- * @param {Number} componentType
74063
- * @returns {*|undefined} component of specified type or undefined if it was not found
74064
- */
74065
- EntityManager.prototype.getComponentByType = function (entityId, componentType) {
74066
- console.warn("EntityManager.getComponentByType is deprecated");
74067
- return this.dataset.getComponentByIndex(entityId, componentType);
74068
- };
74069
-
74070
- /**
74071
- * @deprecated
74072
- * does traversal on a subset of entities which have specified components.
74073
- * @example traverseEntities([Transform,Renderable,Tag],function(transform, renderable, tag, entity){ ... }, this);
74074
- * @param {Array.<class>} classes
74075
- * @param {Function} callback
74076
- * @param {Object} [thisArg] specifies context object on which callbacks are to be called, optional
74077
- */
74078
- EntityManager.prototype.traverseEntities = function (classes, callback, thisArg) {
74079
- if (this.dataset === null) {
74080
- //no data to traverse
74081
- return;
74082
- }
74083
- this.dataset.traverseEntities(classes, callback, thisArg);
74084
- };
74085
-
74086
- /**
74087
- * @deprecated
74088
- * @param entity
74089
- * @param eventName
74090
- * @param listener
74091
- */
74092
- EntityManager.prototype.addEntityEventListener = function (entity, eventName, listener) {
74093
- this.dataset.addEntityEventListener(entity, eventName, listener);
74094
- };
74095
-
74096
- /**
74097
- * @deprecated
74098
- * @param {number} entity
74099
- * @param {string} eventName
74100
- * @param {function} listener
74101
- */
74102
- EntityManager.prototype.removeEntityEventListener = function (entity, eventName, listener) {
74103
- this.dataset.removeEntityEventListener(entity, eventName, listener);
74104
- };
74105
-
74106
- /**
74107
- * @deprecated use dataset directly instead
74108
- * @param entity
74109
- * @param eventName
74110
- * @param event
74111
- */
74112
- EntityManager.prototype.sendEvent = function (entity, eventName, event) {
74113
- this.dataset.sendEvent(entity, eventName, event);
74114
- };
74115
-
74116
- /**
74117
- * @deprecated
74118
- * @param {function} klazz
74119
- * @param {function(component: *, entity: number):boolean} callback
74120
- * @param {*} [thisArg]
74121
- * @deprecated
74122
- */
74123
- EntityManager.prototype.traverseComponents = function (klazz, callback, thisArg) {
74124
- if (this.dataset !== null) {
74125
- this.dataset.traverseComponents(klazz, callback, thisArg);
74126
- }
74127
- };
74128
74125
 
74129
74126
  /**
74130
74127
  * @template T
@@ -74156,33 +74153,6 @@ EntityManager.prototype.getSystem = function (systemClass) {
74156
74153
  return null;
74157
74154
  };
74158
74155
 
74159
- /**
74160
- * @deprecated Use {@link #getSystem} instead
74161
- * @template T,C
74162
- * @param {C} klazz
74163
- * @returns {System|T}
74164
- */
74165
- EntityManager.prototype.getOwnerSystemByComponentClass = function (klazz) {
74166
- const index = this.getOwnerSystemIdByComponentClass(klazz);
74167
- return this.systems[index];
74168
- };
74169
-
74170
- /**
74171
- * @deprecated
74172
- * @param {function} clazz
74173
- * @returns {number} value >= 0, representing system Id, or -1 if system was not found
74174
- */
74175
- EntityManager.prototype.getOwnerSystemIdByComponentClass = function (clazz) {
74176
- const systems = this.systems;
74177
- let i = 0;
74178
- const l = systems.length;
74179
- for (; i < l; i++) {
74180
- if (systems[i].componentClass === clazz) {
74181
- return i;
74182
- }
74183
- }
74184
- return -1;
74185
- };
74186
74156
 
74187
74157
  /**
74188
74158
  * @template T
@@ -74204,19 +74174,6 @@ EntityManager.prototype.getComponentClassByName = function (className) {
74204
74174
  return null;
74205
74175
  };
74206
74176
 
74207
- /**
74208
- *
74209
- * @param {System} system
74210
- * @param {number} timeDelta
74211
- */
74212
- function tryUpdateSystem(system, timeDelta) {
74213
- try {
74214
- system.update(timeDelta);
74215
- } catch (e) {
74216
- console.error(`Failed to update system '${computeSystemName(system)}': `, e);
74217
- }
74218
- }
74219
-
74220
74177
  /**
74221
74178
  * Advance simulation forward by a specified amount of time
74222
74179
  * @param {number} timeDelta in seconds, real number
@@ -74226,12 +74183,51 @@ EntityManager.prototype.simulate = function (timeDelta) {
74226
74183
  assert.notNaN(timeDelta, 'timeDelta');
74227
74184
  assert.greaterThanOrEqual(timeDelta, 0, 'timeDelta must be >= 0');
74228
74185
 
74186
+ /**
74187
+ *
74188
+ * @type {System[]}
74189
+ */
74229
74190
  const systems = this.systems;
74230
- let i = 0;
74231
- const l = systems.length;
74232
- for (; i < l; i++) {
74191
+
74192
+ const system_count = systems.length;
74193
+
74194
+ const fixed_step = this.fixedUpdateStepSize;
74195
+ const accumulatedTime = this.systemAccumulatedFixedStepTime;
74196
+
74197
+ for (let i = 0; i < system_count; i++) {
74198
+
74233
74199
  const system = systems[i];
74234
- tryUpdateSystem(system, timeDelta);
74200
+
74201
+ if (system.fixedUpdate !== noop) {
74202
+ let accumulated_time = accumulatedTime.get(system) + timeDelta;
74203
+
74204
+
74205
+ while (accumulated_time > fixed_step) {
74206
+
74207
+ try {
74208
+ system.fixedUpdate(fixed_step);
74209
+ } catch (e) {
74210
+ console.error(`Failed during fixedUpdate of system '${computeSystemName(system)}': `, e);
74211
+ }
74212
+
74213
+ accumulated_time -= fixed_step;
74214
+ }
74215
+
74216
+ // record whatever remains
74217
+ accumulatedTime.set(system, accumulated_time);
74218
+
74219
+ }
74220
+
74221
+ if (system.update !== noop) {
74222
+
74223
+ try {
74224
+ system.update(timeDelta);
74225
+ } catch (e) {
74226
+ console.error(`Failed during update of system '${computeSystemName(system)}': `, e);
74227
+ }
74228
+
74229
+ }
74230
+
74235
74231
  }
74236
74232
  };
74237
74233
 
@@ -74354,6 +74350,8 @@ EntityManager.prototype.addSystem = async function (system) {
74354
74350
  this.dataset.addObserver(linkObserver);
74355
74351
  }
74356
74352
 
74353
+ this.systemAccumulatedFixedStepTime.set(system, 0);
74354
+
74357
74355
  this.on.systemAdded.send1(system);
74358
74356
 
74359
74357
  await startup_promise;
@@ -74397,6 +74395,8 @@ EntityManager.prototype.removeSystem = async function (system) {
74397
74395
  });
74398
74396
  });
74399
74397
 
74398
+ this.systemAccumulatedFixedStepTime.delete(system);
74399
+
74400
74400
  this.on.systemRemoved.send1(system);
74401
74401
  };
74402
74402
 
@@ -74695,17 +74695,208 @@ EntityManager.prototype.shutdown = function (readyCallback, errorCallback) {
74695
74695
  });
74696
74696
  };
74697
74697
 
74698
+
74699
+ /**
74700
+ * @deprecated
74701
+ * @returns {number}
74702
+ */
74703
+ EntityManager.prototype.createEntity = function () {
74704
+ console.warn("EntityManager.createEntity is deprecated");
74705
+
74706
+ return this.dataset.createEntity();
74707
+ };
74708
+
74709
+ /**
74710
+ * @deprecated
74711
+ * @param id
74712
+ */
74713
+ EntityManager.prototype.createEntitySpecific = function (id) {
74714
+ console.warn("EntityManager.createEntitySpecific is deprecated");
74715
+ this.dataset.createEntitySpecific(id);
74716
+ };
74717
+
74718
+
74719
+ /**
74720
+ * @deprecated
74721
+ * Remove association of specified component type from entity
74722
+ * @param {Number} entityId
74723
+ * @param {Number} componentType
74724
+ */
74725
+ EntityManager.prototype.removeComponentFromEntity = function (entityId, componentType) {
74726
+ console.warn("EntityManager.removeComponentFromEntity is deprecated");
74727
+
74728
+ this.dataset.removeComponentFromEntityByIndex(entityId, componentType);
74729
+ };
74730
+
74731
+ /**
74732
+ * @deprecated use dataset directly
74733
+ * Retrieves component instance associated with entity
74734
+ * @template T
74735
+ * @param {Number} entityId
74736
+ * @param {class.<T>} componentClass
74737
+ * @returns {T|null}
74738
+ * @nosideeffects
74739
+ */
74740
+ EntityManager.prototype.getComponent = function (entityId, componentClass) {
74741
+ console.warn("EntityManager.getComponent is deprecated");
74742
+
74743
+ return this.dataset.getComponent(entityId, componentClass);
74744
+ };
74745
+
74746
+ /**
74747
+ * @deprecated use {@link EntityComponentDataset.entityExists} instead
74748
+ * @param {number} entityIndex
74749
+ * @returns {boolean}
74750
+ */
74751
+ EntityManager.prototype.entityExists = function (entityIndex) {
74752
+ console.warn("EntityManager.entityExists is deprecated");
74753
+ if (this.dataset === null) {
74754
+ //no dataset - no entities
74755
+ return false;
74756
+ }
74757
+ return this.dataset.entityExists(entityIndex);
74758
+ };
74759
+
74760
+
74761
+ /**
74762
+ * @deprecated Use {@link EntityManager#dataset} direction
74763
+ * @param entity
74764
+ * @returns {Array}
74765
+ */
74766
+ EntityManager.prototype.getComponents = function (entity) {
74767
+ console.warn("EntityManager.getComponents is deprecated");
74768
+
74769
+ return this.dataset.getAllComponents(entity);
74770
+ };
74771
+
74772
+ /**
74773
+ * @deprecated
74774
+ * Retrieves component instance associated with entity
74775
+ * @param {Number} entityId
74776
+ * @param {Number} componentType
74777
+ * @returns {*|undefined} component of specified type or undefined if it was not found
74778
+ */
74779
+ EntityManager.prototype.getComponentByType = function (entityId, componentType) {
74780
+ console.warn("EntityManager.getComponentByType is deprecated");
74781
+ return this.dataset.getComponentByIndex(entityId, componentType);
74782
+ };
74783
+
74784
+ /**
74785
+ * @deprecated
74786
+ * does traversal on a subset of entities which have specified components.
74787
+ * @example traverseEntities([Transform,Renderable,Tag],function(transform, renderable, tag, entity){ ... }, this);
74788
+ * @param {Array.<class>} classes
74789
+ * @param {Function} callback
74790
+ * @param {Object} [thisArg] specifies context object on which callbacks are to be called, optional
74791
+ */
74792
+ EntityManager.prototype.traverseEntities = function (classes, callback, thisArg) {
74793
+ console.warn("EntityManager.traverseEntities is deprecated");
74794
+
74795
+ if (this.dataset === null) {
74796
+ //no data to traverse
74797
+ return;
74798
+ }
74799
+ this.dataset.traverseEntities(classes, callback, thisArg);
74800
+ };
74801
+
74802
+ /**
74803
+ * @deprecated
74804
+ * @param entity
74805
+ * @param eventName
74806
+ * @param listener
74807
+ */
74808
+ EntityManager.prototype.addEntityEventListener = function (entity, eventName, listener) {
74809
+ console.warn("EntityManager.addEntityEventListener is deprecated");
74810
+ this.dataset.addEntityEventListener(entity, eventName, listener);
74811
+ };
74812
+
74698
74813
  /**
74699
74814
  * @deprecated
74815
+ * @param {number} entity
74816
+ * @param {string} eventName
74817
+ * @param {function} listener
74818
+ */
74819
+ EntityManager.prototype.removeEntityEventListener = function (entity, eventName, listener) {
74820
+ console.warn("EntityManager.removeEntityEventListener is deprecated");
74821
+ this.dataset.removeEntityEventListener(entity, eventName, listener);
74822
+ };
74823
+
74824
+ /**
74825
+ * @deprecated use dataset directly instead
74826
+ * @param entity
74827
+ * @param eventName
74828
+ * @param event
74829
+ */
74830
+ EntityManager.prototype.sendEvent = function (entity, eventName, event) {
74831
+ console.warn("EntityManager.sendEvent is deprecated");
74832
+ this.dataset.sendEvent(entity, eventName, event);
74833
+ };
74834
+
74835
+ /**
74836
+ * @deprecated
74837
+ * @param {function} klazz
74838
+ * @param {function(component: *, entity: number):boolean} callback
74839
+ * @param {*} [thisArg]
74840
+ * @deprecated
74841
+ */
74842
+ EntityManager.prototype.traverseComponents = function (klazz, callback, thisArg) {
74843
+ console.warn("EntityManager.traverseComponents is deprecated");
74844
+ if (this.dataset !== null) {
74845
+ this.dataset.traverseComponents(klazz, callback, thisArg);
74846
+ }
74847
+ };
74848
+
74849
+ /**
74850
+ * @deprecated Use {@link #getSystem} instead
74851
+ * @template T,C
74852
+ * @param {C} klazz
74853
+ * @returns {System|T}
74854
+ */
74855
+ EntityManager.prototype.getOwnerSystemByComponentClass = function (klazz) {
74856
+
74857
+ console.warn("EntityManager.getOwnerSystemByComponentClass is deprecated, use .getSystem instead");
74858
+ const index = this.getOwnerSystemIdByComponentClass(klazz);
74859
+ return this.systems[index];
74860
+ };
74861
+
74862
+ /**
74863
+ * @deprecated
74864
+ * @param {function} clazz
74865
+ * @returns {number} value >= 0, representing system Id, or -1 if system was not found
74866
+ */
74867
+ EntityManager.prototype.getOwnerSystemIdByComponentClass = function (clazz) {
74868
+ console.warn("EntityManager.getOwnerSystemIdByComponentClass is deprecated, use .getSystem instead");
74869
+
74870
+ const systems = this.systems;
74871
+ let i = 0;
74872
+ const l = systems.length;
74873
+ for (; i < l; i++) {
74874
+ if (systems[i].componentClass === clazz) {
74875
+ return i;
74876
+ }
74877
+ }
74878
+ return -1;
74879
+ };
74880
+
74881
+
74882
+ /**
74883
+ * same as getComponent when component exists, if component is not associated with the entity, callback will be invoked once when it is added.
74884
+ * @param {Number} entityId
74885
+ * @param {Class} componentClass
74886
+ * @param {function} callback
74887
+ * @param {*} [thisArg]
74700
74888
  */
74701
- EntityManager.prototype.reset = function () {
74702
- console.warn("EntityManager.reset is deprecated and should no longer be used, reset dataset instead");
74889
+ EntityManager.prototype.getComponentAsync = function (entityId, componentClass, callback, thisArg) {
74890
+ console.warn("EntityManager.getComponentAsync is deprecated");
74703
74891
 
74704
- this.dataset.clear();
74892
+ const dataset = this.dataset;
74705
74893
 
74706
- this.on.reset.send0();
74894
+ if (dataset === undefined) {
74895
+ throw new Error('No dataset attached');
74896
+ }
74897
+
74898
+ dataset.getComponentAsync(entityId, componentClass, callback, thisArg);
74707
74899
 
74708
- console.log("Entity Manager completed reset");
74709
74900
  };
74710
74901
 
74711
74902
  /**
@@ -86587,59 +86778,6 @@ function aabb_build_frustum(result, x0, y0, z0, x1, y1, z1) {
86587
86778
  result[23] = z1;
86588
86779
  }
86589
86780
 
86590
- /**
86591
- * Created by Alex on 20/02/2017.
86592
- */
86593
-
86594
- /**
86595
- *
86596
- * @param {Float32Array|number[]|vec3} result
86597
- * @param {number} result_offset
86598
- * @param {number} x0
86599
- * @param {number} y0
86600
- * @param {number} z0
86601
- * @param {number} x1
86602
- * @param {number} y1
86603
- * @param {number} z1
86604
- * @param {number} normalX
86605
- * @param {number} normalY
86606
- * @param {number} normalZ
86607
- * @param {number} dist
86608
- * @returns {boolean}
86609
- */
86610
- function plane3_computeLineSegmentIntersection(
86611
- result, result_offset,
86612
- x0, y0, z0,
86613
- x1, y1, z1,
86614
- normalX, normalY, normalZ, dist
86615
- ) {
86616
-
86617
- const directionX = x1 - x0;
86618
- const directionY = y1 - y0;
86619
- const directionZ = z1 - z0;
86620
-
86621
- const denom = v3_dot(directionX, directionY, directionZ, normalX, normalY, normalZ);
86622
-
86623
- if (denom === 0) {
86624
- return false;
86625
- }
86626
-
86627
- const p = v3_dot(normalX, normalY, normalZ, x0, y0, z0) + dist;
86628
-
86629
- const t = -p / denom;
86630
-
86631
- if (t < 0 || t > 1) {
86632
- return false;
86633
- }
86634
-
86635
- result[result_offset] = directionX * t + x0;
86636
- result[result_offset + 1] = directionY * t + y0;
86637
- result[result_offset + 2] = directionZ * t + z0;
86638
-
86639
- return true;
86640
-
86641
- }
86642
-
86643
86781
  /**
86644
86782
  * Bitfields, mapping a corner index to bitfield with attached edges
86645
86783
  * @type {number[]}
@@ -95869,7 +96007,7 @@ GraphicsEngine.prototype.start = function () {
95869
96007
  /**
95870
96008
  * @see https://registry.khronos.org/webgl/specs/latest/1.0/#5.2
95871
96009
  */
95872
- powerPreference:"high-performance"
96010
+ powerPreference: "high-performance"
95873
96011
  };
95874
96012
 
95875
96013
  const webGLRenderer = this.renderer = new WebGLRenderer(rendererParameters);
@@ -96000,8 +96138,9 @@ GraphicsEngine.prototype.normalizeViewportPoint = function (input, result) {
96000
96138
 
96001
96139
  const viewportSize = this.viewport.size;
96002
96140
 
96003
- const _x = input.x;
96004
- const _y = input.y;
96141
+ // shift by pixel center
96142
+ const _x = input.x + 0.5;
96143
+ const _y = input.y + 0.5;
96005
96144
 
96006
96145
  result.x = (_x / viewportSize.x) * 2 - 1;
96007
96146
  result.y = -(_y / viewportSize.y) * 2 + 1;
@@ -96323,6 +96462,27 @@ const TouchEvents = {
96323
96462
  Cancel: "touchcancel",
96324
96463
  };
96325
96464
 
96465
+ /**
96466
+ * Representation of an input device key
96467
+ */
96468
+ class InputDeviceSwitch {
96469
+ /**
96470
+ * Button press
96471
+ * @type {Signal}
96472
+ */
96473
+ down = new Signal()
96474
+ /**
96475
+ * Button release
96476
+ * @type {Signal}
96477
+ */
96478
+ up = new Signal()
96479
+ /**
96480
+ * is button currently being pressed?
96481
+ * @type {boolean}
96482
+ */
96483
+ is_down = false
96484
+ }
96485
+
96326
96486
  /**
96327
96487
  * Created by Alex on 29/01/2015.
96328
96488
  */
@@ -96689,6 +96849,13 @@ class PointerDevice {
96689
96849
  */
96690
96850
  isRunning = false;
96691
96851
 
96852
+ /**
96853
+ * The MouseEvent.buttons is a 32bit field, which means we can encode up to 32 buttons
96854
+ * @readonly
96855
+ * @type {InputDeviceSwitch[]}
96856
+ */
96857
+ buttons = new Array(32);
96858
+
96692
96859
  /**
96693
96860
  *
96694
96861
  * @param {EventTarget} domElement html element
@@ -96697,6 +96864,10 @@ class PointerDevice {
96697
96864
  constructor(domElement) {
96698
96865
  assert.defined(domElement, "domElement");
96699
96866
 
96867
+ // initialize buttons
96868
+ for (let i = 0; i < this.buttons.length; i++) {
96869
+ this.buttons[i] = new InputDeviceSwitch();
96870
+ }
96700
96871
 
96701
96872
  /**
96702
96873
  *
@@ -96738,6 +96909,16 @@ class PointerDevice {
96738
96909
  #eventHandlerMouseDown = (event) => {
96739
96910
  this.readPointerPositionFromEvent(this.position, event);
96740
96911
  this.on.down.send2(this.position, event);
96912
+
96913
+ // update button state and dispatch specific signal
96914
+ const button_index = event.button;
96915
+
96916
+ const button = this.buttons[button_index];
96917
+
96918
+ if (button !== undefined) {
96919
+ button.is_down = true;
96920
+ button.down.send0();
96921
+ }
96741
96922
  }
96742
96923
 
96743
96924
  /**
@@ -96765,6 +96946,16 @@ class PointerDevice {
96765
96946
  #eventHandlerGlobalMouseUp = (event) => {
96766
96947
  this.readPointerPositionFromEvent(this.position, event);
96767
96948
  this.#globalUp.send2(this.position, event);
96949
+
96950
+ // update button state and dispatch specific signal
96951
+ const button_index = event.button;
96952
+
96953
+ const button = this.buttons[button_index];
96954
+
96955
+ if (button !== undefined) {
96956
+ button.is_down = false;
96957
+ button.up.send0();
96958
+ }
96768
96959
  }
96769
96960
 
96770
96961
  /**
@@ -96955,27 +97146,6 @@ const KeyboardEvents = {
96955
97146
  KeyDown: 'keydown'
96956
97147
  };
96957
97148
 
96958
- /**
96959
- * Representation of an input device key
96960
- */
96961
- class InputDeviceSwitch {
96962
- /**
96963
- * Button press
96964
- * @type {Signal}
96965
- */
96966
- down = new Signal()
96967
- /**
96968
- * Button release
96969
- * @type {Signal}
96970
- */
96971
- up = new Signal()
96972
- /**
96973
- * is button currently being pressed?
96974
- * @type {boolean}
96975
- */
96976
- is_down = false
96977
- }
96978
-
96979
97149
  /**
96980
97150
  * Created by Alex on 06/03/2017.
96981
97151
  */
@@ -98373,10 +98543,35 @@ class EntityComponentDataset {
98373
98543
  }
98374
98544
 
98375
98545
  /**
98376
- *
98546
+ * same as getComponent when component exists, if component is not associated with the entity, callback will be invoked once when it is added.
98547
+ * @param {Number} entityId
98548
+ * @param {Class} componentClass
98549
+ * @param {function} callback
98550
+ * @param {*} [thisArg]
98551
+ */
98552
+ getComponentAsync (entityId, componentClass, callback, thisArg) {
98553
+ const component = this.getComponent(entityId, componentClass);
98554
+
98555
+ const handler = (options) => {
98556
+ if (options.klass === componentClass) {
98557
+ this.removeEntityEventListener(entityId, EventType.ComponentAdded, handler);
98558
+ callback.call(thisArg, options.instance);
98559
+ }
98560
+ };
98561
+
98562
+ if (component === undefined) {
98563
+ this.addEntityEventListener(entityId, EventType.ComponentAdded, handler);
98564
+ } else {
98565
+ callback.call(thisArg, component);
98566
+ }
98567
+ };
98568
+
98569
+ /**
98570
+ * Performs traversal on a subset of entities which have specified components.
98571
+ * @example traverseEntities([Transform,Renderable,Tag],function(transform, renderable, tag, entity){ ... }, this);
98377
98572
  * @param {Array} classes
98378
98573
  * @param {function:boolean?} visitor Visitor can return optional "false" to terminate traversal earlier
98379
- * @param {object} [thisArg]
98574
+ * @param {object} [thisArg] specifies context object on which callbacks are to be called, optional
98380
98575
  */
98381
98576
  traverseEntities(classes, visitor, thisArg) {
98382
98577
 
@@ -98452,7 +98647,7 @@ class EntityComponentDataset {
98452
98647
  }
98453
98648
 
98454
98649
  /**
98455
- * does traversal on a subset of entities which have only the specified components and no others
98650
+ * Performs traversal on a subset of entities which have only the specified components and no others
98456
98651
  * @example traverseEntitiesExact([Transform,Renderable,Tag],function(transform, renderable, tag, entity){ ... }, this);
98457
98652
  * @param {Array.<class>} classes
98458
98653
  * @param {Function} visitor
@@ -99858,7 +100053,7 @@ class RepeatBehavior extends AbstractDecoratorBehavior {
99858
100053
  * @type {number}
99859
100054
  * @private
99860
100055
  */
99861
- this.__limit = count;
100056
+ this.limit = count;
99862
100057
 
99863
100058
  /**
99864
100059
  *
@@ -99871,19 +100066,19 @@ class RepeatBehavior extends AbstractDecoratorBehavior {
99871
100066
  }
99872
100067
 
99873
100068
  /**
99874
- *
100069
+ * @deprecated use .limit directly instead
99875
100070
  * @param {number} v
99876
100071
  */
99877
100072
  setCount(v) {
99878
- this.__limit = v;
100073
+ this.limit = v;
99879
100074
  }
99880
100075
 
99881
100076
  /**
99882
- *
100077
+ * @deprecated use .limit directly instead
99883
100078
  * @return {number}
99884
100079
  */
99885
100080
  getCount() {
99886
- return this.__limit;
100081
+ return this.limit;
99887
100082
  }
99888
100083
 
99889
100084
  /**
@@ -99896,8 +100091,17 @@ class RepeatBehavior extends AbstractDecoratorBehavior {
99896
100091
  return new RepeatBehavior(source, count);
99897
100092
  }
99898
100093
 
100094
+ initialize(context) {
100095
+ super.initialize(context);
100096
+
100097
+ // reset iterator
100098
+ this.__iterator = 0;
100099
+ }
100100
+
99899
100101
  tick(timeDelta) {
99900
- const s = this.__source.tick(timeDelta);
100102
+ const source = this.__source;
100103
+
100104
+ const s = source.tick(timeDelta);
99901
100105
 
99902
100106
  assert.enum(s, BehaviorStatus, 'status');
99903
100107
 
@@ -99908,12 +100112,12 @@ class RepeatBehavior extends AbstractDecoratorBehavior {
99908
100112
 
99909
100113
  this.__iterator++;
99910
100114
 
99911
- if (this.__iterator >= this.__limit) {
100115
+ if (this.__iterator >= this.limit) {
99912
100116
 
99913
100117
  return BehaviorStatus.Succeeded;
99914
100118
  } else {
99915
100119
  //re-initialize the source behavior
99916
- this.__source.initialize(this.context);
100120
+ source.initialize(this.context);
99917
100121
 
99918
100122
  return BehaviorStatus.Running;
99919
100123
  }
@@ -123976,7 +124180,7 @@ function makeAlexWaterMaterial() {
123976
124180
  * @param {function(terrain:Terrain,entity:number)} [callback]
123977
124181
  * @returns {Terrain|null}
123978
124182
  */
123979
- function obtainTerrain(ecd, callback) {
124183
+ function obtainTerrain(ecd, callback=noop) {
123980
124184
  assert.notEqual(ecd, null, 'ecd is null');
123981
124185
  assert.notEqual(ecd, undefined, 'ecd is undefined');
123982
124186
 
@@ -123984,9 +124188,7 @@ function obtainTerrain(ecd, callback) {
123984
124188
 
123985
124189
  const terrain = object.component;
123986
124190
 
123987
- if (terrain !== null && typeof callback === "function") {
123988
124191
  callback(terrain, object.entity);
123989
- }
123990
124192
 
123991
124193
  return terrain;
123992
124194
  }