@woosh/meep-engine 2.39.42 → 2.40.0

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.
@@ -85,6 +85,14 @@ export class BinaryBuffer {
85
85
  this.__growFactor = 1.1;
86
86
  }
87
87
 
88
+ /**
89
+ * Access raw underlying bytes attached to the buffer
90
+ * @return {Uint8Array}
91
+ */
92
+ get raw_bytes() {
93
+ return this.__data_uint8;
94
+ }
95
+
88
96
  /**
89
97
  * @param {ArrayBuffer} arrayBuffer
90
98
  */
@@ -551,139 +551,6 @@ export class AABB3 {
551
551
  return aabb3_intersects_line_segment(this.x0, this.y0, this.z0, this.x1, this.y1, this.z1, startX, startY, startZ, endX, endY, endZ);
552
552
  }
553
553
 
554
- /**
555
- * @source http://stackoverflow.com/questions/3106666/intersection-of-line-segment-with-axis-aligned-box-in-c-sharp
556
- * @param {number} startX
557
- * @param {number} startY
558
- * @param {number} startZ
559
- * @param {number} endX
560
- * @param {number} endY
561
- * @param {number} endZ
562
- * @returns {boolean}
563
- */
564
- intersectSegment2(startX, startY, startZ, endX, endY, endZ) {
565
- //var beginToEnd = segmentEnd - segmentBegin;
566
- const deltaX = endX - startX,
567
- deltaY = endY - startY,
568
- deltaZ = endZ - startZ;
569
- //var minToMax = new Vector3D(boxSize.X, boxSize.Y, boxSize.Z);
570
-
571
- //var min = boxCenter - minToMax / 2;
572
- //var max = boxCenter + minToMax / 2;
573
- //var beginToMin = min - segmentBegin;
574
- //var beginToMax = max - segmentBegin;
575
- //var tNear = double.MinValue;
576
- let tNear = Number.NEGATIVE_INFINITY;
577
- //var tFar = double.MaxValue;
578
- let tFar = Number.POSITIVE_INFINITY;
579
- let t1, t2, tMin, tMax;
580
- //var intersections = new List<Point3D>();
581
- //var intersections = [];
582
- let beginToMin = this.x0 - startX;
583
- let beginToMax = this.x1 - startX;
584
- if (deltaX === 0) {//parallel
585
- if (beginToMin > 0 || beginToMax < 0) {
586
- return false; //segment is not between planes
587
- }
588
- } else {
589
- t1 = beginToMin / deltaX;
590
- t2 = beginToMax / deltaX;
591
- tMin = Math.min(t1, t2);
592
- tMax = Math.max(t1, t2);
593
- if (tMin > tNear) {
594
- tNear = tMin;
595
- }
596
- if (tMax < tFar) {
597
- tFar = tMax;
598
- }
599
- if (tNear > tFar || tFar < 0) {
600
- return false;
601
- }
602
- }
603
- beginToMin = this.y0 - startY;
604
- beginToMax = this.y1 - startY;
605
- if (deltaY === 0) {//parallel
606
- if (beginToMin > 0 || beginToMax < 0) {
607
- return false; //segment is not between planes
608
- }
609
- } else {
610
- t1 = beginToMin / deltaY;
611
- t2 = beginToMax / deltaY;
612
- tMin = Math.min(t1, t2);
613
- tMax = Math.max(t1, t2);
614
- if (tMin > tNear) {
615
- tNear = tMin;
616
- }
617
- if (tMax < tFar) {
618
- tFar = tMax;
619
- }
620
- if (tNear > tFar || tFar < 0) {
621
- return false;
622
- }
623
- }
624
- beginToMin = this.z0 - startZ;
625
- beginToMax = this.z1 - startZ;
626
- if (deltaZ === 0) {//parallel
627
- if (beginToMin > 0 || beginToMax < 0) {
628
- return false; //segment is not between planes
629
- }
630
- } else {
631
- t1 = beginToMin / deltaZ;
632
- t2 = beginToMax / deltaZ;
633
- tMin = Math.min(t1, t2);
634
- tMax = Math.max(t1, t2);
635
- if (tMin > tNear) {
636
- tNear = tMin;
637
- }
638
- if (tMax < tFar) {
639
- tFar = tMax;
640
- }
641
- if (tNear > tFar || tFar < 0) {
642
- return false;
643
- }
644
- }
645
- //
646
- if (tNear >= 0 && tNear <= 1) {
647
- //intersections.push({
648
- // x: startX + deltaX * tNear,
649
- // y: startY + deltaY * tNear,
650
- // z: startZ + deltaZ * tNear
651
- //});
652
- return true;
653
- }
654
- if (tFar >= 0 && tFar <= 1) {
655
- //intersections.push({
656
- // x: startX + deltaX * tFar,
657
- // y: startY + deltaY * tFar,
658
- // z: startZ + deltaZ * tFar
659
- //});
660
- return true;
661
- }
662
- return false;
663
- //foreach (Axis axis in Enum.GetValues(typeof(Axis)))
664
- //{
665
- // if (beginToEnd.GetCoordinate(axis) == 0) // parallel
666
- // {
667
- // if (beginToMin.GetCoordinate(axis) > 0 || beginToMax.GetCoordinate(axis) < 0)
668
- // return intersections; // segment is not between planes
669
- // }
670
- // else
671
- // {
672
- // var t1 = beginToMin.GetCoordinate(axis) / beginToEnd.GetCoordinate(axis);
673
- // var t2 = beginToMax.GetCoordinate(axis) / beginToEnd.GetCoordinate(axis);
674
- // var tMin = Math.Min(t1, t2);
675
- // var tMax = Math.Max(t1, t2);
676
- // if (tMin > tNear) tNear = tMin;
677
- // if (tMax < tFar) tFar = tMax;
678
- // if (tNear > tFar || tFar < 0) return intersections;
679
- //
680
- // }
681
- //}
682
- //if (tNear >= 0 && tNear <= 1) intersections.Add(segmentBegin + beginToEnd * tNear);
683
- //if (tFar >= 0 && tFar <= 1) intersections.Add(segmentBegin + beginToEnd * tFar);
684
- //return intersections;
685
- }
686
-
687
554
  /**
688
555
  *
689
556
  * @param {THREE.Box} box
@@ -1,7 +1,7 @@
1
1
  import { fabsf } from "../../math/fabsf.js";
2
2
 
3
3
  /**
4
- *
4
+ * http://stackoverflow.com/questions/3106666/intersection-of-line-segment-with-axis-aligned-box-in-c-sharp
5
5
  * @param {number} x0
6
6
  * @param {number} y0
7
7
  * @param {number} z0
@@ -0,0 +1,9 @@
1
+ /**
2
+ *
3
+ * @type {number[]|mat4}
4
+ */
5
+ export const MATRIX_4_IDENTITY = Object.freeze([1, 0, 0, 0,
6
+ 0, 1, 0, 0,
7
+ 0, 0, 1, 0,
8
+ 0, 0, 0, 1
9
+ ]);
@@ -3,7 +3,7 @@
3
3
  * @enum {string}
