@woosh/meep-engine 2.47.23 → 2.47.27

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 (32) 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/decal/v2/FPDecalSystem.js +3 -0
  27. package/src/engine/graphics/ecs/mesh/MeshSystem.js +1 -1
  28. package/src/engine/graphics/make_ray_from_viewport_position.js +28 -0
  29. package/src/engine/input/devices/PointerDevice.js +32 -0
  30. package/src/engine/intelligence/behavior/decorator/RepeatBehavior.js +17 -8
  31. package/src/engine/intelligence/behavior/decorator/RepeatBehaviorSerializationAdapter.js +2 -2
  32. package/src/engine/intelligence/behavior/primitive/SucceedingBehavior.js +9 -5
@@ -19,6 +19,7 @@ import Terrain from "../../src/engine/ecs/terrain/ecs/Terrain.js";
19
19
  import { SurfacePoint3 } from "../../src/core/geom/3d/SurfacePoint3.js";
20
20
  import { makeScreenScissorFrustum } from "../../src/engine/graphics/camera/makeScreenScissorFrustum.js";
21
21
  import { ShadedGeometrySystem } from "../../src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
22
+ import { make_ray_from_viewport_position } from "../../src/engine/graphics/make_ray_from_viewport_position.js";
22
23
 
23
24
  class SelectionView extends View {
24
25
  constructor() {
@@ -224,20 +225,19 @@ export function pickingEntitySelection(point, engine, camera) {
224
225
  const em = engine.entityManager;
225
226
  const dataset = em.dataset;
226
227
 
227
- const graphicsEngine = engine.graphics;
228
-
229
- const source = new Vector3(0, 0, 0);
230
- const rayDirection = new Vector3(0, 0, 0);
231
-
232
- const normalizedPoint = new Vector2(0, 0);
233
-
234
- graphicsEngine.normalizeViewportPoint(point, normalizedPoint);
228
+ // push source by a small amount along the way to prevent selection of elements directly on the NEAR plane
229
+ const ray_offset = 0.0001;
235
230
 
236
- graphicsEngine.viewportProjectionRay(normalizedPoint.x, normalizedPoint.y, source, rayDirection);
231
+ const ray = make_ray_from_viewport_position(engine,point);
237
232
 
238
- // push source by a small amount along the way to prevent selection of elements directly on the NEAR plane
239
- source.add(rayDirection.clone().multiplyScalar(0.0001));
233
+ const ray_origin = ray.origin;
234
+ const ray_direction = ray.direction;
240
235
 
236
+ ray_origin._add(
237
+ ray_direction.x * ray_offset,
238
+ ray_direction.y * ray_offset,
239
+ ray_direction.z * ray_offset,
240
+ )
241
241
 
242
242
  let bestCandidate = null;
243
243
  let bestDistance = Infinity;
@@ -249,7 +249,7 @@ export function pickingEntitySelection(point, engine, camera) {
249
249
  * @param {Vector3} contact
250
250
  */
251
251
  function tryAddEntity(entity, contact) {
252
- const distance = source.distanceSqrTo(contact);
252
+ const distance = ray.origin.distanceSqrTo(contact);
253
253
 
254
254
  if (distance < bestDistance) {
255
255
  bestDistance = distance;
@@ -272,8 +272,8 @@ export function pickingEntitySelection(point, engine, camera) {
272
272
 
273
273
  if (sgm !== undefined && sgm !== null) {
274
274
  const hits = sgm.raycast(
275
- source.x, source.y, source.y,
276
- rayDirection.x, rayDirection.y, rayDirection.z
275
+ ray_origin.x, ray_origin.y, ray_origin.y,
276
+ ray_direction.x, ray_direction.y, ray_direction.z
277
277
  );
278
278
 
279
279
  for (let i = 0; i < hits.length; i++) {
@@ -291,7 +291,7 @@ export function pickingEntitySelection(point, engine, camera) {
291
291
  */
292
292
  const bvh = layer.bvh;
293
293
 
294
- bvh.traverseRayLeafIntersections(source.x, source.y, source.z, rayDirection.x, rayDirection.y, rayDirection.z, function (leaf) {
294
+ bvh.traverseRayLeafIntersections(ray_origin.x, ray_origin.y, ray_origin.z, ray_direction.x, ray_direction.y, ray_direction.z, function (leaf) {
295
295
  const entity = findEntityOfNode(leaf);
296
296
 
297
297
  if (typeof entity !== "number") {
@@ -308,7 +308,7 @@ export function pickingEntitySelection(point, engine, camera) {
308
308
  && typeof object.raycast === "function"
309
309
  ) {
310
310
  //found a "raycast" function on the value object held by the leaf, assuming this is THREE.js raycast function
311
- const raycaster = new Raycaster(source, rayDirection, 0, Infinity);
311
+ const raycaster = new Raycaster(ray_origin, ray_direction, 0, Infinity);
312
312
 
313
313
  // WORKAROUND FOR https://github.com/mrdoob/three.js/issues/17078
314
314
  raycaster.camera = camera;
@@ -333,7 +333,7 @@ export function pickingEntitySelection(point, engine, camera) {
333
333
  if (terrain !== undefined) {
334
334
  const sp = new SurfacePoint3();
335
335
 
336
- terrain.raycastFirstSync(sp, source.x, source.y, source.z, rayDirection.x, rayDirection.y, rayDirection.z);
336
+ terrain.raycastFirstSync(sp, ray_origin.x, ray_origin.y, ray_origin.z, ray_direction.x, ray_direction.y, ray_direction.z);
337
337
 
338
338
  tryAddEntity(entity, sp.position);
339
339
  return;
@@ -33,6 +33,7 @@ import { ProcessState } from "../../src/core/process/ProcessState.js";
33
33
  import { MeshEvents } from "../../src/engine/graphics/ecs/mesh/MeshEvents.js";
34
34
  import { obtainTerrain } from "../../src/engine/ecs/terrain/util/obtainTerrain.js";
35
35
  import { SurfacePoint3 } from "../../src/core/geom/3d/SurfacePoint3.js";
36
+ import { make_ray_from_viewport_position } from "../../src/engine/graphics/make_ray_from_viewport_position.js";
36
37
 
37
38
  class ViewManager extends View {
38
39
  constructor() {
@@ -178,13 +179,11 @@ function prepareMeshLibrary(editor) {
178
179
  const normalizedPosition = new Vector2();
179
180
 
180
181
  //compute world position for drop
182
+ const ray = make_ray_from_viewport_position(engine, position);
181
183
 
182
- graphics.normalizeViewportPoint(position, normalizedPosition);
184
+ const source = ray.origin;
185
+ const direction = ray.direction;
183
186
 
184
- const source = new Vector3();
185
- const direction = new Vector3();
186
-
187
- graphics.viewportProjectionRay(normalizedPosition.x, normalizedPosition.y, source, direction);
188
187
 
189
188
  const entityManager = engine.entityManager;
190
189
  const ecd = entityManager.dataset;
@@ -233,7 +233,6 @@ class EntityListView extends View {
233
233
 
234
234
  dataset.onEntityCreated.add(handlers.addOne);
235
235
  dataset.onEntityRemoved.add(handlers.removeOne);
236
- entityManager.on.reset.add(handlers.reset);
237
236
 
238
237
  }
239
238
 
@@ -250,7 +249,6 @@ class EntityListView extends View {
250
249
 
251
250
  dataset.onEntityCreated.remove(handlers.addOne);
252
251
  dataset.onEntityRemoved.remove(handlers.removeOne);
253
- entityManager.on.reset.remove(handlers.reset);
254
252
  }
255
253
  }
256
254
 
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.23",
8
+ "version": "2.47.27",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -3,7 +3,6 @@ import { MeshBasicMaterial, MeshStandardMaterial, OctahedronBufferGeometry } fro
3
3
  import EntityBuilder from "../../../../../engine/ecs/EntityBuilder.js";
4
4
  import { ShadedGeometry } from "../../../../../engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
5
5
  import { Transform } from "../../../../../engine/ecs/transform/Transform.js";
6
- import Vector3 from "../../../Vector3.js";
7
6
  import { ShadedGeometrySystem } from "../../../../../engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
8
7
  import { SurfacePoint3 } from "../../SurfacePoint3.js";
9
8
  import { topo_mesh_to_three_buffer_geometry } from "../topo_mesh_to_three_buffer_geometry.js";
@@ -27,6 +26,7 @@ import { expandConnectivityByLocality } from "../expandConnectivityByLocality.js
27
26
  import { buildCubeURLs } from "../../../../../engine/graphics/texture/cubemap/buildCubeURLs.js";
28
27
  import { EntityNode } from "../../../../../engine/ecs/parent/EntityNode.js";
29
28
  import { TransformAttachmentSystem } from "../../../../../engine/ecs/transform-attachment/TransformAttachmentSystem.js";
29
+ import { make_ray_from_viewport_position } from "../../../../../engine/graphics/make_ray_from_viewport_position.js";
30
30
 
31
31
  const harness = new EngineHarness();
32
32
 
@@ -71,7 +71,7 @@ function set_highlight({
71
71
 
72
72
  entity.addChild(EntityNode.fromComponents(
73
73
  new Transform(),
74
- ShadedGeometry.from(selected_geo,new MeshBasicMaterial({
74
+ ShadedGeometry.from(selected_geo, new MeshBasicMaterial({
75
75
  wireframe: true,
76
76
  transparent: true,
77
77
  opacity: 0.7,
@@ -129,12 +129,12 @@ async function main(engine) {
129
129
 
130
130
  n.entity.removeComponent(ShadedGeometry);
131
131
 
132
- let hue =0;
132
+ let hue = 0;
133
133
 
134
134
  do {
135
135
  hue = random();
136
136
 
137
- }while(Math.abs(hue - 0.53855555555) < 0.11); // shift away from hue of selection mask
137
+ } while (Math.abs(hue - 0.53855555555) < 0.11); // shift away from hue of selection mask
138
138
 
139
139
  sg.material = new MeshStandardMaterial({
140
140
  color: Color.fromHSV(hue, 0.9, 0.9).toHex()
@@ -188,11 +188,11 @@ async function main(engine) {
188
188
 
189
189
  const contact = new SurfacePoint3();
190
190
 
191
- const ray_origin = new Vector3();
192
- const ray_direction = new Vector3();
191
+ const ray = make_ray_from_viewport_position(engine, position);
192
+
193
+ const ray_origin = ray.origin;
194
+ const ray_direction = ray.direction;
193
195
 
194
- engine.graphics.normalizeViewportPoint(position, position);
195
- engine.graphics.viewportProjectionRay(position.x, position.y, ray_origin, ray_direction);
196
196
 
197
197
  highlight.destroy();
198
198
 
@@ -19,7 +19,7 @@ export function abstractJSONSerializer(source, serializers, classNames, construc
19
19
  const Klass = source.constructor;
20
20
  let typeName = classNames.get(Klass);
21
21
 
22
- if (typeName === undefined) {
22
+ if (typeName === undefined && Klass.hasOwnProperty("typeName")) {
23
23
  // try fallback to "typeName" field on constructor
24
24
  typeName = Klass.typeName;
25
25
  }
@@ -1065,10 +1065,35 @@ export class EntityComponentDataset {
1065
1065
  }
1066
1066
 
1067
1067
  /**
1068
- *
1068
+ * same as getComponent when component exists, if component is not associated with the entity, callback will be invoked once when it is added.
1069
+ * @param {Number} entityId
1070
+ * @param {Class} componentClass
1071
+ * @param {function} callback
1072
+ * @param {*} [thisArg]
1073
+ */
1074
+ getComponentAsync (entityId, componentClass, callback, thisArg) {
1075
+ const component = this.getComponent(entityId, componentClass);
1076
+
1077
+ const handler = (options) => {
1078
+ if (options.klass === componentClass) {
1079
+ this.removeEntityEventListener(entityId, EventType.ComponentAdded, handler);
1080
+ callback.call(thisArg, options.instance);
1081
+ }
1082
+ }
1083
+
1084
+ if (component === undefined) {
1085
+ this.addEntityEventListener(entityId, EventType.ComponentAdded, handler);
1086
+ } else {
1087
+ callback.call(thisArg, component);
1088
+ }
1089
+ };
1090
+
1091
+ /**
1092
+ * Performs traversal on a subset of entities which have specified components.
1093
+ * @example traverseEntities([Transform,Renderable,Tag],function(transform, renderable, tag, entity){ ... }, this);
1069
1094
  * @param {Array} classes
1070
1095
  * @param {function:boolean?} visitor Visitor can return optional "false" to terminate traversal earlier
1071
- * @param {object} [thisArg]
1096
+ * @param {object} [thisArg] specifies context object on which callbacks are to be called, optional
1072
1097
  */
1073
1098
  traverseEntities(classes, visitor, thisArg) {
1074
1099
 
@@ -1144,7 +1169,7 @@ export class EntityComponentDataset {
1144
1169
  }
1145
1170
 
1146
1171
  /**
1147
- * does traversal on a subset of entities which have only the specified components and no others
1172
+ * Performs traversal on a subset of entities which have only the specified components and no others
1148
1173
  * @example traverseEntitiesExact([Transform,Renderable,Tag],function(transform, renderable, tag, entity){ ... }, this);
1149
1174
  * @param {Array.<class>} classes
1150
1175
  * @param {Function} visitor