4
4
  * @readonly
5
5
  */
6
- const DataType = {
6
+ export const DataType = {
7
7
  String: "string",
8
8
  Number: "number",
9
9
  Boolean: "boolean",
@@ -12,4 +12,4 @@ const DataType = {
12
12
  };
13
13
 
14
14
 
15
- export default DataType;
15
+ export default DataType;
@@ -234,6 +234,13 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
234
234
  * @type {Signal<string,Vector3>}
235
235
  */
236
236
  this.on.axisSelected = new Signal();
237
+
238
+ /**
239
+ *
240
+ * @type {boolean}
241
+ * @private
242
+ */
243
+ this.__needs_update = true;
237
244
  }
238
245
 
239
246
  link() {
@@ -262,6 +269,7 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
262
269
  */
263
270
  onMouseMove(evt) {
264
271
  this._setPointerPositionFromEvent(evt);
272
+ this.__try_update();
265
273
  }
266
274
 
267
275
  /**
@@ -271,9 +279,19 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
271
279
  */
272
280
  _setPointerPositionFromEvent(evt) {
273
281
  const v2 = new Vector2();
282
+
274
283
  readPositionFromMouseEvent(v2, evt);
275
284
 
285
+ const position_changed = (this.input_pointer_position === null || this.input_pointer_position.x !== v2.x || this.input_pointer_position.y !== v2.y);
286
+
276
287
  this.input_pointer_position = new Vector3(v2.x, v2.y, 0);
288
+
289
+
290
+ if (position_changed) {
291
+ this.__needs_update = true;
292
+ }
293
+
294
+ return position_changed;
277
295
  }
278
296
 
279
297
  /**
@@ -282,6 +300,8 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
282
300
  */
283
301
  onMouseOut(evt) {
284
302
  this.input_pointer_position = null;
303
+ this.__needs_update = true;
304
+ this.__try_update();
285
305
  }
286
306
 
287
307
  /**
@@ -289,6 +309,11 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
289
309
  * @param {MouseEvent} evt
290
310
  */
291
311
  onMouseClick(evt) {
312
+
313
+ this._setPointerPositionFromEvent(evt);
314
+
315
+ this.__try_update();
316
+
292
317
  if (this.selectedAxis !== null) {
293
318
  this.on.axisSelected.send2(
294
319
  this.selectedAxis.axis,
@@ -326,7 +351,17 @@ export class BlenderCameraOrientationGizmo extends CanvasView {
326
351
  ctx.closePath();
327
352
  }
328
353
 
354
+ __try_update() {
355
+ if (!this.__needs_update) {
356
+ return;
357
+ }
358
+ this.update();
359
+ }
360
+
329
361
  update() {
362
+ // reset flag
363
+ this.__needs_update = false;
364
+
330
365
  this.clear();
331
366
 
332
367
  // Calculate the rotation matrix from the camera
@@ -28,10 +28,11 @@ import SelectionClearAction from "../actions/concrete/SelectionClearAction.js";
28
28
  import EntityCreateAction from "../actions/concrete/EntityCreateAction.js";
29
29
  import ComponentAddAction from "../actions/concrete/ComponentAddAction.js";
30
30
  import SelectionAddAction from "../actions/concrete/SelectionAddAction.js";
31
- import { noop, passThrough } from "../../core/function/Functions.js";
31
+ import { passThrough } from "../../core/function/Functions.js";
32
32
  import { ProcessState } from "../../core/process/ProcessState.js";
33
33
  import { MeshEvents } from "../../engine/graphics/ecs/mesh/MeshEvents.js";
34
34
  import { obtainTerrain } from "../../engine/ecs/terrain/util/obtainTerrain.js";
35
+ import { SurfacePoint3 } from "../../core/geom/3d/SurfacePoint3.js";
35
36
 
36
37
  class ViewManager extends View {
37
38
  constructor() {
@@ -204,35 +205,37 @@ function prepareMeshLibrary(editor) {
204
205
  const entityCreateAction = new EntityCreateAction();
205
206
  actions.do(entityCreateAction);
206
207
 
207
- terrain.raycast(source, direction, function (hit, normal, geometry) {
208
- function handleMeshSetEvent() {
209
- const bb = mesh.boundingBox;
208
+ const sp3 = new SurfacePoint3();
210
209
 
211
- const c0 = new Vector3(bb.x0, bb.y0, bb.z0);
212
- const c1 = new Vector3(bb.x1, bb.y1, bb.z1);
210
+ const hit_found = terrain.raycastFirstSync(sp3, source.x, source.y, source.z, direction.x, direction.y, direction.z);
213
211
 
214
- const diagonal = c0.distanceTo(c1);
212
+ function handleMeshSetEvent() {
213
+ const bb = mesh.boundingBox;
215
214
 
216
- const offset = direction.clone().multiplyScalar(diagonal);
215
+ const c0 = new Vector3(bb.x0, bb.y0, bb.z0);
216
+ const c1 = new Vector3(bb.x1, bb.y1, bb.z1);
217
217
 
218
- transform.position.add(offset);
218
+ const diagonal = c0.distanceTo(c1);
219
219
 
220
- //remove listener
221
- ecd.removeEntityEventListener(entityCreateAction.entity, MeshEvents.DataSet, handleMeshSetEvent);
222
- }
220
+ const offset = direction.clone().multiplyScalar(diagonal);
223
221
 
224
- if (hit !== null) {
225
- //got a terrain ray hit, set world placement position to that point
226
- worldPosition.copy(hit);
227
- } else {
228
- //set position to the source of the ray pick if there's nothing else available
229
- worldPosition.copy(source);
222
+ transform.position.add(offset);
230
223
 
224
+ //remove listener
225
+ ecd.removeEntityEventListener(entityCreateAction.entity, MeshEvents.DataSet, handleMeshSetEvent);
226
+ }
231
227
 
232
- //wait for mesh to load
233
- ecd.addEntityEventListener(entityCreateAction.entity, MeshEvents.DataSet, handleMeshSetEvent);
234
- }
235
- }, noop);
228
+ if (hit_found) {
229
+ //got a terrain ray hit, set world placement position to that point
230
+ worldPosition.copy(sp3.position);
231
+ } else {
232
+ //set position to the source of the ray pick if there's nothing else available
233
+ worldPosition.copy(source);
234
+
235
+
236
+ //wait for mesh to load
237
+ ecd.addEntityEventListener(entityCreateAction.entity, MeshEvents.DataSet, handleMeshSetEvent);
238
+ }
236
239
 
237
240
  transform.position.copy(worldPosition);
238
241
 
@@ -1,6 +1,8 @@
1
1
  import View from "../../../../../view/View.js";
2
2
  import Vector1 from "../../../../../core/geom/Vector1.js";
3
3
 
4
+ const DEFAULT_VALUE = 0;
5
+
4
6
  export class NumberController extends View {
5
7
  /**
6
8
  *
@@ -32,6 +34,22 @@ export class NumberController extends View {
32
34
 
33
35
  let lockForward = false;
34
36
 
37
+ /**
38
+ *
39
+ * @param {number} num_value
40
+ * @return {string}
41
+ */
42
+ function format_value_string(num_value) {
43
+
44
+ let str = String(num_value);
45
+
46
+ if (Math.abs(num_value) > 0 && Math.abs(num_value % 1).toString().length > (figures + 2)) {
47
+ str = num_value.toFixed(figures);
48
+ }
49
+
50
+ return str;
51
+ }
52
+
35
53
  function data2view() {
36
54
 
37
55
  if (lockForward) {
@@ -40,26 +58,37 @@ export class NumberController extends View {
40
58
 
41
59
  const num_value = _value.getValue();
42
60
 
43
- let str = num_value;
44
-
45
- if (Math.abs(num_value) > 0 && Math.abs(num_value % 1).toString().length > (figures + 2)) {
46
- str = num_value.toFixed(figures);
47
- }
48
-
49
- el.value = str;
61
+ el.value = format_value_string(num_value);
50
62
 
51
63
  }
52
64
 
53
65
  function view2data() {
54
66
  lockForward = true;
55
67
 
56
- _value.set(parseFloat(el.value));
68
+ const value = parseFloat(el.value);
69
+
70
+ if (Number.isNaN(value)) {
71
+ _value.set(DEFAULT_VALUE);
72
+ } else {
73
+ _value.set(value);
74
+ }
57
75
 
58
76
  lockForward = false;
59
77
  }
60
78
 
79
+ /**
80
+ * Input field stops being edited
81
+ */
82
+ function handle_blur() {
83
+ if (Number.isNaN(parseFloat(el.value))) {
84
+ // input in the field is invalid, replace with the value held in the data container
85
+ el.value = format_value_string(_value.getValue());
86
+ }
87
+ }
88
+
61
89
  _value.process(data2view);
62
90
 
63
91
  el.addEventListener('input', view2data);
92
+ el.addEventListener('blur', handle_blur);
64
93
  }
65
94
  }
@@ -9,7 +9,6 @@ import Vector3 from "../core/geom/Vector3.js";
9
9
  import Terrain from "./ecs/terrain/ecs/Terrain.js";
10
10
  import Vector2 from "../core/geom/Vector2.js";
11
11
  import Water from "./graphics/ecs/water/Water.js";
12
- import { loadGameClassRegistry } from "../../model/game/GameClassRegistry.js";
13
12
  import { WebEnginePlatform } from "./platform/WebEnginePlatform.js";
14
13
  import Tag from "./ecs/components/Tag.js";
15
14
  import { SerializationMetadata } from "./ecs/components/SerializationMetadata.js";
@@ -116,8 +115,6 @@ export class EngineHarness {
116
115
 
117
116
  await setLocale(engine);
118
117
 
119
- loadGameClassRegistry(engine.classRegistry);
120
-
121
118
  engine.sceneManager.create("test");
122
119
  engine.sceneManager.set("test");
123
120
 
@@ -7,7 +7,14 @@ import { PNG } from './PNG.js';
7
7
  import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
8
8
  import { isArrayEqualStrict } from "../../../../../core/collection/array/isArrayEqualStrict.js";
9
9
  import { PNG_HEADER_BYTES } from "./PNG_HEADER_BYTES.js";
10
+ import { crc } from "./crc.js";
10
11
 
12
+ /**
13
+ *
14
+ * @param {Uint8Array} buffer
15
+ * @param {number} offset
16
+ * @return {number}
17
+ */
11
18
  function readUInt32(buffer, offset) {
12
19
  return (buffer[offset] << 24) +
13
20
  (buffer[offset + 1] << 16) +
@@ -16,6 +23,12 @@ function readUInt32(buffer, offset) {
16
23
  }
17
24
 
18
25
 
26
+ /**
27
+ *
28
+ * @param {Uint8Array} buffer
29
+ * @param {number} offset
30
+ * @return {number}
31
+ */
19
32
  function readUInt8(buffer, offset) {
20
33
  return buffer[offset];
21
34
  }
@@ -37,8 +50,19 @@ export function PNGReader(bytes) {
37
50
 
38
51
  this.buffer = new BinaryBuffer();
39
52
  this.buffer.fromArrayBuffer(bytes);
53
+
54
+ /**
55
+ * Whether CRC should be performed or not
56
+ * @type {boolean}
57
+ */
58
+ this.crc_enabled = false;
40
59
  }
41
60
 
61
+ /**
62
+ *
63
+ * @param {number} length
64
+ * @return {Uint8Array}
65
+ */
42
66
  PNGReader.prototype.readBytes = function (length) {
43
67
  const result = new Uint8Array(length);
44
68
 
@@ -91,16 +115,31 @@ PNGReader.prototype.decodeChunk = function () {
91
115
  throw new Error('Bad chunk length ' + (0xFFFFFFFF & length));
92
116
  }
93
117
 
118
+
119
+ const chunk_address = buffer.position;
120
+
94
121
  const type = buffer.readASCIICharacters(4);
95
122
 
96
123
  /**
97
124
  *
98
125
  * @type {Uint8Array}
99
126
  */
100
- var chunk = this.readBytes(length);
127
+ const chunk = this.readBytes(length);
101
128
 
102
129
  // checksum
103
- var crc = buffer.readUint32();
130
+ const crc_expected = buffer.readUint32();
131
+
132
+ if (this.crc_enabled) {
133
+
134
+ // NOTE: CRC includes the "type" tag, not just the chunk bytes
135
+ const crc_actual = crc(buffer.raw_bytes, chunk_address, length + 4);
136
+
137
+ if (crc_actual !== crc_expected) {
138
+ console.warn(`CRC (Cyclic Redundancy Check) error at block '${type}' at address ${chunk_address}`);
139
+ }
140
+
141
+ }
142
+
104
143
 
105
144
  switch (type) {
106
145
  case 'IHDR':
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Ported from C source at https://www.w3.org/TR/PNG-CRCAppendix.html
3
+ * See also ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-V42] for a formal specification
4
+ */
5
+
6
+ /**
7
+ *
8
+ * @type {Uint32Array}
9
+ */
10
+ const crc_table = new Uint32Array(256);
11
+
12
+ // Precompute checksum table
13
+ for (let n = 0; n < 256; n++) {
14
+ let c = n;
15
+ for (let k = 0; k < 8; k++) {
16
+ if (c & 1) {
17
+ c = 0xedb88320 ^ (c >>> 1);
18
+ } else {
19
+ c = c >>> 1;
20
+ }
21
+ }
22
+ crc_table[n] = c;
23
+ }
24
+
25
+ const INITIAL = 0xffffffff;
26
+
27
+ /**
28
+ * Update a running CRC with the bytes buf[0..len-1]--the CRC
29
+ * should be initialized to all 1's, and the transmitted value
30
+ * is the 1's complement of the final running CRC (see the
31
+ * crc() routine below)).
32
+ * @param {number} crc
33
+ * @param {Uint8Array} buf
34
+ * @param {number} offset
35
+ * @param {number} len
36
+ * @return {number}
37
+ */
38
+ function update_crc(
39
+ crc,
40
+ buf,
41
+ offset,
42
+ len,
43
+ ) {
44
+ let c = crc;
45
+
46
+ const end = offset + len;
47
+
48
+ for (let n = offset; n < end; n++) {
49
+ const lookup_index = (c ^ buf[n]) & 0xff;
50
+
51
+ c = crc_table[lookup_index] ^ (c >>> 8);
52
+ }
53
+
54
+ return c;
55
+ }
56
+
57
+ /**
58
+ * Returns CRC of the bytes buf[0..len-1]
59
+ * @param {Uint8Array} buf byte buffer
60
+ * @param {number} offset
61
+ * @param {number} len how many bytes to include in checksum calculation
62
+ * @return {number}
63
+ */
64
+ export function crc(buf, offset, len) {
65
+ return (update_crc(INITIAL, buf, offset, len) ^ INITIAL) >>> 0;
66
+ }
@@ -429,7 +429,7 @@ export class VoiceSystem extends AbstractContextSystem {
429
429
  const bb = ecd.getComponent(entity, Blackboard);
430
430
 
431
431
  if (bb !== undefined) {
432
- bb.acquireNumber(`voice.line_spoken.${line_id}.count`).increment();
432
+ bb.incrementNumber(`voice.line_spoken.${line_id}.count`);
433
433
  }
434
434
 
435
435
  }